@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
@@ -1,15 +1,39 @@
1
+ import { DEFAULT_HEARTBEAT_ACK_MAX_CHARS, stripHeartbeatToken } from "../auto-reply/heartbeat.js";
1
2
  import { normalizeVerboseLevel } from "../auto-reply/thinking.js";
3
+ import { isSilentReplyText, SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js";
2
4
  import { loadConfig } from "../config/config.js";
3
5
  import { getAgentRunContext } from "../infra/agent-events.js";
4
6
  import { resolveHeartbeatVisibility } from "../infra/heartbeat-visibility.js";
7
+ import { stripInlineDirectiveTagsForDisplay } from "../utils/directive-tags.js";
5
8
  import { loadSessionEntry } from "./session-utils.js";
6
9
  import { formatForLog } from "./ws-log.js";
10
+ function resolveHeartbeatAckMaxChars() {
11
+ try {
12
+ const cfg = loadConfig();
13
+ return Math.max(0, cfg.agents?.defaults?.heartbeat?.ackMaxChars ?? DEFAULT_HEARTBEAT_ACK_MAX_CHARS);
14
+ }
15
+ catch {
16
+ return DEFAULT_HEARTBEAT_ACK_MAX_CHARS;
17
+ }
18
+ }
19
+ function resolveHeartbeatContext(runId, sourceRunId) {
20
+ const primary = getAgentRunContext(runId);
21
+ if (primary?.isHeartbeat) {
22
+ return primary;
23
+ }
24
+ if (sourceRunId && sourceRunId !== runId) {
25
+ const source = getAgentRunContext(sourceRunId);
26
+ if (source?.isHeartbeat) {
27
+ return source;
28
+ }
29
+ }
30
+ return primary;
31
+ }
7
32
  /**
8
- * Check if webchat broadcasts should be suppressed for heartbeat runs.
9
- * Returns true if the run is a heartbeat and showOk is false.
33
+ * Check if heartbeat ACK/noise should be hidden from interactive chat surfaces.
10
34
  */
11
- function shouldSuppressHeartbeatBroadcast(runId) {
12
- const runContext = getAgentRunContext(runId);
35
+ function shouldHideHeartbeatChatOutput(runId, sourceRunId) {
36
+ const runContext = resolveHeartbeatContext(runId, sourceRunId);
13
37
  if (!runContext?.isHeartbeat) {
14
38
  return false;
15
39
  }
@@ -23,6 +47,22 @@ function shouldSuppressHeartbeatBroadcast(runId) {
23
47
  return true;
24
48
  }
25
49
  }
50
+ function normalizeHeartbeatChatFinalText(params) {
51
+ if (!shouldHideHeartbeatChatOutput(params.runId, params.sourceRunId)) {
52
+ return { suppress: false, text: params.text };
53
+ }
54
+ const stripped = stripHeartbeatToken(params.text, {
55
+ mode: "heartbeat",
56
+ maxAckChars: resolveHeartbeatAckMaxChars(),
57
+ });
58
+ if (!stripped.didStrip) {
59
+ return { suppress: false, text: params.text };
60
+ }
61
+ if (stripped.shouldSkip) {
62
+ return { suppress: true, text: "" };
63
+ }
64
+ return { suppress: false, text: stripped.text };
65
+ }
26
66
  export function createChatRunRegistry() {
27
67
  const chatRunSessions = new Map();
28
68
  const add = (sessionId, entry) => {
@@ -141,8 +181,18 @@ export function createToolEventRecipientRegistry() {
141
181
  return { add, get, markFinal };
142
182
  }
143
183
  export function createAgentEventHandler({ broadcast, broadcastToConnIds, nodeSendToSession, agentRunSeq, chatRunState, resolveSessionKeyForRun, clearAgentRunContext, toolEventRecipients, }) {
144
- const emitChatDelta = (sessionKey, clientRunId, seq, text) => {
145
- chatRunState.buffers.set(clientRunId, text);
184
+ const emitChatDelta = (sessionKey, clientRunId, sourceRunId, seq, text) => {
185
+ const cleaned = stripInlineDirectiveTagsForDisplay(text).text;
186
+ if (!cleaned) {
187
+ return;
188
+ }
189
+ if (isSilentReplyText(cleaned, SILENT_REPLY_TOKEN)) {
190
+ return;
191
+ }
192
+ chatRunState.buffers.set(clientRunId, cleaned);
193
+ if (shouldHideHeartbeatChatOutput(clientRunId, sourceRunId)) {
194
+ return;
195
+ }
146
196
  const now = Date.now();
147
197
  const last = chatRunState.deltaSentAt.get(clientRunId) ?? 0;
148
198
  if (now - last < 150) {
@@ -156,18 +206,22 @@ export function createAgentEventHandler({ broadcast, broadcastToConnIds, nodeSen
156
206
  state: "delta",
157
207
  message: {
158
208
  role: "assistant",
159
- content: [{ type: "text", text }],
209
+ content: [{ type: "text", text: cleaned }],
160
210
  timestamp: now,
161
211
  },
162
212
  };
163
- // Suppress webchat broadcast for heartbeat runs when showOk is false
164
- if (!shouldSuppressHeartbeatBroadcast(clientRunId)) {
165
- broadcast("chat", payload, { dropIfSlow: true });
166
- }
213
+ broadcast("chat", payload, { dropIfSlow: true });
167
214
  nodeSendToSession(sessionKey, "chat", payload);
168
215
  };
169
- const emitChatFinal = (sessionKey, clientRunId, seq, jobState, error) => {
170
- const text = chatRunState.buffers.get(clientRunId)?.trim() ?? "";
216
+ const emitChatFinal = (sessionKey, clientRunId, sourceRunId, seq, jobState, error) => {
217
+ const bufferedText = stripInlineDirectiveTagsForDisplay(chatRunState.buffers.get(clientRunId) ?? "").text.trim();
218
+ const normalizedHeartbeatText = normalizeHeartbeatChatFinalText({
219
+ runId: clientRunId,
220
+ sourceRunId,
221
+ text: bufferedText,
222
+ });
223
+ const text = normalizedHeartbeatText.text.trim();
224
+ const shouldSuppressSilent = normalizedHeartbeatText.suppress || isSilentReplyText(text, SILENT_REPLY_TOKEN);
171
225
  chatRunState.buffers.delete(clientRunId);
172
226
  chatRunState.deltaSentAt.delete(clientRunId);
173
227
  if (jobState === "done") {
@@ -176,7 +230,7 @@ export function createAgentEventHandler({ broadcast, broadcastToConnIds, nodeSen
176
230
  sessionKey,
177
231
  seq,
178
232
  state: "final",
179
- message: text
233
+ message: text && !shouldSuppressSilent
180
234
  ? {
181
235
  role: "assistant",
182
236
  content: [{ type: "text", text }],
@@ -184,10 +238,7 @@ export function createAgentEventHandler({ broadcast, broadcastToConnIds, nodeSen
184
238
  }
185
239
  : undefined,
186
240
  };
187
- // Suppress webchat broadcast for heartbeat runs when showOk is false
188
- if (!shouldSuppressHeartbeatBroadcast(clientRunId)) {
189
- broadcast("chat", payload);
190
- }
241
+ broadcast("chat", payload);
191
242
  nodeSendToSession(sessionKey, "chat", payload);
192
243
  return;
193
244
  }
@@ -225,11 +276,14 @@ export function createAgentEventHandler({ broadcast, broadcastToConnIds, nodeSen
225
276
  };
226
277
  return (evt) => {
227
278
  const chatLink = chatRunState.registry.peek(evt.runId);
228
- const sessionKey = chatLink?.sessionKey ?? resolveSessionKeyForRun(evt.runId);
279
+ const eventSessionKey = typeof evt.sessionKey === "string" && evt.sessionKey.trim() ? evt.sessionKey : undefined;
280
+ const sessionKey = chatLink?.sessionKey ?? eventSessionKey ?? resolveSessionKeyForRun(evt.runId);
229
281
  const clientRunId = chatLink?.clientRunId ?? evt.runId;
282
+ const eventRunId = chatLink?.clientRunId ?? evt.runId;
283
+ const eventForClients = chatLink ? { ...evt, runId: eventRunId } : evt;
230
284
  const isAborted = chatRunState.abortedRuns.has(clientRunId) || chatRunState.abortedRuns.has(evt.runId);
231
285
  // Include sessionKey so Control UI can filter tool streams per session.
232
- const agentPayload = sessionKey ? { ...evt, sessionKey } : evt;
286
+ const agentPayload = sessionKey ? { ...eventForClients, sessionKey } : eventForClients;
233
287
  const last = agentRunSeq.get(evt.runId) ?? 0;
234
288
  const isToolEvent = evt.stream === "tool";
235
289
  const toolVerbose = isToolEvent ? resolveToolVerboseLevel(evt.runId, sessionKey) : "off";
@@ -239,12 +293,14 @@ export function createAgentEventHandler({ broadcast, broadcastToConnIds, nodeSen
239
293
  const data = evt.data ? { ...evt.data } : {};
240
294
  delete data.result;
241
295
  delete data.partialResult;
242
- return sessionKey ? { ...evt, sessionKey, data } : { ...evt, data };
296
+ return sessionKey
297
+ ? { ...eventForClients, sessionKey, data }
298
+ : { ...eventForClients, data };
243
299
  })()
244
300
  : agentPayload;
245
301
  if (evt.seq !== last + 1) {
246
302
  broadcast("agent", {
247
- runId: evt.runId,
303
+ runId: eventRunId,
248
304
  stream: "error",
249
305
  ts: Date.now(),
250
306
  sessionKey,
@@ -277,7 +333,7 @@ export function createAgentEventHandler({ broadcast, broadcastToConnIds, nodeSen
277
333
  nodeSendToSession(sessionKey, "agent", isToolEvent ? toolPayload : agentPayload);
278
334
  }
279
335
  if (!isAborted && evt.stream === "assistant" && typeof evt.data?.text === "string") {
280
- emitChatDelta(sessionKey, clientRunId, evt.seq, evt.data.text);
336
+ emitChatDelta(sessionKey, clientRunId, evt.runId, evt.seq, evt.data.text);
281
337
  }
282
338
  else if (!isAborted && (lifecyclePhase === "end" || lifecyclePhase === "error")) {
283
339
  if (chatLink) {
@@ -286,10 +342,10 @@ export function createAgentEventHandler({ broadcast, broadcastToConnIds, nodeSen
286
342
  clearAgentRunContext(evt.runId);
287
343
  return;
288
344
  }
289
- emitChatFinal(finished.sessionKey, finished.clientRunId, evt.seq, lifecyclePhase === "error" ? "error" : "done", evt.data?.error);
345
+ emitChatFinal(finished.sessionKey, finished.clientRunId, evt.runId, evt.seq, lifecyclePhase === "error" ? "error" : "done", evt.data?.error);
290
346
  }
291
347
  else {
292
- emitChatFinal(sessionKey, evt.runId, evt.seq, lifecyclePhase === "error" ? "error" : "done", evt.data?.error);
348
+ emitChatFinal(sessionKey, eventRunId, evt.runId, evt.seq, lifecyclePhase === "error" ? "error" : "done", evt.data?.error);
293
349
  }
294
350
  }
295
351
  else if (isAborted && (lifecyclePhase === "end" || lifecyclePhase === "error")) {
@@ -305,6 +361,8 @@ export function createAgentEventHandler({ broadcast, broadcastToConnIds, nodeSen
305
361
  if (lifecyclePhase === "end" || lifecyclePhase === "error") {
306
362
  toolEventRecipients.markFinal(evt.runId);
307
363
  clearAgentRunContext(evt.runId);
364
+ agentRunSeq.delete(evt.runId);
365
+ agentRunSeq.delete(clientRunId);
308
366
  }
309
367
  };
310
368
  }
@@ -1,11 +1,14 @@
1
- export const MAX_PAYLOAD_BYTES = 512 * 1024; // cap incoming frame size
2
- export const MAX_BUFFERED_BYTES = 1.5 * 1024 * 1024; // per-connection send buffer limit
1
+ // Keep server maxPayload aligned with gateway client maxPayload so high-res canvas snapshots
2
+ // don't get disconnected mid-invoke with "Max payload size exceeded".
3
+ export const MAX_PAYLOAD_BYTES = 25 * 1024 * 1024;
4
+ export const MAX_BUFFERED_BYTES = 50 * 1024 * 1024; // per-connection send buffer limit (2x max payload)
3
5
  const DEFAULT_MAX_CHAT_HISTORY_MESSAGES_BYTES = 6 * 1024 * 1024; // keep history responses comfortably under client WS limits
4
6
  let maxChatHistoryMessagesBytes = DEFAULT_MAX_CHAT_HISTORY_MESSAGES_BYTES;
5
7
  export const getMaxChatHistoryMessagesBytes = () => maxChatHistoryMessagesBytes;
6
8
  export const __setMaxChatHistoryMessagesBytesForTest = (value) => {
7
- if (!process.env.VITEST && process.env.NODE_ENV !== "test")
9
+ if (!process.env.VITEST && process.env.NODE_ENV !== "test") {
8
10
  return;
11
+ }
9
12
  if (value === undefined) {
10
13
  maxChatHistoryMessagesBytes = DEFAULT_MAX_CHAT_HISTORY_MESSAGES_BYTES;
11
14
  return;
@@ -16,13 +19,11 @@ export const __setMaxChatHistoryMessagesBytesForTest = (value) => {
16
19
  };
17
20
  export const DEFAULT_HANDSHAKE_TIMEOUT_MS = 10_000;
18
21
  export const getHandshakeTimeoutMs = () => {
19
- if (process.env.VITEST &&
20
- (process.env.POOLBOT_TEST_HANDSHAKE_TIMEOUT_MS ||
21
- process.env.CLAWDBOT_TEST_HANDSHAKE_TIMEOUT_MS)) {
22
- const parsed = Number(process.env.POOLBOT_TEST_HANDSHAKE_TIMEOUT_MS ||
23
- process.env.CLAWDBOT_TEST_HANDSHAKE_TIMEOUT_MS);
24
- if (Number.isFinite(parsed) && parsed > 0)
22
+ if (process.env.VITEST && process.env.POOLBOT_TEST_HANDSHAKE_TIMEOUT_MS) {
23
+ const parsed = Number(process.env.POOLBOT_TEST_HANDSHAKE_TIMEOUT_MS);
24
+ if (Number.isFinite(parsed) && parsed > 0) {
25
25
  return parsed;
26
+ }
26
27
  }
27
28
  return DEFAULT_HANDSHAKE_TIMEOUT_MS;
28
29
  };
@@ -235,6 +235,7 @@ export function buildGatewayCronService(params) {
235
235
  status: evt.status,
236
236
  error: evt.error,
237
237
  summary: evt.summary,
238
+ delivered: evt.delivered,
238
239
  sessionId: evt.sessionId,
239
240
  sessionKey: evt.sessionKey,
240
241
  runAtMs: evt.runAtMs,
@@ -5,7 +5,7 @@ import { A2UI_PATH, CANVAS_HOST_PATH, CANVAS_WS_PATH, handleA2uiHttpRequest, } f
5
5
  import { loadConfig } from "../config/config.js";
6
6
  import { safeEqualSecret } from "../security/secret-equal.js";
7
7
  import { handleSlackHttpRequest } from "../slack/http/index.js";
8
- import { authorizeGatewayConnect, isLocalDirectRequest, } from "./auth.js";
8
+ import { authorizeHttpGatewayConnect, isLocalDirectRequest, } from "./auth.js";
9
9
  import { CANVAS_CAPABILITY_TTL_MS, normalizeCanvasScopedUrl } from "./canvas-capability.js";
10
10
  import { handleControlUiAvatarRequest, handleControlUiHttpRequest, } from "./control-ui.js";
11
11
  import { applyHookMappings } from "./hooks-mapping.js";
@@ -58,21 +58,22 @@ function hasAuthorizedNodeWsClientForCanvasCapability(clients, capability) {
58
58
  return false;
59
59
  }
60
60
  async function authorizeCanvasRequest(params) {
61
- const { req, auth, trustedProxies, clients, canvasCapability, malformedScopedPath, rateLimiter } = params;
61
+ const { req, auth, trustedProxies, allowRealIpFallback, clients, canvasCapability, malformedScopedPath, rateLimiter, } = params;
62
62
  if (malformedScopedPath) {
63
63
  return { ok: false, reason: "unauthorized" };
64
64
  }
65
- if (isLocalDirectRequest(req, trustedProxies)) {
65
+ if (isLocalDirectRequest(req, trustedProxies, allowRealIpFallback)) {
66
66
  return { ok: true };
67
67
  }
68
68
  let lastAuthFailure = null;
69
69
  const token = getBearerToken(req);
70
70
  if (token) {
71
- const authResult = await authorizeGatewayConnect({
71
+ const authResult = await authorizeHttpGatewayConnect({
72
72
  auth: { ...auth, allowTailscale: false },
73
73
  connectAuth: { token, password: token },
74
74
  req,
75
75
  trustedProxies,
76
+ allowRealIpFallback,
76
77
  rateLimiter,
77
78
  });
78
79
  if (authResult.ok) {
@@ -169,10 +170,10 @@ export function createHooksRequestHandler(opts) {
169
170
  if (url.searchParams.has("token")) {
170
171
  res.statusCode = 400;
171
172
  res.setHeader("Content-Type", "text/plain; charset=utf-8");
172
- res.end("Hook token must be provided via Authorization: Bearer <token> or X-PoolBot-Token header (query parameters are not allowed).");
173
+ res.end("Hook token must be provided via Authorization: Bearer <token> or X-Pool Bot-Token header (query parameters are not allowed).");
173
174
  return true;
174
175
  }
175
- const token = extractHookToken(req).token;
176
+ const { token } = extractHookToken(req);
176
177
  const clientKey = resolveHookClientKey(req);
177
178
  if (!safeEqualSecret(token, hooksConfig.token)) {
178
179
  const throttle = recordHookAuthFailure(clientKey, Date.now());
@@ -346,6 +347,7 @@ export function createGatewayHttpServer(opts) {
346
347
  try {
347
348
  const configSnapshot = loadConfig();
348
349
  const trustedProxies = configSnapshot.gateway?.trustedProxies ?? [];
350
+ const allowRealIpFallback = configSnapshot.gateway?.allowRealIpFallback === true;
349
351
  const scopedCanvas = normalizeCanvasScopedUrl(req.url ?? "/");
350
352
  if (scopedCanvas.malformedScopedPath) {
351
353
  sendGatewayAuthFailure(res, { ok: false, reason: "unauthorized" });
@@ -361,6 +363,7 @@ export function createGatewayHttpServer(opts) {
361
363
  if (await handleToolsInvokeHttpRequest(req, res, {
362
364
  auth: resolvedAuth,
363
365
  trustedProxies,
366
+ allowRealIpFallback,
364
367
  rateLimiter,
365
368
  })) {
366
369
  return;
@@ -374,11 +377,12 @@ export function createGatewayHttpServer(opts) {
374
377
  // their own auth when exposing sensitive functionality.
375
378
  if (requestPath.startsWith("/api/channels/")) {
376
379
  const token = getBearerToken(req);
377
- const authResult = await authorizeGatewayConnect({
380
+ const authResult = await authorizeHttpGatewayConnect({
378
381
  auth: resolvedAuth,
379
382
  connectAuth: token ? { token, password: token } : null,
380
383
  req,
381
384
  trustedProxies,
385
+ allowRealIpFallback,
382
386
  rateLimiter,
383
387
  });
384
388
  if (!authResult.ok) {
@@ -395,6 +399,7 @@ export function createGatewayHttpServer(opts) {
395
399
  auth: resolvedAuth,
396
400
  config: openResponsesConfig,
397
401
  trustedProxies,
402
+ allowRealIpFallback,
398
403
  rateLimiter,
399
404
  })) {
400
405
  return;
@@ -404,6 +409,7 @@ export function createGatewayHttpServer(opts) {
404
409
  if (await handleOpenAiHttpRequest(req, res, {
405
410
  auth: resolvedAuth,
406
411
  trustedProxies,
412
+ allowRealIpFallback,
407
413
  rateLimiter,
408
414
  })) {
409
415
  return;
@@ -415,6 +421,7 @@ export function createGatewayHttpServer(opts) {
415
421
  req,
416
422
  auth: resolvedAuth,
417
423
  trustedProxies,
424
+ allowRealIpFallback,
418
425
  clients,
419
426
  canvasCapability: scopedCanvas.capability,
420
427
  malformedScopedPath: scopedCanvas.malformedScopedPath,
@@ -477,10 +484,12 @@ export function attachGatewayUpgradeHandler(opts) {
477
484
  if (url.pathname === CANVAS_WS_PATH) {
478
485
  const configSnapshot = loadConfig();
479
486
  const trustedProxies = configSnapshot.gateway?.trustedProxies ?? [];
487
+ const allowRealIpFallback = configSnapshot.gateway?.allowRealIpFallback === true;
480
488
  const ok = await authorizeCanvasRequest({
481
489
  req,
482
490
  auth: resolvedAuth,
483
491
  trustedProxies,
492
+ allowRealIpFallback,
484
493
  clients,
485
494
  canvasCapability: scopedCanvas.capability,
486
495
  malformedScopedPath: scopedCanvas.malformedScopedPath,
@@ -1,7 +1,7 @@
1
1
  import { abortChatRunById } from "./chat-abort.js";
2
- import { setBroadcastHealthUpdate } from "./server/health-state.js";
3
2
  import { DEDUPE_MAX, DEDUPE_TTL_MS, HEALTH_REFRESH_INTERVAL_MS, TICK_INTERVAL_MS, } from "./server-constants.js";
4
3
  import { formatError } from "./server-utils.js";
4
+ import { setBroadcastHealthUpdate } from "./server/health-state.js";
5
5
  export function startGatewayMaintenanceTimers(params) {
6
6
  setBroadcastHealthUpdate((snap) => {
7
7
  params.broadcast("health", snap, {
@@ -30,20 +30,34 @@ export function startGatewayMaintenanceTimers(params) {
30
30
  .catch((err) => params.logHealth.error(`initial refresh failed: ${formatError(err)}`));
31
31
  // dedupe cache cleanup
32
32
  const dedupeCleanup = setInterval(() => {
33
+ const AGENT_RUN_SEQ_MAX = 10_000;
33
34
  const now = Date.now();
34
35
  for (const [k, v] of params.dedupe) {
35
- if (now - v.ts > DEDUPE_TTL_MS)
36
+ if (now - v.ts > DEDUPE_TTL_MS) {
36
37
  params.dedupe.delete(k);
38
+ }
37
39
  }
38
40
  if (params.dedupe.size > DEDUPE_MAX) {
39
- const entries = [...params.dedupe.entries()].sort((a, b) => a[1].ts - b[1].ts);
41
+ const entries = [...params.dedupe.entries()].toSorted((a, b) => a[1].ts - b[1].ts);
40
42
  for (let i = 0; i < params.dedupe.size - DEDUPE_MAX; i++) {
41
43
  params.dedupe.delete(entries[i][0]);
42
44
  }
43
45
  }
46
+ if (params.agentRunSeq.size > AGENT_RUN_SEQ_MAX) {
47
+ const excess = params.agentRunSeq.size - AGENT_RUN_SEQ_MAX;
48
+ let removed = 0;
49
+ for (const runId of params.agentRunSeq.keys()) {
50
+ params.agentRunSeq.delete(runId);
51
+ removed += 1;
52
+ if (removed >= excess) {
53
+ break;
54
+ }
55
+ }
56
+ }
44
57
  for (const [runId, entry] of params.chatAbortControllers) {
45
- if (now <= entry.expiresAtMs)
58
+ if (now <= entry.expiresAtMs) {
46
59
  continue;
60
+ }
47
61
  abortChatRunById({
48
62
  chatAbortControllers: params.chatAbortControllers,
49
63
  chatRunBuffers: params.chatRunBuffers,
@@ -57,8 +71,9 @@ export function startGatewayMaintenanceTimers(params) {
57
71
  }
58
72
  const ABORTED_RUN_TTL_MS = 60 * 60_000;
59
73
  for (const [runId, abortedAt] of params.chatRunState.abortedRuns) {
60
- if (now - abortedAt <= ABORTED_RUN_TTL_MS)
74
+ if (now - abortedAt <= ABORTED_RUN_TTL_MS) {
61
75
  continue;
76
+ }
62
77
  params.chatRunState.abortedRuns.delete(runId);
63
78
  params.chatRunBuffers.delete(runId);
64
79
  params.chatDeltaSentAt.delete(runId);
@@ -9,6 +9,7 @@ import { createReplyDispatcher } from "../../auto-reply/reply/reply-dispatcher.j
9
9
  import { createReplyPrefixOptions } from "../../channels/reply-prefix.js";
10
10
  import { resolveSessionFilePath } from "../../config/sessions.js";
11
11
  import { resolveSendPolicy } from "../../sessions/send-policy.js";
12
+ import { stripInlineDirectiveTagsForDisplay } from "../../utils/directive-tags.js";
12
13
  import { INTERNAL_MESSAGE_CHANNEL } from "../../utils/message-channel.js";
13
14
  import { abortChatRunById, abortChatRunsForSessionKey, isChatStopCommandText, resolveChatRunExpiresAtMs, } from "../chat-abort.js";
14
15
  import { parseMessageWithAttachments } from "../chat-attachments.js";
@@ -57,9 +58,10 @@ function sanitizeChatHistoryContentBlock(block) {
57
58
  const entry = { ...block };
58
59
  let changed = false;
59
60
  if (typeof entry.text === "string") {
60
- const res = truncateChatHistoryText(entry.text);
61
+ const stripped = stripInlineDirectiveTagsForDisplay(entry.text);
62
+ const res = truncateChatHistoryText(stripped.text);
61
63
  entry.text = res.text;
62
- changed ||= res.truncated;
64
+ changed ||= stripped.changed || res.truncated;
63
65
  }
64
66
  if (typeof entry.partialJson === "string") {
65
67
  const res = truncateChatHistoryText(entry.partialJson);
@@ -109,9 +111,10 @@ function sanitizeChatHistoryMessage(message) {
109
111
  changed = true;
110
112
  }
111
113
  if (typeof entry.content === "string") {
112
- const res = truncateChatHistoryText(entry.content);
114
+ const stripped = stripInlineDirectiveTagsForDisplay(entry.content);
115
+ const res = truncateChatHistoryText(stripped.text);
113
116
  entry.content = res.text;
114
- changed ||= res.truncated;
117
+ changed ||= stripped.changed || res.truncated;
115
118
  }
116
119
  else if (Array.isArray(entry.content)) {
117
120
  const updated = entry.content.map((block) => sanitizeChatHistoryContentBlock(block));
@@ -121,9 +124,10 @@ function sanitizeChatHistoryMessage(message) {
121
124
  }
122
125
  }
123
126
  if (typeof entry.text === "string") {
124
- const res = truncateChatHistoryText(entry.text);
127
+ const stripped = stripInlineDirectiveTagsForDisplay(entry.text);
128
+ const res = truncateChatHistoryText(stripped.text);
125
129
  entry.text = res.text;
126
- changed ||= res.truncated;
130
+ changed ||= stripped.changed || res.truncated;
127
131
  }
128
132
  return { message: changed ? entry : message, changed };
129
133
  }
@@ -233,16 +233,15 @@ export const configHandlers = {
233
233
  note,
234
234
  });
235
235
  const sentinelPath = await tryWriteRestartSentinelPayload(payload);
236
- const audit = {
237
- actor: actor.actor,
238
- deviceId: actor.deviceId,
239
- clientIp: actor.clientIp,
240
- changedPaths,
241
- };
242
236
  const restart = scheduleGatewaySigusr1Restart({
243
237
  delayMs: restartDelayMs,
244
238
  reason: "config.patch",
245
- audit,
239
+ audit: {
240
+ actor: actor.actor,
241
+ deviceId: actor.deviceId,
242
+ clientIp: actor.clientIp,
243
+ changedPaths,
244
+ },
246
245
  });
247
246
  if (restart.coalesced) {
248
247
  context?.logGateway?.warn(`config.patch restart coalesced ${formatControlPlaneActor(actor)} delayMs=${restart.delayMs}`);
@@ -284,16 +283,15 @@ export const configHandlers = {
284
283
  note,
285
284
  });
286
285
  const sentinelPath = await tryWriteRestartSentinelPayload(payload);
287
- const audit = {
288
- actor: actor.actor,
289
- deviceId: actor.deviceId,
290
- clientIp: actor.clientIp,
291
- changedPaths,
292
- };
293
286
  const restart = scheduleGatewaySigusr1Restart({
294
287
  delayMs: restartDelayMs,
295
288
  reason: "config.apply",
296
- audit,
289
+ audit: {
290
+ actor: actor.actor,
291
+ deviceId: actor.deviceId,
292
+ clientIp: actor.clientIp,
293
+ changedPaths,
294
+ },
297
295
  });
298
296
  if (restart.coalesced) {
299
297
  context?.logGateway?.warn(`config.apply restart coalesced ${formatControlPlaneActor(actor)} delayMs=${restart.delayMs}`);
@@ -1,7 +1,7 @@
1
- import { approveDevicePairing, listDevicePairing, rejectDevicePairing, revokeDeviceToken, rotateDeviceToken, summarizeDeviceTokens, } from "../../infra/device-pairing.js";
2
- import { ErrorCodes, errorShape, formatValidationErrors, validateDevicePairApproveParams, validateDevicePairListParams, validateDevicePairRejectParams, validateDeviceTokenRevokeParams, validateDeviceTokenRotateParams, } from "../protocol/index.js";
1
+ import { approveDevicePairing, listDevicePairing, removePairedDevice, rejectDevicePairing, revokeDeviceToken, rotateDeviceToken, summarizeDeviceTokens, } from "../../infra/device-pairing.js";
2
+ import { ErrorCodes, errorShape, formatValidationErrors, validateDevicePairApproveParams, validateDevicePairListParams, validateDevicePairRemoveParams, validateDevicePairRejectParams, validateDeviceTokenRevokeParams, validateDeviceTokenRotateParams, } from "../protocol/index.js";
3
3
  function redactPairedDevice(device) {
4
- const { tokens, ...rest } = device;
4
+ const { tokens, approvedScopes: _approvedScopes, ...rest } = device;
5
5
  return {
6
6
  ...rest,
7
7
  tokens: summarizeDeviceTokens(tokens),
@@ -58,6 +58,20 @@ export const deviceHandlers = {
58
58
  }, { dropIfSlow: true });
59
59
  respond(true, rejected, undefined);
60
60
  },
61
+ "device.pair.remove": async ({ params, respond, context }) => {
62
+ if (!validateDevicePairRemoveParams(params)) {
63
+ respond(false, undefined, errorShape(ErrorCodes.INVALID_REQUEST, `invalid device.pair.remove params: ${formatValidationErrors(validateDevicePairRemoveParams.errors)}`));
64
+ return;
65
+ }
66
+ const { deviceId } = params;
67
+ const removed = await removePairedDevice(deviceId);
68
+ if (!removed) {
69
+ respond(false, undefined, errorShape(ErrorCodes.INVALID_REQUEST, "unknown deviceId"));
70
+ return;
71
+ }
72
+ context.logGateway.info(`device pairing removed device=${removed.deviceId}`);
73
+ respond(true, removed, undefined);
74
+ },
61
75
  "device.token.rotate": async ({ params, respond, context }) => {
62
76
  if (!validateDeviceTokenRotateParams(params)) {
63
77
  respond(false, undefined, errorShape(ErrorCodes.INVALID_REQUEST, `invalid device.token.rotate params: ${formatValidationErrors(validateDeviceTokenRotateParams.errors)}`));
@@ -1,3 +1,6 @@
1
+ import { DEFAULT_PROVIDER } from "../../agents/defaults.js";
2
+ import { buildAllowedModelSet } from "../../agents/model-selection.js";
3
+ import { loadConfig } from "../../config/config.js";
1
4
  import { ErrorCodes, errorShape, formatValidationErrors, validateModelsListParams, } from "../protocol/index.js";
2
5
  export const modelsHandlers = {
3
6
  "models.list": async ({ params, respond, context }) => {
@@ -6,7 +9,14 @@ export const modelsHandlers = {
6
9
  return;
7
10
  }
8
11
  try {
9
- const models = await context.loadGatewayModelCatalog();
12
+ const catalog = await context.loadGatewayModelCatalog();
13
+ const cfg = loadConfig();
14
+ const { allowedCatalog } = buildAllowedModelSet({
15
+ cfg,
16
+ catalog,
17
+ defaultProvider: DEFAULT_PROVIDER,
18
+ });
19
+ const models = allowedCatalog.length > 0 ? allowedCatalog : catalog;
10
20
  respond(true, { models }, undefined);
11
21
  }
12
22
  catch (err) {