@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,9 +1,9 @@
1
+ import { clearSessionAuthProfileOverride } from "../../agents/auth-profiles/session-override.js";
1
2
  import { lookupContextTokens } from "../../agents/context.js";
2
3
  import { DEFAULT_CONTEXT_TOKENS } from "../../agents/defaults.js";
3
4
  import { loadModelCatalog } from "../../agents/model-catalog.js";
4
5
  import { buildAllowedModelSet, modelKey, normalizeProviderId, resolveModelRefFromString, resolveThinkingDefault, } from "../../agents/model-selection.js";
5
6
  import { updateSessionStore } from "../../config/sessions.js";
6
- import { clearSessionAuthProfileOverride } from "../../agents/auth-profiles/session-override.js";
7
7
  import { applyModelOverrideToSessionEntry } from "../../sessions/model-overrides.js";
8
8
  import { resolveThreadParentSessionKey } from "../../sessions/session-key-utils.js";
9
9
  const FUZZY_VARIANT_TOKENS = [
@@ -18,14 +18,17 @@ const FUZZY_VARIANT_TOKENS = [
18
18
  "nano",
19
19
  ];
20
20
  function boundedLevenshteinDistance(a, b, maxDistance) {
21
- if (a === b)
21
+ if (a === b) {
22
22
  return 0;
23
- if (!a || !b)
23
+ }
24
+ if (!a || !b) {
24
25
  return null;
26
+ }
25
27
  const aLen = a.length;
26
28
  const bLen = b.length;
27
- if (Math.abs(aLen - bLen) > maxDistance)
29
+ if (Math.abs(aLen - bLen) > maxDistance) {
28
30
  return null;
31
+ }
29
32
  // Standard DP with early exit. O(maxDistance * minLen) in common cases.
30
33
  const prev = Array.from({ length: bLen + 1 }, (_, idx) => idx);
31
34
  const curr = Array.from({ length: bLen + 1 }, () => 0);
@@ -36,49 +39,59 @@ function boundedLevenshteinDistance(a, b, maxDistance) {
36
39
  for (let j = 1; j <= bLen; j++) {
37
40
  const cost = aChar === b.charCodeAt(j - 1) ? 0 : 1;
38
41
  curr[j] = Math.min(prev[j] + 1, curr[j - 1] + 1, prev[j - 1] + cost);
39
- if (curr[j] < rowMin)
42
+ if (curr[j] < rowMin) {
40
43
  rowMin = curr[j];
44
+ }
41
45
  }
42
- if (rowMin > maxDistance)
46
+ if (rowMin > maxDistance) {
43
47
  return null;
44
- for (let j = 0; j <= bLen; j++)
48
+ }
49
+ for (let j = 0; j <= bLen; j++) {
45
50
  prev[j] = curr[j] ?? 0;
51
+ }
46
52
  }
47
53
  const dist = prev[bLen] ?? null;
48
- if (dist == null || dist > maxDistance)
54
+ if (dist == null || dist > maxDistance) {
49
55
  return null;
56
+ }
50
57
  return dist;
51
58
  }
52
59
  function resolveModelOverrideFromEntry(entry) {
53
60
  const model = entry?.modelOverride?.trim();
54
- if (!model)
61
+ if (!model) {
55
62
  return null;
63
+ }
56
64
  const provider = entry?.providerOverride?.trim() || undefined;
57
65
  return { provider, model };
58
66
  }
59
67
  function resolveParentSessionKeyCandidate(params) {
60
68
  const explicit = params.parentSessionKey?.trim();
61
- if (explicit && explicit !== params.sessionKey)
69
+ if (explicit && explicit !== params.sessionKey) {
62
70
  return explicit;
71
+ }
63
72
  const derived = resolveThreadParentSessionKey(params.sessionKey);
64
- if (derived && derived !== params.sessionKey)
73
+ if (derived && derived !== params.sessionKey) {
65
74
  return derived;
75
+ }
66
76
  return null;
67
77
  }
68
78
  export function resolveStoredModelOverride(params) {
69
79
  const direct = resolveModelOverrideFromEntry(params.sessionEntry);
70
- if (direct)
80
+ if (direct) {
71
81
  return { ...direct, source: "session" };
82
+ }
72
83
  const parentKey = resolveParentSessionKeyCandidate({
73
84
  sessionKey: params.sessionKey,
74
85
  parentSessionKey: params.parentSessionKey,
75
86
  });
76
- if (!parentKey || !params.sessionStore)
87
+ if (!parentKey || !params.sessionStore) {
77
88
  return null;
89
+ }
78
90
  const parentEntry = params.sessionStore[parentKey];
79
91
  const parentOverride = resolveModelOverrideFromEntry(parentEntry);
80
- if (!parentOverride)
92
+ if (!parentOverride) {
81
93
  return null;
94
+ }
82
95
  return { ...parentOverride, source: "parent" };
83
96
  }
84
97
  function scoreFuzzyMatch(params) {
@@ -90,15 +103,19 @@ function scoreFuzzyMatch(params) {
90
103
  const haystack = `${providerLower}/${modelLower}`;
91
104
  const key = modelKey(provider, model);
92
105
  const scoreFragment = (value, weights) => {
93
- if (!fragment)
106
+ if (!fragment) {
94
107
  return 0;
108
+ }
95
109
  let score = 0;
96
- if (value === fragment)
110
+ if (value === fragment) {
97
111
  score = Math.max(score, weights.exact);
98
- if (value.startsWith(fragment))
112
+ }
113
+ if (value.startsWith(fragment)) {
99
114
  score = Math.max(score, weights.starts);
100
- if (value.includes(fragment))
115
+ }
116
+ if (value.includes(fragment)) {
101
117
  score = Math.max(score, weights.includes);
118
+ }
102
119
  return score;
103
120
  };
104
121
  let score = 0;
@@ -138,15 +155,18 @@ function scoreFuzzyMatch(params) {
138
155
  score -= variantCount * 30;
139
156
  }
140
157
  else if (fragmentVariants.length > 0) {
141
- if (variantMatchCount > 0)
158
+ if (variantMatchCount > 0) {
142
159
  score += variantMatchCount * 40;
143
- if (variantMatchCount === 0)
160
+ }
161
+ if (variantMatchCount === 0) {
144
162
  score -= 20;
163
+ }
145
164
  }
146
165
  const defaultProvider = normalizeProviderId(params.defaultProvider);
147
166
  const isDefault = provider === defaultProvider && model === params.defaultModel;
148
- if (isDefault)
167
+ if (isDefault) {
149
168
  score += 20;
169
+ }
150
170
  return {
151
171
  score,
152
172
  isDefault,
@@ -212,7 +232,11 @@ export async function createModelSelectionState(params) {
212
232
  sessionKey,
213
233
  parentSessionKey,
214
234
  });
215
- if (storedOverride?.model) {
235
+ // Skip stored session model override only when an explicit heartbeat.model
236
+ // was resolved. Heartbeat runs without heartbeat.model should still inherit
237
+ // the regular session/parent model override behavior.
238
+ const skipStoredOverride = params.hasResolvedHeartbeatModelOverride === true;
239
+ if (storedOverride?.model && !skipStoredOverride) {
216
240
  const candidateProvider = storedOverride.provider || defaultProvider;
217
241
  const key = modelKey(candidateProvider, storedOverride.model);
218
242
  if (allowedModelKeys.size === 0 || allowedModelKeys.has(key)) {
@@ -238,8 +262,9 @@ export async function createModelSelectionState(params) {
238
262
  }
239
263
  let defaultThinkingLevel;
240
264
  const resolveDefaultThinkingLevel = async () => {
241
- if (defaultThinkingLevel)
265
+ if (defaultThinkingLevel) {
242
266
  return defaultThinkingLevel;
267
+ }
243
268
  let catalogForThinking = modelCatalog ?? allowedModelCatalog;
244
269
  if (!catalogForThinking || catalogForThinking.length === 0) {
245
270
  modelCatalog = await loadModelCatalog({ config: cfg });
@@ -281,26 +306,30 @@ export function resolveModelDirectiveSelection(params) {
281
306
  };
282
307
  const resolveFuzzy = (params) => {
283
308
  const fragment = params.fragment.trim().toLowerCase();
284
- if (!fragment)
309
+ if (!fragment) {
285
310
  return {};
311
+ }
286
312
  const providerFilter = params.provider ? normalizeProviderId(params.provider) : undefined;
287
313
  const candidates = [];
288
314
  for (const key of allowedModelKeys) {
289
315
  const slash = key.indexOf("/");
290
- if (slash <= 0)
316
+ if (slash <= 0) {
291
317
  continue;
318
+ }
292
319
  const provider = normalizeProviderId(key.slice(0, slash));
293
320
  const model = key.slice(slash + 1);
294
- if (providerFilter && provider !== providerFilter)
321
+ if (providerFilter && provider !== providerFilter) {
295
322
  continue;
323
+ }
296
324
  candidates.push({ provider, model });
297
325
  }
298
326
  // Also allow partial alias matches when the user didn't specify a provider.
299
327
  if (!params.provider) {
300
328
  const aliasMatches = [];
301
329
  for (const [aliasKey, entry] of aliasIndex.byAlias.entries()) {
302
- if (!aliasKey.includes(fragment))
330
+ if (!aliasKey.includes(fragment)) {
303
331
  continue;
332
+ }
304
333
  aliasMatches.push({
305
334
  provider: entry.ref.provider,
306
335
  model: entry.ref.model,
@@ -308,15 +337,17 @@ export function resolveModelDirectiveSelection(params) {
308
337
  }
309
338
  for (const match of aliasMatches) {
310
339
  const key = modelKey(match.provider, match.model);
311
- if (!allowedModelKeys.has(key))
340
+ if (!allowedModelKeys.has(key)) {
312
341
  continue;
342
+ }
313
343
  if (!candidates.some((c) => c.provider === match.provider && c.model === match.model)) {
314
344
  candidates.push(match);
315
345
  }
316
346
  }
317
347
  }
318
- if (candidates.length === 0)
348
+ if (candidates.length === 0) {
319
349
  return {};
350
+ }
320
351
  const scored = candidates
321
352
  .map((candidate) => {
322
353
  const details = scoreFuzzyMatch({
@@ -330,25 +361,32 @@ export function resolveModelDirectiveSelection(params) {
330
361
  return Object.assign({ candidate }, details);
331
362
  })
332
363
  .toSorted((a, b) => {
333
- if (b.score !== a.score)
364
+ if (b.score !== a.score) {
334
365
  return b.score - a.score;
335
- if (a.isDefault !== b.isDefault)
366
+ }
367
+ if (a.isDefault !== b.isDefault) {
336
368
  return a.isDefault ? -1 : 1;
337
- if (a.variantMatchCount !== b.variantMatchCount)
369
+ }
370
+ if (a.variantMatchCount !== b.variantMatchCount) {
338
371
  return b.variantMatchCount - a.variantMatchCount;
339
- if (a.variantCount !== b.variantCount)
372
+ }
373
+ if (a.variantCount !== b.variantCount) {
340
374
  return a.variantCount - b.variantCount;
341
- if (a.modelLength !== b.modelLength)
375
+ }
376
+ if (a.modelLength !== b.modelLength) {
342
377
  return a.modelLength - b.modelLength;
378
+ }
343
379
  return a.key.localeCompare(b.key);
344
380
  });
345
381
  const bestScored = scored[0];
346
382
  const best = bestScored?.candidate;
347
- if (!best || !bestScored)
383
+ if (!best || !bestScored) {
348
384
  return {};
385
+ }
349
386
  const minScore = providerFilter ? 90 : 120;
350
- if (bestScored.score < minScore)
387
+ if (bestScored.score < minScore) {
351
388
  return {};
389
+ }
352
390
  return { selection: buildSelection(best.provider, best.model) };
353
391
  };
354
392
  const resolved = resolveModelRefFromString({
@@ -358,8 +396,9 @@ export function resolveModelDirectiveSelection(params) {
358
396
  });
359
397
  if (!resolved) {
360
398
  const fuzzy = resolveFuzzy({ fragment: rawTrimmed });
361
- if (fuzzy.selection || fuzzy.error)
399
+ if (fuzzy.selection || fuzzy.error) {
362
400
  return fuzzy;
401
+ }
363
402
  return {
364
403
  error: `Unrecognized model "${rawTrimmed}". Use /models to list providers, or /models <provider> to list models.`,
365
404
  };
@@ -382,13 +421,15 @@ export function resolveModelDirectiveSelection(params) {
382
421
  const provider = normalizeProviderId(rawTrimmed.slice(0, slash).trim());
383
422
  const fragment = rawTrimmed.slice(slash + 1).trim();
384
423
  const fuzzy = resolveFuzzy({ provider, fragment });
385
- if (fuzzy.selection || fuzzy.error)
424
+ if (fuzzy.selection || fuzzy.error) {
386
425
  return fuzzy;
426
+ }
387
427
  }
388
428
  // Otherwise, try fuzzy matching across allowlisted models.
389
429
  const fuzzy = resolveFuzzy({ fragment: rawTrimmed });
390
- if (fuzzy.selection || fuzzy.error)
430
+ if (fuzzy.selection || fuzzy.error) {
391
431
  return fuzzy;
432
+ }
392
433
  return {
393
434
  error: `Model "${resolved.ref.provider}/${resolved.ref.model}" is not allowed. Use /models to list providers, or /models <provider> to list models.`,
394
435
  };
@@ -9,8 +9,9 @@ function isRunAlreadyQueued(run, items, allowPromptFallback = false) {
9
9
  if (messageId) {
10
10
  return items.some((item) => item.messageId?.trim() === messageId && hasSameRouting(item));
11
11
  }
12
- if (!allowPromptFallback)
12
+ if (!allowPromptFallback) {
13
13
  return false;
14
+ }
14
15
  return items.some((item) => item.prompt === run.prompt && hasSameRouting(item));
15
16
  }
16
17
  export function enqueueFollowupRun(key, run, settings, dedupeMode = "message-id") {
@@ -19,25 +20,29 @@ export function enqueueFollowupRun(key, run, settings, dedupeMode = "message-id"
19
20
  ? undefined
20
21
  : (item, items) => isRunAlreadyQueued(item, items, dedupeMode === "prompt");
21
22
  // Deduplicate: skip if the same message is already queued.
22
- if (shouldSkipQueueItem({ item: run, items: queue.items, dedupe }))
23
+ if (shouldSkipQueueItem({ item: run, items: queue.items, dedupe })) {
23
24
  return false;
25
+ }
24
26
  queue.lastEnqueuedAt = Date.now();
25
27
  queue.lastRun = run.run;
26
28
  const shouldEnqueue = applyQueueDropPolicy({
27
29
  queue,
28
30
  summarize: (item) => item.summaryLine?.trim() || item.prompt.trim(),
29
31
  });
30
- if (!shouldEnqueue)
32
+ if (!shouldEnqueue) {
31
33
  return false;
34
+ }
32
35
  queue.items.push(run);
33
36
  return true;
34
37
  }
35
38
  export function getFollowupQueueDepth(key) {
36
39
  const cleaned = key.trim();
37
- if (!cleaned)
40
+ if (!cleaned) {
38
41
  return 0;
42
+ }
39
43
  const queue = FOLLOWUP_QUEUES.get(cleaned);
40
- if (!queue)
44
+ if (!queue) {
41
45
  return 0;
46
+ }
42
47
  return queue.items.length;
43
48
  }
@@ -1,3 +1,4 @@
1
+ import { applyQueueRuntimeSettings } from "../../../utils/queue-helpers.js";
1
2
  export const DEFAULT_QUEUE_DEBOUNCE_MS = 1000;
2
3
  export const DEFAULT_QUEUE_CAP = 20;
3
4
  export const DEFAULT_QUEUE_DROP = "summarize";
@@ -5,16 +6,10 @@ export const FOLLOWUP_QUEUES = new Map();
5
6
  export function getFollowupQueue(key, settings) {
6
7
  const existing = FOLLOWUP_QUEUES.get(key);
7
8
  if (existing) {
8
- existing.mode = settings.mode;
9
- existing.debounceMs =
10
- typeof settings.debounceMs === "number"
11
- ? Math.max(0, settings.debounceMs)
12
- : existing.debounceMs;
13
- existing.cap =
14
- typeof settings.cap === "number" && settings.cap > 0
15
- ? Math.floor(settings.cap)
16
- : existing.cap;
17
- existing.dropPolicy = settings.dropPolicy ?? existing.dropPolicy;
9
+ applyQueueRuntimeSettings({
10
+ target: existing,
11
+ settings,
12
+ });
18
13
  return existing;
19
14
  }
20
15
  const created = {
@@ -32,16 +27,22 @@ export function getFollowupQueue(key, settings) {
32
27
  droppedCount: 0,
33
28
  summaryLines: [],
34
29
  };
30
+ applyQueueRuntimeSettings({
31
+ target: created,
32
+ settings,
33
+ });
35
34
  FOLLOWUP_QUEUES.set(key, created);
36
35
  return created;
37
36
  }
38
37
  export function clearFollowupQueue(key) {
39
38
  const cleaned = key.trim();
40
- if (!cleaned)
39
+ if (!cleaned) {
41
40
  return 0;
41
+ }
42
42
  const queue = FOLLOWUP_QUEUES.get(cleaned);
43
- if (!queue)
43
+ if (!queue) {
44
44
  return 0;
45
+ }
45
46
  const cleared = queue.items.length + queue.droppedCount;
46
47
  queue.items.length = 0;
47
48
  queue.droppedCount = 0;
@@ -1,34 +1,40 @@
1
1
  import { isMessagingToolDuplicate } from "../../agents/pi-embedded-helpers.js";
2
2
  import { normalizeTargetForProvider } from "../../infra/outbound/target-normalization.js";
3
+ import { normalizeOptionalAccountId } from "../../routing/account-id.js";
3
4
  import { extractReplyToTag } from "./reply-tags.js";
4
5
  import { createReplyToModeFilterForChannel } from "./reply-threading.js";
5
- export function applyReplyTagsToPayload(payload, currentMessageId) {
6
- if (typeof payload.text !== "string") {
7
- if (!payload.replyToCurrent || payload.replyToId)
8
- return payload;
9
- return {
10
- ...payload,
11
- replyToId: currentMessageId?.trim() || undefined,
6
+ function resolveReplyThreadingForPayload(params) {
7
+ const implicitReplyToId = params.implicitReplyToId?.trim() || undefined;
8
+ const currentMessageId = params.currentMessageId?.trim() || undefined;
9
+ // 1) Apply implicit reply threading first (replyToMode will strip later if needed).
10
+ let resolved = params.payload.replyToId || params.payload.replyToCurrent === false || !implicitReplyToId
11
+ ? params.payload
12
+ : { ...params.payload, replyToId: implicitReplyToId };
13
+ // 2) Parse explicit reply tags from text (if present) and clean them.
14
+ if (typeof resolved.text === "string" && resolved.text.includes("[[")) {
15
+ const { cleaned, replyToId, replyToCurrent, hasTag } = extractReplyToTag(resolved.text, currentMessageId);
16
+ resolved = {
17
+ ...resolved,
18
+ text: cleaned ? cleaned : undefined,
19
+ replyToId: replyToId ?? resolved.replyToId,
20
+ replyToTag: hasTag || resolved.replyToTag,
21
+ replyToCurrent: replyToCurrent || resolved.replyToCurrent,
12
22
  };
13
23
  }
14
- const shouldParseTags = payload.text.includes("[[");
15
- if (!shouldParseTags) {
16
- if (!payload.replyToCurrent || payload.replyToId)
17
- return payload;
18
- return {
19
- ...payload,
20
- replyToId: currentMessageId?.trim() || undefined,
21
- replyToTag: payload.replyToTag ?? true,
24
+ // 3) If replyToCurrent was set out-of-band (e.g. tags already stripped upstream),
25
+ // ensure replyToId is set to the current message id when available.
26
+ if (resolved.replyToCurrent && !resolved.replyToId && currentMessageId) {
27
+ resolved = {
28
+ ...resolved,
29
+ replyToId: currentMessageId,
22
30
  };
23
31
  }
24
- const { cleaned, replyToId, replyToCurrent, hasTag } = extractReplyToTag(payload.text, currentMessageId);
25
- return {
26
- ...payload,
27
- text: cleaned ? cleaned : undefined,
28
- replyToId: replyToId ?? payload.replyToId,
29
- replyToTag: hasTag || payload.replyToTag,
30
- replyToCurrent: replyToCurrent || payload.replyToCurrent,
31
- };
32
+ return resolved;
33
+ }
34
+ // Backward-compatible helper: apply explicit reply tags/directives to a single payload.
35
+ // This intentionally does not apply implicit threading.
36
+ export function applyReplyTagsToPayload(payload, currentMessageId) {
37
+ return resolveReplyThreadingForPayload({ payload, currentMessageId });
32
38
  }
33
39
  export function isRenderablePayload(payload) {
34
40
  return Boolean(payload.text ||
@@ -40,41 +46,66 @@ export function isRenderablePayload(payload) {
40
46
  export function applyReplyThreading(params) {
41
47
  const { payloads, replyToMode, replyToChannel, currentMessageId } = params;
42
48
  const applyReplyToMode = createReplyToModeFilterForChannel(replyToMode, replyToChannel);
49
+ const implicitReplyToId = currentMessageId?.trim() || undefined;
43
50
  return payloads
44
- .map((payload) => applyReplyTagsToPayload(payload, currentMessageId))
51
+ .map((payload) => resolveReplyThreadingForPayload({ payload, implicitReplyToId, currentMessageId }))
45
52
  .filter(isRenderablePayload)
46
53
  .map(applyReplyToMode);
47
54
  }
48
55
  export function filterMessagingToolDuplicates(params) {
49
56
  const { payloads, sentTexts } = params;
50
- if (sentTexts.length === 0)
57
+ if (sentTexts.length === 0) {
51
58
  return payloads;
59
+ }
52
60
  return payloads.filter((payload) => !isMessagingToolDuplicate(payload.text ?? "", sentTexts));
53
61
  }
54
- function normalizeAccountId(value) {
55
- const trimmed = value?.trim();
56
- return trimmed ? trimmed.toLowerCase() : undefined;
62
+ export function filterMessagingToolMediaDuplicates(params) {
63
+ const { payloads, sentMediaUrls } = params;
64
+ if (sentMediaUrls.length === 0) {
65
+ return payloads;
66
+ }
67
+ const sentSet = new Set(sentMediaUrls);
68
+ return payloads.map((payload) => {
69
+ const mediaUrl = payload.mediaUrl;
70
+ const mediaUrls = payload.mediaUrls;
71
+ const stripSingle = mediaUrl && sentSet.has(mediaUrl);
72
+ const filteredUrls = mediaUrls?.filter((u) => !sentSet.has(u));
73
+ if (!stripSingle && (!mediaUrls || filteredUrls?.length === mediaUrls.length)) {
74
+ return payload; // No change
75
+ }
76
+ return {
77
+ ...payload,
78
+ mediaUrl: stripSingle ? undefined : mediaUrl,
79
+ mediaUrls: filteredUrls?.length ? filteredUrls : undefined,
80
+ };
81
+ });
57
82
  }
58
83
  export function shouldSuppressMessagingToolReplies(params) {
59
84
  const provider = params.messageProvider?.trim().toLowerCase();
60
- if (!provider)
85
+ if (!provider) {
61
86
  return false;
87
+ }
62
88
  const originTarget = normalizeTargetForProvider(provider, params.originatingTo);
63
- if (!originTarget)
89
+ if (!originTarget) {
64
90
  return false;
65
- const originAccount = normalizeAccountId(params.accountId);
91
+ }
92
+ const originAccount = normalizeOptionalAccountId(params.accountId);
66
93
  const sentTargets = params.messagingToolSentTargets ?? [];
67
- if (sentTargets.length === 0)
94
+ if (sentTargets.length === 0) {
68
95
  return false;
96
+ }
69
97
  return sentTargets.some((target) => {
70
- if (!target?.provider)
98
+ if (!target?.provider) {
71
99
  return false;
72
- if (target.provider.trim().toLowerCase() !== provider)
100
+ }
101
+ if (target.provider.trim().toLowerCase() !== provider) {
73
102
  return false;
103
+ }
74
104
  const targetKey = normalizeTargetForProvider(provider, target.to);
75
- if (!targetKey)
105
+ if (!targetKey) {
76
106
  return false;
77
- const targetAccount = normalizeAccountId(target.accountId);
107
+ }
108
+ const targetAccount = normalizeOptionalAccountId(target.accountId);
78
109
  if (originAccount && targetAccount && originAccount !== targetAccount) {
79
110
  return false;
80
111
  }
@@ -4,23 +4,24 @@ export function createReplyReferencePlanner(options) {
4
4
  const existingId = options.existingId?.trim();
5
5
  const startId = options.startId?.trim();
6
6
  const use = () => {
7
- if (!allowReference)
7
+ if (!allowReference) {
8
8
  return undefined;
9
- if (existingId) {
10
- hasReplied = true;
11
- return existingId;
12
9
  }
13
- if (!startId)
10
+ if (options.replyToMode === "off") {
14
11
  return undefined;
15
- if (options.replyToMode === "off")
12
+ }
13
+ const id = existingId ?? startId;
14
+ if (!id) {
16
15
  return undefined;
16
+ }
17
17
  if (options.replyToMode === "all") {
18
18
  hasReplied = true;
19
- return startId;
19
+ return id;
20
20
  }
21
+ // "first": only the first reply gets a reference.
21
22
  if (!hasReplied) {
22
23
  hasReplied = true;
23
- return startId;
24
+ return id;
24
25
  }
25
26
  return undefined;
26
27
  };
@@ -9,7 +9,7 @@
9
9
  import { resolveSessionAgentId } from "../../agents/agent-scope.js";
10
10
  import { resolveEffectiveMessagesConfig } from "../../agents/identity.js";
11
11
  import { normalizeChannelId } from "../../channels/plugins/index.js";
12
- import { INTERNAL_MESSAGE_CHANNEL } from "../../utils/message-channel.js";
12
+ import { INTERNAL_MESSAGE_CHANNEL, normalizeMessageChannel } from "../../utils/message-channel.js";
13
13
  import { normalizeReplyPayload } from "./normalize-reply.js";
14
14
  /**
15
15
  * Routes a reply payload to the specified channel.
@@ -21,20 +21,25 @@ import { normalizeReplyPayload } from "./normalize-reply.js";
21
21
  */
22
22
  export async function routeReply(params) {
23
23
  const { payload, channel, to, accountId, threadId, cfg, abortSignal } = params;
24
- // Debug: `pnpm test src/auto-reply/reply/route-reply.test.ts`
25
- const responsePrefix = params.sessionKey
26
- ? resolveEffectiveMessagesConfig(cfg, resolveSessionAgentId({
24
+ const normalizedChannel = normalizeMessageChannel(channel);
25
+ const resolvedAgentId = params.sessionKey
26
+ ? resolveSessionAgentId({
27
27
  sessionKey: params.sessionKey,
28
28
  config: cfg,
29
- })).responsePrefix
29
+ })
30
+ : undefined;
31
+ // Debug: `pnpm test src/auto-reply/reply/route-reply.test.ts`
32
+ const responsePrefix = params.sessionKey
33
+ ? resolveEffectiveMessagesConfig(cfg, resolvedAgentId ?? resolveSessionAgentId({ config: cfg }), { channel: normalizedChannel, accountId }).responsePrefix
30
34
  : cfg.messages?.responsePrefix === "auto"
31
35
  ? undefined
32
36
  : cfg.messages?.responsePrefix;
33
37
  const normalized = normalizeReplyPayload(payload, {
34
38
  responsePrefix,
35
39
  });
36
- if (!normalized)
40
+ if (!normalized) {
37
41
  return { ok: true };
42
+ }
38
43
  let text = normalized.text ?? "";
39
44
  let mediaUrls = (normalized.mediaUrls?.filter(Boolean) ?? []).length
40
45
  ? normalized.mediaUrls?.filter(Boolean)
@@ -74,11 +79,12 @@ export async function routeReply(params) {
74
79
  payloads: [normalized],
75
80
  replyToId: resolvedReplyToId ?? null,
76
81
  threadId: resolvedThreadId,
82
+ agentId: resolvedAgentId,
77
83
  abortSignal,
78
84
  mirror: params.mirror !== false && params.sessionKey
79
85
  ? {
80
86
  sessionKey: params.sessionKey,
81
- agentId: resolveSessionAgentId({ sessionKey: params.sessionKey, config: cfg }),
87
+ agentId: resolvedAgentId,
82
88
  text,
83
89
  mediaUrls,
84
90
  }
@@ -102,7 +108,8 @@ export async function routeReply(params) {
102
108
  * this generic interface.
103
109
  */
104
110
  export function isRoutableChannel(channel) {
105
- if (!channel || channel === INTERNAL_MESSAGE_CHANNEL)
111
+ if (!channel || channel === INTERNAL_MESSAGE_CHANNEL) {
106
112
  return false;
113
+ }
107
114
  return normalizeChannelId(channel) !== null;
108
115
  }
@@ -1 +1 @@
1
- export const BARE_SESSION_RESET_PROMPT = "A new session was started via /new or /reset. Greet the user in your configured persona, if one is provided. Be yourself - use your defined voice, mannerisms, and mood. Keep it to 1-3 sentences and ask what they want to do. If the runtime model differs from default_model in the system prompt, mention the default model. Do not mention internal steps, files, tools, or reasoning.";
1
+ export const BARE_SESSION_RESET_PROMPT = "A new session was started via /new or /reset. Execute your Session Startup sequence now - read the required files before responding to the user. Then greet the user in your configured persona, if one is provided. Be yourself - use your defined voice, mannerisms, and mood. Keep it to 1-3 sentences and ask what they want to do. If the runtime model differs from default_model in the system prompt, mention the default model. Do not mention internal steps, files, tools, or reasoning.";