@poolzin/pool-bot 2026.2.24 → 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 (646) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/acp/client.js +207 -18
  3. package/dist/acp/event-mapper.js +87 -22
  4. package/dist/acp/meta.js +12 -6
  5. package/dist/acp/secret-file.js +22 -0
  6. package/dist/agents/agent-paths.js +8 -9
  7. package/dist/agents/agent-scope.js +17 -5
  8. package/dist/agents/auth-profiles/oauth.js +148 -64
  9. package/dist/agents/auth-profiles/session-override.js +13 -7
  10. package/dist/agents/bash-process-registry.test-helpers.js +29 -0
  11. package/dist/agents/bash-tools.exec-approval-request.js +20 -0
  12. package/dist/agents/bash-tools.exec-host-gateway.js +240 -0
  13. package/dist/agents/bash-tools.exec-host-node.js +235 -0
  14. package/dist/agents/bash-tools.exec-runtime.js +2 -25
  15. package/dist/agents/bash-tools.exec-types.js +1 -0
  16. package/dist/agents/bash-tools.process.js +224 -218
  17. package/dist/agents/bedrock-discovery.js +3 -1
  18. package/dist/agents/byteplus-models.js +97 -0
  19. package/dist/agents/chutes-oauth.js +1 -0
  20. package/dist/agents/cli-runner/helpers.js +4 -0
  21. package/dist/agents/compaction.js +41 -14
  22. package/dist/agents/content-blocks.js +16 -0
  23. package/dist/agents/doubao-models.js +121 -0
  24. package/dist/agents/failover-error.js +2 -0
  25. package/dist/agents/huggingface-models.js +5 -3
  26. package/dist/agents/live-model-filter.js +5 -0
  27. package/dist/agents/minimax-vlm.js +10 -8
  28. package/dist/agents/model-auth.js +6 -0
  29. package/dist/agents/model-catalog.js +3 -1
  30. package/dist/agents/model-fallback.js +96 -101
  31. package/dist/agents/model-selection.js +7 -1
  32. package/dist/agents/models-config.providers.js +364 -165
  33. package/dist/agents/ollama-stream.js +117 -4
  34. package/dist/agents/opencode-zen-models.js +22 -11
  35. package/dist/agents/pi-embedded-helpers/errors.js +55 -33
  36. package/dist/agents/pi-embedded-helpers/messaging-dedupe.js +10 -5
  37. package/dist/agents/pi-embedded-helpers/thinking.js +10 -5
  38. package/dist/agents/pi-embedded-helpers.js +1 -1
  39. package/dist/agents/pi-embedded-payloads.js +1 -0
  40. package/dist/agents/pi-embedded-runner/compact.js +29 -7
  41. package/dist/agents/pi-embedded-runner/extensions.js +28 -26
  42. package/dist/agents/pi-embedded-runner/google.js +20 -8
  43. package/dist/agents/pi-embedded-runner/run/attempt.js +95 -36
  44. package/dist/agents/pi-embedded-runner/run.js +71 -12
  45. package/dist/agents/pi-embedded-runner/run.overflow-compaction.fixture.js +34 -0
  46. package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +11 -2
  47. package/dist/agents/pi-embedded-runner/session-manager-cache.js +11 -7
  48. package/dist/agents/pi-embedded-runner/system-prompt.js +2 -0
  49. package/dist/agents/pi-embedded-runner/thinking.js +42 -0
  50. package/dist/agents/pi-embedded-runner/tool-name-allowlist.js +19 -0
  51. package/dist/agents/pi-embedded-runner/utils.js +7 -10
  52. package/dist/agents/pi-embedded-subscribe.handlers.lifecycle.js +45 -56
  53. package/dist/agents/pi-embedded-subscribe.handlers.tools.js +2 -2
  54. package/dist/agents/pi-embedded-subscribe.js +9 -4
  55. package/dist/agents/pi-embedded-subscribe.tools.js +68 -14
  56. package/dist/agents/pi-embedded-utils.js +3 -0
  57. package/dist/agents/pi-extensions/compaction-safeguard-runtime.js +4 -20
  58. package/dist/agents/pi-extensions/compaction-safeguard.js +75 -33
  59. package/dist/agents/pi-settings.js +40 -0
  60. package/dist/agents/pi-tools.policy.js +2 -1
  61. package/dist/agents/provider/config-loader.js +1 -1
  62. package/dist/agents/sandbox/browser.js +170 -33
  63. package/dist/agents/sandbox/config-hash.js +14 -27
  64. package/dist/agents/sandbox/config.js +21 -2
  65. package/dist/agents/sandbox/constants.js +2 -0
  66. package/dist/agents/sandbox/docker.js +16 -2
  67. package/dist/agents/sandbox/novnc-auth.js +62 -0
  68. package/dist/agents/sandbox/sanitize-env-vars.js +1 -1
  69. package/dist/agents/sandbox/shared.js +10 -6
  70. package/dist/agents/sandbox-paths.js +24 -11
  71. package/dist/agents/schema/clean-for-gemini.js +132 -85
  72. package/dist/agents/session-slug.js +10 -5
  73. package/dist/agents/session-tool-result-guard-wrapper.js +1 -0
  74. package/dist/agents/session-tool-result-guard.js +3 -1
  75. package/dist/agents/session-transcript-repair.js +40 -6
  76. package/dist/agents/skills/bundled-dir.js +19 -5
  77. package/dist/agents/skills/env-overrides.js +124 -43
  78. package/dist/agents/skills/frontmatter.js +6 -6
  79. package/dist/agents/skills/plugin-skills.js +14 -7
  80. package/dist/agents/skills/workspace.js +1 -0
  81. package/dist/agents/skills.test-helpers.js +13 -0
  82. package/dist/agents/stable-stringify.js +12 -0
  83. package/dist/agents/subagent-announce.js +251 -49
  84. package/dist/agents/subagent-lifecycle-events.js +19 -0
  85. package/dist/agents/subagent-registry-cleanup.js +31 -0
  86. package/dist/agents/subagent-registry-completion.js +68 -0
  87. package/dist/agents/subagent-registry-queries.js +117 -0
  88. package/dist/agents/subagent-registry-state.js +46 -0
  89. package/dist/agents/subagent-registry.js +252 -221
  90. package/dist/agents/subagent-registry.mocks.shared.js +12 -0
  91. package/dist/agents/subagent-registry.store.js +1 -0
  92. package/dist/agents/subagent-registry.types.js +1 -0
  93. package/dist/agents/subagent-spawn.js +195 -7
  94. package/dist/agents/system-prompt.js +22 -6
  95. package/dist/agents/test-helpers/assistant-message-fixtures.js +29 -0
  96. package/dist/agents/test-helpers/fast-coding-tools.js +1 -18
  97. package/dist/agents/test-helpers/fast-core-tools.js +1 -17
  98. package/dist/agents/test-helpers/pi-tools-sandbox-context.js +27 -0
  99. package/dist/agents/timeout.js +18 -6
  100. package/dist/agents/tool-call-id.js +1 -1
  101. package/dist/agents/tool-display-common.js +162 -29
  102. package/dist/agents/tool-images.js +82 -9
  103. package/dist/agents/tool-policy-shared.js +108 -0
  104. package/dist/agents/tool-policy.js +51 -26
  105. package/dist/agents/tools/browser-tool.js +160 -54
  106. package/dist/agents/tools/canvas-tool.js +27 -1
  107. package/dist/agents/tools/common.js +45 -0
  108. package/dist/agents/tools/cron-tool.test-helpers.js +12 -0
  109. package/dist/agents/tools/discord-actions-guild.js +4 -1
  110. package/dist/agents/tools/discord-actions-moderation-shared.js +27 -0
  111. package/dist/agents/tools/gateway-tool.js +3 -1
  112. package/dist/agents/tools/image-tool.js +214 -99
  113. package/dist/agents/tools/nodes-utils.js +1 -10
  114. package/dist/agents/tools/sessions-history-tool.js +140 -108
  115. package/dist/agents/tools/sessions-send-helpers.js +12 -6
  116. package/dist/agents/tools/sessions-spawn-tool.js +8 -2
  117. package/dist/agents/tools/subagents-tool.js +2 -1
  118. package/dist/agents/tools/whatsapp-actions.js +10 -2
  119. package/dist/agents/tools/whatsapp-target-auth.js +18 -0
  120. package/dist/agents/transcript-policy.js +22 -8
  121. package/dist/agents/venice-models.js +11 -3
  122. package/dist/agents/workspace.js +222 -46
  123. package/dist/auto-reply/commands-registry.data.js +51 -0
  124. package/dist/auto-reply/commands-registry.js +19 -21
  125. package/dist/auto-reply/fallback-state.js +114 -0
  126. package/dist/auto-reply/group-activation.js +10 -5
  127. package/dist/auto-reply/inbound-debounce.js +10 -5
  128. package/dist/auto-reply/model-runtime.js +68 -0
  129. package/dist/auto-reply/reply/abort.js +1 -1
  130. package/dist/auto-reply/reply/agent-runner-execution.js +40 -5
  131. package/dist/auto-reply/reply/agent-runner.js +165 -39
  132. package/dist/auto-reply/reply/bash-command.js +41 -39
  133. package/dist/auto-reply/reply/command-gates.js +25 -0
  134. package/dist/auto-reply/reply/commands-allowlist.js +111 -72
  135. package/dist/auto-reply/reply/commands-bash.js +6 -5
  136. package/dist/auto-reply/reply/commands-config.js +30 -28
  137. package/dist/auto-reply/reply/commands-core.js +2 -1
  138. package/dist/auto-reply/reply/commands-info.js +1 -0
  139. package/dist/auto-reply/reply/commands-models.js +65 -14
  140. package/dist/auto-reply/reply/commands-session.js +237 -82
  141. package/dist/auto-reply/reply/commands-setunset-standard.js +13 -0
  142. package/dist/auto-reply/reply/commands-setunset.js +45 -0
  143. package/dist/auto-reply/reply/commands-subagents/action-agents.js +44 -0
  144. package/dist/auto-reply/reply/commands-subagents/action-focus.js +64 -0
  145. package/dist/auto-reply/reply/commands-subagents/action-help.js +4 -0
  146. package/dist/auto-reply/reply/commands-subagents/action-info.js +45 -0
  147. package/dist/auto-reply/reply/commands-subagents/action-kill.js +60 -0
  148. package/dist/auto-reply/reply/commands-subagents/action-list.js +44 -0
  149. package/dist/auto-reply/reply/commands-subagents/action-log.js +29 -0
  150. package/dist/auto-reply/reply/commands-subagents/action-send.js +119 -0
  151. package/dist/auto-reply/reply/commands-subagents/action-spawn.js +52 -0
  152. package/dist/auto-reply/reply/commands-subagents/action-unfocus.js +30 -0
  153. package/dist/auto-reply/reply/commands-subagents/shared.js +303 -0
  154. package/dist/auto-reply/reply/commands-subagents.js +51 -587
  155. package/dist/auto-reply/reply/commands-tts.js +10 -5
  156. package/dist/auto-reply/reply/config-value.js +10 -5
  157. package/dist/auto-reply/reply/directive-handling.model-picker.js +12 -6
  158. package/dist/auto-reply/reply/directive-handling.persist.js +9 -21
  159. package/dist/auto-reply/reply/directive-handling.shared.js +24 -4
  160. package/dist/auto-reply/reply/followup-runner.js +1 -0
  161. package/dist/auto-reply/reply/get-reply-directives-utils.js +23 -14
  162. package/dist/auto-reply/reply/get-reply-directives.js +17 -28
  163. package/dist/auto-reply/reply/get-reply-inline-actions.js +1 -0
  164. package/dist/auto-reply/reply/get-reply.js +71 -12
  165. package/dist/auto-reply/reply/model-selection.js +80 -39
  166. package/dist/auto-reply/reply/queue/enqueue.js +10 -5
  167. package/dist/auto-reply/reply/queue/state.js +13 -12
  168. package/dist/auto-reply/reply/reply-payloads.js +67 -36
  169. package/dist/auto-reply/reply/reply-reference.js +9 -8
  170. package/dist/auto-reply/reply/route-reply.js +15 -8
  171. package/dist/auto-reply/reply/session-reset-prompt.js +1 -1
  172. package/dist/auto-reply/reply/session.js +22 -6
  173. package/dist/auto-reply/reply/strip-inbound-meta.js +147 -0
  174. package/dist/auto-reply/reply/subagents-utils.js +56 -30
  175. package/dist/auto-reply/reply/typing.js +46 -21
  176. package/dist/auto-reply/send-policy.js +14 -7
  177. package/dist/auto-reply/status.js +140 -16
  178. package/dist/auto-reply/templating.js +10 -5
  179. package/dist/auto-reply/thinking.js +7 -16
  180. package/dist/auto-reply/tokens.js +21 -5
  181. package/dist/browser/bridge-server.js +36 -20
  182. package/dist/browser/cdp.helpers.js +7 -14
  183. package/dist/browser/cdp.js +35 -15
  184. package/dist/browser/chrome.profile-decoration.js +7 -4
  185. package/dist/browser/config.js +30 -0
  186. package/dist/browser/extension-relay-auth.js +55 -0
  187. package/dist/browser/extension-relay.js +74 -29
  188. package/dist/browser/navigation-guard.js +39 -0
  189. package/dist/browser/paths.js +77 -0
  190. package/dist/browser/profiles.js +13 -8
  191. package/dist/browser/pw-ai-module.js +10 -5
  192. package/dist/browser/pw-session.js +76 -39
  193. package/dist/browser/pw-tools-core.interactions.js +14 -7
  194. package/dist/browser/pw-tools-core.state.js +12 -6
  195. package/dist/browser/routes/agent.act.js +431 -424
  196. package/dist/browser/routes/agent.shared.js +47 -3
  197. package/dist/browser/routes/agent.snapshot.js +122 -116
  198. package/dist/browser/routes/agent.storage.js +303 -297
  199. package/dist/browser/routes/tabs.js +154 -100
  200. package/dist/browser/server-context.js +7 -0
  201. package/dist/browser/server-lifecycle.js +37 -0
  202. package/dist/build-info.json +3 -3
  203. package/dist/channels/allow-from.js +26 -0
  204. package/dist/channels/allowlists/resolve-utils.js +43 -19
  205. package/dist/channels/channel-config.js +14 -7
  206. package/dist/channels/draft-stream-loop.js +7 -0
  207. package/dist/channels/model-overrides.js +82 -0
  208. package/dist/channels/plugins/account-action-gate.js +13 -0
  209. package/dist/channels/plugins/message-actions.js +10 -0
  210. package/dist/channels/plugins/normalize/imessage.js +14 -7
  211. package/dist/channels/plugins/normalize/slack.js +10 -5
  212. package/dist/channels/plugins/normalize/telegram.js +14 -7
  213. package/dist/channels/plugins/outbound/discord.js +80 -8
  214. package/dist/channels/plugins/outbound/signal.js +11 -11
  215. package/dist/channels/plugins/setup-helpers.js +10 -5
  216. package/dist/channels/sender-label.js +14 -7
  217. package/dist/channels/session.js +4 -2
  218. package/dist/channels/status-reactions.js +297 -0
  219. package/dist/channels/telegram/api.js +18 -0
  220. package/dist/cli/argv.js +84 -21
  221. package/dist/cli/banner.js +3 -2
  222. package/dist/cli/browser-cli-actions-input/register.files-downloads.js +65 -56
  223. package/dist/cli/cli-name.js +11 -11
  224. package/dist/cli/cli-utils.js +13 -3
  225. package/dist/cli/command-format.js +1 -1
  226. package/dist/cli/config-cli.js +1 -1
  227. package/dist/cli/daemon-cli/lifecycle-core.js +31 -19
  228. package/dist/cli/daemon-cli/lifecycle.js +64 -2
  229. package/dist/cli/daemon-cli/restart-health.js +126 -0
  230. package/dist/cli/daemon-cli/status.gather.js +9 -13
  231. package/dist/cli/daemon-cli/status.print.js +2 -10
  232. package/dist/cli/deps.js +27 -22
  233. package/dist/cli/exec-approvals-cli.js +92 -124
  234. package/dist/cli/gateway-cli/run-loop.js +23 -5
  235. package/dist/cli/memory-cli.js +158 -61
  236. package/dist/cli/node-cli/register.js +14 -5
  237. package/dist/cli/nodes-cli/register.push.js +63 -0
  238. package/dist/cli/nodes-media-utils.js +26 -0
  239. package/dist/cli/outbound-send-deps.js +2 -9
  240. package/dist/cli/outbound-send-mapping.js +11 -0
  241. package/dist/cli/pairing-cli.js +40 -14
  242. package/dist/cli/plugins-cli.js +250 -73
  243. package/dist/cli/ports.js +11 -10
  244. package/dist/cli/program/build-program.js +3 -1
  245. package/dist/cli/program/command-registry.js +214 -136
  246. package/dist/cli/program/command-tree.js +16 -0
  247. package/dist/cli/program/help.js +43 -12
  248. package/dist/cli/program/preaction.js +13 -9
  249. package/dist/cli/program/register.configure.js +3 -18
  250. package/dist/cli/program/register.maintenance.js +2 -2
  251. package/dist/cli/program/register.onboard.js +2 -0
  252. package/dist/cli/program/register.status-health-sessions.js +16 -17
  253. package/dist/cli/program/register.subclis.js +93 -52
  254. package/dist/cli/route.js +12 -8
  255. package/dist/cli/system-cli.js +36 -46
  256. package/dist/cli/test-runtime-capture.js +24 -0
  257. package/dist/cli/update-cli/shared.js +22 -9
  258. package/dist/cli/update-cli/update-command.js +89 -14
  259. package/dist/cli/update-cli/wizard.js +6 -12
  260. package/dist/commands/agent/run-context.js +18 -5
  261. package/dist/commands/agent/session-store.js +17 -4
  262. package/dist/commands/agent.js +185 -89
  263. package/dist/commands/agents.bindings.js +14 -7
  264. package/dist/commands/agents.commands.add.js +13 -9
  265. package/dist/commands/agents.commands.identity.js +12 -6
  266. package/dist/commands/agents.commands.list.js +11 -6
  267. package/dist/commands/agents.config.js +8 -10
  268. package/dist/commands/agents.providers.js +12 -6
  269. package/dist/commands/auth-choice-options.js +103 -75
  270. package/dist/commands/auth-choice.apply.byteplus.js +55 -0
  271. package/dist/commands/auth-choice.apply.js +4 -0
  272. package/dist/commands/auth-choice.apply.minimax.js +61 -13
  273. package/dist/commands/auth-choice.apply.openai.js +3 -1
  274. package/dist/commands/auth-choice.apply.volcengine.js +55 -0
  275. package/dist/commands/auth-choice.preferred-provider.js +2 -0
  276. package/dist/commands/channels/remove.js +13 -6
  277. package/dist/commands/channels/shared.js +4 -14
  278. package/dist/commands/channels.mock-harness.js +23 -0
  279. package/dist/commands/configure.commands.js +14 -0
  280. package/dist/commands/configure.gateway.js +2 -4
  281. package/dist/commands/configure.js +1 -1
  282. package/dist/commands/configure.shared.js +11 -0
  283. package/dist/commands/daemon-install-helpers.js +2 -2
  284. package/dist/commands/daemon-install-runtime-warning.js +11 -0
  285. package/dist/commands/dashboard.js +12 -10
  286. package/dist/commands/docs.js +14 -8
  287. package/dist/commands/doctor-config-flow.js +11 -9
  288. package/dist/commands/doctor-legacy-config.js +281 -0
  289. package/dist/commands/doctor-state-integrity.js +99 -23
  290. package/dist/commands/doctor-update.js +12 -9
  291. package/dist/commands/models/list.list-command.js +7 -5
  292. package/dist/commands/models/set-image.js +2 -21
  293. package/dist/commands/node-daemon-install-helpers.js +10 -8
  294. package/dist/commands/onboard-auth.config-minimax.js +54 -80
  295. package/dist/commands/onboard-auth.config-opencode.js +2 -18
  296. package/dist/commands/onboard-auth.credentials.js +90 -13
  297. package/dist/commands/onboard-auth.js +1 -1
  298. package/dist/commands/onboard-auth.models.js +6 -5
  299. package/dist/commands/onboard-hooks.js +1 -1
  300. package/dist/commands/onboard-non-interactive/api-keys.js +14 -7
  301. package/dist/commands/onboard-non-interactive/local/auth-choice.js +64 -49
  302. package/dist/commands/onboard-provider-auth-flags.js +14 -0
  303. package/dist/commands/onboard-remote.js +14 -7
  304. package/dist/commands/onboard.js +11 -13
  305. package/dist/commands/sandbox-display.js +6 -5
  306. package/dist/commands/sessions.test-helpers.js +61 -0
  307. package/dist/commands/status-all/diagnosis.js +14 -10
  308. package/dist/commands/status-all/format.js +1 -0
  309. package/dist/commands/status.gateway-probe.js +1 -16
  310. package/dist/commands/systemd-linger.js +12 -6
  311. package/dist/config/agent-limits.js +2 -0
  312. package/dist/config/commands.js +32 -15
  313. package/dist/config/config-paths.js +9 -11
  314. package/dist/config/config.js +1 -1
  315. package/dist/config/defaults.js +22 -2
  316. package/dist/config/discord-preview-streaming.js +104 -0
  317. package/dist/config/env-substitution.js +62 -34
  318. package/dist/config/env-vars.js +45 -7
  319. package/dist/config/includes.js +4 -0
  320. package/dist/config/io.js +656 -171
  321. package/dist/config/legacy.migrations.part-1.js +189 -78
  322. package/dist/config/legacy.shared.js +3 -1
  323. package/dist/config/merge-patch.js +54 -4
  324. package/dist/config/prototype-keys.js +4 -0
  325. package/dist/config/redact-snapshot.js +404 -76
  326. package/dist/config/schema.help.js +44 -7
  327. package/dist/config/schema.js +58 -570
  328. package/dist/config/schema.labels.js +38 -6
  329. package/dist/config/sessions/delivery-info.js +10 -3
  330. package/dist/config/sessions/main-session.js +10 -5
  331. package/dist/config/sessions/session-file.js +33 -0
  332. package/dist/config/sessions/session-key.js +10 -5
  333. package/dist/config/sessions/store.js +1 -1
  334. package/dist/config/sessions.js +1 -0
  335. package/dist/config/validation.js +140 -85
  336. package/dist/config/zod-schema.agent-runtime.js +11 -0
  337. package/dist/config/zod-schema.hooks.js +40 -11
  338. package/dist/config/zod-schema.installs.js +20 -0
  339. package/dist/config/zod-schema.js +156 -20
  340. package/dist/config/zod-schema.providers-core.js +78 -4
  341. package/dist/config/zod-schema.providers.js +6 -1
  342. package/dist/config/zod-schema.session.js +41 -2
  343. package/dist/cron/run-log.js +3 -0
  344. package/dist/cron/schedule.js +21 -10
  345. package/dist/cron/service/ops.js +35 -21
  346. package/dist/cron/service/timer.js +116 -16
  347. package/dist/cron/stagger.js +3 -1
  348. package/dist/daemon/cmd-argv.js +21 -0
  349. package/dist/daemon/cmd-set.js +58 -0
  350. package/dist/daemon/service-types.js +1 -0
  351. package/dist/discord/api.js +12 -6
  352. package/dist/discord/draft-chunking.js +22 -0
  353. package/dist/discord/draft-stream.js +124 -0
  354. package/dist/discord/monitor/agent-components.js +1 -1
  355. package/dist/discord/monitor/commands.js +5 -0
  356. package/dist/discord/monitor/exec-approvals.js +357 -162
  357. package/dist/discord/monitor/gateway-plugin.js +2 -1
  358. package/dist/discord/monitor/listeners.js +37 -27
  359. package/dist/discord/monitor/message-handler.js +4 -1
  360. package/dist/discord/monitor/message-handler.preflight.js +65 -8
  361. package/dist/discord/monitor/message-handler.process.js +246 -217
  362. package/dist/discord/monitor/message-utils.js +143 -6
  363. package/dist/discord/monitor/model-picker-preferences.js +143 -0
  364. package/dist/discord/monitor/model-picker.js +651 -0
  365. package/dist/discord/monitor/native-command.js +573 -16
  366. package/dist/discord/monitor/provider.allowlist.js +223 -0
  367. package/dist/discord/monitor/provider.js +275 -347
  368. package/dist/discord/monitor/provider.lifecycle.js +100 -0
  369. package/dist/discord/monitor/reply-delivery.js +123 -16
  370. package/dist/discord/monitor/thread-bindings.discord-api.js +215 -0
  371. package/dist/discord/monitor/thread-bindings.js +4 -0
  372. package/dist/discord/monitor/thread-bindings.lifecycle.js +177 -0
  373. package/dist/discord/monitor/thread-bindings.manager.js +423 -0
  374. package/dist/discord/monitor/thread-bindings.messages.js +55 -0
  375. package/dist/discord/monitor/thread-bindings.state.js +358 -0
  376. package/dist/discord/monitor/thread-bindings.types.js +6 -0
  377. package/dist/discord/resolve-users.js +33 -21
  378. package/dist/discord/send.channels.js +15 -0
  379. package/dist/discord/send.js +3 -2
  380. package/dist/discord/send.outbound.js +82 -26
  381. package/dist/discord/send.permissions.js +83 -30
  382. package/dist/discord/send.reactions.js +8 -4
  383. package/dist/discord/token.js +10 -5
  384. package/dist/discord/voice/command.js +263 -0
  385. package/dist/discord/voice/manager.js +531 -0
  386. package/dist/gateway/auth.js +72 -13
  387. package/dist/gateway/call.js +152 -83
  388. package/dist/gateway/canvas-capability.js +75 -0
  389. package/dist/gateway/client.js +28 -4
  390. package/dist/gateway/config-reload.js +3 -4
  391. package/dist/gateway/control-plane-audit.js +28 -0
  392. package/dist/gateway/control-plane-rate-limit.js +53 -0
  393. package/dist/gateway/control-ui.js +219 -96
  394. package/dist/gateway/events.js +1 -0
  395. package/dist/gateway/hooks-mapping.js +88 -38
  396. package/dist/gateway/hooks.js +109 -54
  397. package/dist/gateway/http-auth-helpers.js +3 -2
  398. package/dist/gateway/http-common.js +22 -0
  399. package/dist/gateway/http-endpoint-helpers.js +1 -0
  400. package/dist/gateway/method-scopes.js +169 -0
  401. package/dist/gateway/net.js +74 -9
  402. package/dist/gateway/node-invoke-system-run-approval.js +14 -35
  403. package/dist/gateway/node-registry.js +10 -5
  404. package/dist/gateway/openai-http.js +1 -0
  405. package/dist/gateway/openresponses-http.js +121 -110
  406. package/dist/gateway/origin-check.js +1 -18
  407. package/dist/gateway/probe-auth.js +2 -0
  408. package/dist/gateway/protocol/index.js +4 -2
  409. package/dist/gateway/protocol/schema/cron.js +1 -0
  410. package/dist/gateway/protocol/schema/devices.js +1 -0
  411. package/dist/gateway/protocol/schema/protocol-schemas.js +4 -1
  412. package/dist/gateway/protocol/schema/push.js +18 -0
  413. package/dist/gateway/protocol/schema/sessions.js +6 -0
  414. package/dist/gateway/protocol/schema.js +1 -0
  415. package/dist/gateway/role-policy.js +17 -0
  416. package/dist/gateway/server/ws-connection/connect-policy.js +37 -0
  417. package/dist/gateway/server/ws-connection/message-handler.js +175 -148
  418. package/dist/gateway/server-chat.js +83 -25
  419. package/dist/gateway/server-constants.js +10 -9
  420. package/dist/gateway/server-cron.js +1 -0
  421. package/dist/gateway/server-http.js +247 -54
  422. package/dist/gateway/server-maintenance.js +20 -5
  423. package/dist/gateway/server-methods/agent.js +162 -24
  424. package/dist/gateway/server-methods/chat.js +465 -130
  425. package/dist/gateway/server-methods/config.js +193 -152
  426. package/dist/gateway/server-methods/devices.js +17 -3
  427. package/dist/gateway/server-methods/models.js +11 -1
  428. package/dist/gateway/server-methods/nodes.helpers.js +12 -0
  429. package/dist/gateway/server-methods/nodes.js +251 -69
  430. package/dist/gateway/server-methods/push.js +53 -0
  431. package/dist/gateway/server-methods/sessions.js +64 -8
  432. package/dist/gateway/server-methods/usage.js +162 -75
  433. package/dist/gateway/server-node-events.js +29 -0
  434. package/dist/gateway/server-reload-handlers.js +2 -3
  435. package/dist/gateway/server-runtime-config.js +39 -13
  436. package/dist/gateway/server-runtime-state.js +2 -0
  437. package/dist/gateway/server-startup-memory.js +17 -11
  438. package/dist/gateway/server-ws-runtime.js +1 -0
  439. package/dist/gateway/server.impl.js +296 -139
  440. package/dist/gateway/session-preview.test-helpers.js +11 -0
  441. package/dist/gateway/session-utils.fs.js +32 -34
  442. package/dist/gateway/sessions-resolve.js +17 -5
  443. package/dist/gateway/startup-auth.js +126 -0
  444. package/dist/gateway/test-helpers.agent-results.js +15 -0
  445. package/dist/gateway/test-helpers.mocks.js +37 -14
  446. package/dist/gateway/test-helpers.openai-mock.js +14 -7
  447. package/dist/gateway/test-helpers.server.js +161 -77
  448. package/dist/gateway/tools-invoke-http.js +21 -10
  449. package/dist/hooks/bundled/bootstrap-extra-files/handler.js +3 -1
  450. package/dist/hooks/bundled/command-logger/handler.js +7 -2
  451. package/dist/hooks/bundled/session-memory/handler.js +170 -38
  452. package/dist/hooks/frontmatter.js +6 -6
  453. package/dist/hooks/gmail-watcher-lifecycle.js +23 -0
  454. package/dist/hooks/gmail-watcher.js +11 -6
  455. package/dist/hooks/internal-hooks.js +11 -1
  456. package/dist/hooks/llm-slug-generator.js +4 -1
  457. package/dist/hooks/workspace.js +47 -17
  458. package/dist/imessage/accounts.js +9 -20
  459. package/dist/imessage/monitor/inbound-processing.js +2 -1
  460. package/dist/infra/archive-path.js +49 -0
  461. package/dist/infra/archive.js +174 -73
  462. package/dist/infra/control-ui-assets.js +14 -6
  463. package/dist/infra/device-pairing.js +204 -144
  464. package/dist/infra/env.js +10 -5
  465. package/dist/infra/exec-approvals-allowlist.js +141 -70
  466. package/dist/infra/exec-approvals-analysis.js +78 -20
  467. package/dist/infra/exec-approvals.js +5 -17
  468. package/dist/infra/exec-safe-bin-policy.js +277 -0
  469. package/dist/infra/fixed-window-rate-limit.js +33 -0
  470. package/dist/infra/fs-safe.js +71 -39
  471. package/dist/infra/gateway-lock.js +6 -2
  472. package/dist/infra/git-root.js +61 -0
  473. package/dist/infra/heartbeat-active-hours.js +2 -2
  474. package/dist/infra/heartbeat-reason.js +40 -0
  475. package/dist/infra/heartbeat-runner.js +72 -32
  476. package/dist/infra/heartbeat-wake.js +6 -12
  477. package/dist/infra/host-env-security-policy.json +19 -0
  478. package/dist/infra/host-env-security.js +66 -0
  479. package/dist/infra/install-source-utils.js +91 -7
  480. package/dist/infra/net/ssrf.js +131 -38
  481. package/dist/infra/node-pairing.js +50 -105
  482. package/dist/infra/npm-integrity.js +45 -0
  483. package/dist/infra/npm-pack-install.js +40 -0
  484. package/dist/infra/outbound/bound-delivery-router.js +88 -0
  485. package/dist/infra/outbound/channel-adapters.js +20 -7
  486. package/dist/infra/outbound/channel-selection.js +12 -6
  487. package/dist/infra/outbound/envelope.js +1 -1
  488. package/dist/infra/outbound/format.js +12 -6
  489. package/dist/infra/outbound/message-action-runner.js +107 -327
  490. package/dist/infra/outbound/message.js +59 -36
  491. package/dist/infra/outbound/outbound-policy.js +52 -25
  492. package/dist/infra/outbound/outbound-send-service.js +58 -71
  493. package/dist/infra/outbound/payloads.js +14 -7
  494. package/dist/infra/outbound/session-binding-service.js +123 -0
  495. package/dist/infra/pairing-files.js +10 -0
  496. package/dist/infra/path-guards.js +25 -0
  497. package/dist/infra/plain-object.js +9 -0
  498. package/dist/infra/provider-usage.fetch.codex.js +7 -15
  499. package/dist/infra/provider-usage.fetch.gemini.js +14 -11
  500. package/dist/infra/provider-usage.fetch.shared.js +30 -1
  501. package/dist/infra/provider-usage.fetch.zai.js +10 -9
  502. package/dist/infra/push-apns.js +365 -0
  503. package/dist/infra/restart-sentinel.js +16 -1
  504. package/dist/infra/restart.js +229 -26
  505. package/dist/infra/retry-policy.js +4 -2
  506. package/dist/infra/retry.js +9 -5
  507. package/dist/infra/scp-host.js +54 -0
  508. package/dist/infra/session-cost-usage.js +107 -59
  509. package/dist/infra/session-maintenance-warning.js +3 -1
  510. package/dist/infra/shell-env.js +98 -34
  511. package/dist/infra/ssh-config.js +12 -6
  512. package/dist/infra/system-run-command.js +49 -4
  513. package/dist/infra/update-channels.js +10 -5
  514. package/dist/infra/update-startup.js +86 -9
  515. package/dist/line/accounts.js +5 -7
  516. package/dist/line/bot-access.js +8 -20
  517. package/dist/line/bot-handlers.js +3 -1
  518. package/dist/link-understanding/detect.js +15 -7
  519. package/dist/media/constants.js +15 -6
  520. package/dist/media/image-ops.js +7 -0
  521. package/dist/media/inbound-path-policy.js +114 -0
  522. package/dist/media/input-files.js +16 -0
  523. package/dist/media/local-roots.js +3 -2
  524. package/dist/media-understanding/apply.js +4 -1
  525. package/dist/media-understanding/concurrency.js +8 -20
  526. package/dist/memory/backend-config.js +45 -6
  527. package/dist/memory/embeddings.js +10 -4
  528. package/dist/memory/fs-utils.js +23 -0
  529. package/dist/memory/manager-search.js +12 -6
  530. package/dist/memory/manager-sync-ops.js +12 -2
  531. package/dist/memory/qmd-manager.js +466 -53
  532. package/dist/memory/query-expansion.js +167 -3
  533. package/dist/memory/status-format.js +10 -5
  534. package/dist/memory/sync-memory-files.js +1 -1
  535. package/dist/memory/test-manager.js +8 -0
  536. package/dist/node-host/invoke-system-run.js +281 -0
  537. package/dist/node-host/invoke.js +55 -337
  538. package/dist/pairing/pairing-store.js +22 -0
  539. package/dist/plugin-sdk/allow-from.js +1 -1
  540. package/dist/plugin-sdk/command-auth.js +3 -1
  541. package/dist/plugin-sdk/index.js +6 -3
  542. package/dist/plugin-sdk/temp-path.js +47 -0
  543. package/dist/plugin-sdk/webhook-targets.js +32 -0
  544. package/dist/plugins/bundled-dir.js +9 -6
  545. package/dist/plugins/discovery.js +217 -23
  546. package/dist/plugins/hook-runner-global.js +16 -0
  547. package/dist/plugins/hooks.js +50 -0
  548. package/dist/plugins/install.js +28 -16
  549. package/dist/plugins/loader.js +192 -26
  550. package/dist/plugins/logger.js +8 -0
  551. package/dist/plugins/manifest-registry.js +3 -0
  552. package/dist/plugins/path-safety.js +34 -0
  553. package/dist/plugins/registry.js +5 -2
  554. package/dist/plugins/runtime/index.js +271 -206
  555. package/dist/plugins/runtime.js +3 -17
  556. package/dist/plugins/update.js +78 -12
  557. package/dist/process/spawn-utils.js +14 -7
  558. package/dist/providers/github-copilot-models.js +4 -1
  559. package/dist/providers/github-copilot-token.js +11 -6
  560. package/dist/providers/qwen-portal-oauth.js +14 -6
  561. package/dist/routing/account-id.js +30 -0
  562. package/dist/routing/resolve-route.js +3 -7
  563. package/dist/routing/session-key.js +2 -16
  564. package/dist/security/audit-channel.js +100 -20
  565. package/dist/security/audit-extra.async.js +505 -179
  566. package/dist/security/audit-extra.js +12 -2
  567. package/dist/security/audit-extra.sync.js +421 -35
  568. package/dist/security/audit-fs.js +31 -13
  569. package/dist/security/audit.js +180 -370
  570. package/dist/security/dm-policy-shared.js +68 -0
  571. package/dist/security/external-content.js +46 -14
  572. package/dist/security/fix.js +49 -85
  573. package/dist/security/scan-paths.js +20 -0
  574. package/dist/security/secret-equal.js +3 -7
  575. package/dist/security/windows-acl.js +30 -15
  576. package/dist/shared/entry-status.js +6 -0
  577. package/dist/shared/frontmatter.js +5 -5
  578. package/dist/shared/node-list-parse.js +13 -0
  579. package/dist/shared/node-match.js +11 -4
  580. package/dist/shared/operator-scope-compat.js +42 -0
  581. package/dist/shared/text-chunking.js +29 -0
  582. package/dist/signal/accounts.js +7 -20
  583. package/dist/signal/monitor/event-handler.js +3 -1
  584. package/dist/slack/accounts.js +6 -19
  585. package/dist/slack/actions.js +11 -3
  586. package/dist/slack/blocks.test-helpers.js +31 -0
  587. package/dist/slack/monitor/auth.js +1 -1
  588. package/dist/slack/monitor/message-handler/dispatch.js +50 -29
  589. package/dist/slack/monitor/mrkdwn.js +8 -0
  590. package/dist/slack/monitor/replies.js +15 -7
  591. package/dist/slack/monitor/slash.js +22 -13
  592. package/dist/slack/resolve-channels.js +10 -5
  593. package/dist/slack/send.js +102 -12
  594. package/dist/slack/stream-mode.js +10 -0
  595. package/dist/slack/streaming.js +4 -2
  596. package/dist/telegram/accounts.js +19 -14
  597. package/dist/telegram/bot/helpers.js +3 -5
  598. package/dist/telegram/bot-access.js +35 -36
  599. package/dist/telegram/bot-handlers.js +120 -148
  600. package/dist/telegram/bot-message-context.js +68 -9
  601. package/dist/telegram/bot-message-dispatch.js +477 -210
  602. package/dist/telegram/bot-native-commands.js +16 -0
  603. package/dist/telegram/draft-stream.js +44 -8
  604. package/dist/telegram/inline-buttons.js +5 -15
  605. package/dist/telegram/monitor.js +11 -7
  606. package/dist/telegram/network-config.js +19 -7
  607. package/dist/telegram/reasoning-lane-coordinator.js +128 -0
  608. package/dist/telegram/send.js +3 -2
  609. package/dist/telegram/sent-message-cache.js +5 -6
  610. package/dist/telegram/status-reaction-variants.js +208 -0
  611. package/dist/telegram/sticker-cache.js +11 -9
  612. package/dist/terminal/prompt-select-styled.js +9 -0
  613. package/dist/terminal/theme.js +12 -12
  614. package/dist/test-utils/command-runner.js +6 -0
  615. package/dist/test-utils/internal-hook-event-payload.js +10 -0
  616. package/dist/test-utils/model-auth-mock.js +12 -0
  617. package/dist/test-utils/provider-usage-fetch.js +14 -0
  618. package/dist/test-utils/temp-home.js +33 -0
  619. package/dist/tts/tts.js +80 -567
  620. package/dist/tui/components/chat-log.js +50 -8
  621. package/dist/tui/theme/theme.js +10 -12
  622. package/dist/tui/tui-command-handlers.js +36 -27
  623. package/dist/tui/tui-event-handlers.js +122 -32
  624. package/dist/tui/tui-local-shell.js +16 -6
  625. package/dist/tui/tui.js +236 -48
  626. package/dist/utils/account-id.js +2 -4
  627. package/dist/utils/boolean.js +10 -5
  628. package/dist/utils/directive-tags.js +11 -0
  629. package/dist/utils/mask-api-key.js +10 -0
  630. package/dist/utils/queue-helpers.js +67 -12
  631. package/dist/utils/run-with-concurrency.js +39 -0
  632. package/dist/web/auto-reply/deliver-reply.js +8 -4
  633. package/dist/web/auto-reply/mentions.js +10 -5
  634. package/dist/web/auto-reply/monitor/group-members.js +14 -7
  635. package/dist/web/auto-reply/monitor/process-message.js +45 -24
  636. package/dist/web/inbound/access-control.js +5 -2
  637. package/dist/web/login-qr.js +12 -6
  638. package/dist/web/media.js +126 -15
  639. package/docs/tools/slash-commands.md +5 -1
  640. package/extensions/bluebubbles/src/monitor-processing.ts +580 -139
  641. package/extensions/bluebubbles/src/monitor.ts +208 -1950
  642. package/extensions/feishu/src/external-keys.ts +19 -0
  643. package/extensions/lobster/src/windows-spawn.ts +193 -0
  644. package/extensions/matrix/src/matrix/actions/limits.ts +6 -0
  645. package/extensions/mattermost/src/mattermost/reactions.test-helpers.ts +83 -0
  646. package/package.json +1 -1
@@ -1,22 +1,27 @@
1
1
  import { normalizeCommandBody } from "./commands-registry.js";
2
2
  export function normalizeGroupActivation(raw) {
3
3
  const value = raw?.trim().toLowerCase();
4
- if (value === "mention")
4
+ if (value === "mention") {
5
5
  return "mention";
6
- if (value === "always")
6
+ }
7
+ if (value === "always") {
7
8
  return "always";
9
+ }
8
10
  return undefined;
9
11
  }
10
12
  export function parseActivationCommand(raw) {
11
- if (!raw)
13
+ if (!raw) {
12
14
  return { hasCommand: false };
15
+ }
13
16
  const trimmed = raw.trim();
14
- if (!trimmed)
17
+ if (!trimmed) {
15
18
  return { hasCommand: false };
19
+ }
16
20
  const normalized = normalizeCommandBody(trimmed);
17
21
  const match = normalized.match(/^\/activation(?:\s+([a-zA-Z]+))?\s*$/i);
18
- if (!match)
22
+ if (!match) {
19
23
  return { hasCommand: false };
24
+ }
20
25
  const mode = normalizeGroupActivation(match[1]);
21
26
  return { hasCommand: true, mode };
22
27
  }
@@ -1,11 +1,13 @@
1
1
  const resolveMs = (value) => {
2
- if (typeof value !== "number" || !Number.isFinite(value))
2
+ if (typeof value !== "number" || !Number.isFinite(value)) {
3
3
  return undefined;
4
+ }
4
5
  return Math.max(0, Math.trunc(value));
5
6
  };
6
7
  const resolveChannelOverride = (params) => {
7
- if (!params.byChannel)
8
+ if (!params.byChannel) {
8
9
  return undefined;
10
+ }
9
11
  return resolveMs(params.byChannel[params.channel]);
10
12
  };
11
13
  export function resolveInboundDebounceMs(params) {
@@ -27,8 +29,9 @@ export function createInboundDebouncer(params) {
27
29
  clearTimeout(buffer.timeout);
28
30
  buffer.timeout = null;
29
31
  }
30
- if (buffer.items.length === 0)
32
+ if (buffer.items.length === 0) {
31
33
  return;
34
+ }
32
35
  try {
33
36
  await params.onFlush(buffer.items);
34
37
  }
@@ -38,13 +41,15 @@ export function createInboundDebouncer(params) {
38
41
  };
39
42
  const flushKey = async (key) => {
40
43
  const buffer = buffers.get(key);
41
- if (!buffer)
44
+ if (!buffer) {
42
45
  return;
46
+ }
43
47
  await flushBuffer(key, buffer);
44
48
  };
45
49
  const scheduleFlush = (key, buffer) => {
46
- if (buffer.timeout)
50
+ if (buffer.timeout) {
47
51
  clearTimeout(buffer.timeout);
52
+ }
48
53
  buffer.timeout = setTimeout(() => {
49
54
  void flushBuffer(key, buffer);
50
55
  }, debounceMs);
@@ -0,0 +1,68 @@
1
+ export function formatProviderModelRef(providerRaw, modelRaw) {
2
+ const provider = String(providerRaw ?? "").trim();
3
+ const model = String(modelRaw ?? "").trim();
4
+ if (!provider) {
5
+ return model;
6
+ }
7
+ if (!model) {
8
+ return provider;
9
+ }
10
+ const prefix = `${provider}/`;
11
+ if (model.toLowerCase().startsWith(prefix.toLowerCase())) {
12
+ const normalizedModel = model.slice(prefix.length).trim();
13
+ if (normalizedModel) {
14
+ return `${provider}/${normalizedModel}`;
15
+ }
16
+ }
17
+ return `${provider}/${model}`;
18
+ }
19
+ function normalizeModelWithinProvider(provider, modelRaw) {
20
+ const model = String(modelRaw ?? "").trim();
21
+ if (!provider || !model) {
22
+ return model;
23
+ }
24
+ const prefix = `${provider}/`;
25
+ if (model.toLowerCase().startsWith(prefix.toLowerCase())) {
26
+ const withoutPrefix = model.slice(prefix.length).trim();
27
+ if (withoutPrefix) {
28
+ return withoutPrefix;
29
+ }
30
+ }
31
+ return model;
32
+ }
33
+ function normalizeModelRef(rawModel, fallbackProvider, parseEmbeddedProvider = false) {
34
+ const trimmed = String(rawModel ?? "").trim();
35
+ const slashIndex = parseEmbeddedProvider ? trimmed.indexOf("/") : -1;
36
+ if (slashIndex > 0) {
37
+ const provider = trimmed.slice(0, slashIndex).trim();
38
+ const model = trimmed.slice(slashIndex + 1).trim();
39
+ if (provider && model) {
40
+ return {
41
+ provider,
42
+ model,
43
+ label: `${provider}/${model}`,
44
+ };
45
+ }
46
+ }
47
+ const provider = String(fallbackProvider ?? "").trim();
48
+ const dedupedModel = normalizeModelWithinProvider(provider, trimmed);
49
+ return {
50
+ provider,
51
+ model: dedupedModel || trimmed,
52
+ label: provider ? formatProviderModelRef(provider, dedupedModel || trimmed) : trimmed,
53
+ };
54
+ }
55
+ export function resolveSelectedAndActiveModel(params) {
56
+ const selected = normalizeModelRef(params.selectedModel, params.selectedProvider);
57
+ const runtimeModel = params.sessionEntry?.model?.trim();
58
+ const runtimeProvider = params.sessionEntry?.modelProvider?.trim();
59
+ const active = runtimeModel
60
+ ? normalizeModelRef(runtimeModel, runtimeProvider || selected.provider, !runtimeProvider)
61
+ : selected;
62
+ const activeDiffers = active.provider !== selected.provider || active.model !== selected.model;
63
+ return {
64
+ selected,
65
+ active,
66
+ activeDiffers,
67
+ };
68
+ }
@@ -79,7 +79,7 @@ export function formatAbortReplyText(stoppedSubagents) {
79
79
  const label = stoppedSubagents === 1 ? "sub-agent" : "sub-agents";
80
80
  return `⚙️ Agent was aborted. Stopped ${stoppedSubagents} ${label}.`;
81
81
  }
82
- function resolveSessionEntryForKey(store, sessionKey) {
82
+ export function resolveSessionEntryForKey(store, sessionKey) {
83
83
  if (!store || !sessionKey) {
84
84
  return {};
85
85
  }
@@ -6,21 +6,23 @@ import { getCliSessionId } from "../../agents/cli-session.js";
6
6
  import { runWithModelFallback } from "../../agents/model-fallback.js";
7
7
  import { isCliProvider } from "../../agents/model-selection.js";
8
8
  import { runEmbeddedPiAgent } from "../../agents/pi-embedded.js";
9
- import { isCompactionFailureError, isContextOverflowError, isLikelyContextOverflowError, sanitizeUserFacingText, } from "../../agents/pi-embedded-helpers.js";
9
+ import { isCompactionFailureError, isContextOverflowError, isLikelyContextOverflowError, isTransientHttpError, sanitizeUserFacingText, } from "../../agents/pi-embedded-helpers.js";
10
10
  import { resolveAgentIdFromSessionKey, resolveGroupSessionKey, resolveSessionTranscriptPath, updateSessionStore, } from "../../config/sessions.js";
11
11
  import { logVerbose } from "../../globals.js";
12
12
  import { emitAgentEvent, registerAgentRunContext } from "../../infra/agent-events.js";
13
13
  import { defaultRuntime } from "../../runtime.js";
14
14
  import { isMarkdownCapableMessageChannel, resolveMessageChannel, } from "../../utils/message-channel.js";
15
15
  import { stripHeartbeatToken } from "../heartbeat.js";
16
- import { isSilentReplyText, SILENT_REPLY_TOKEN } from "../tokens.js";
16
+ import { isSilentReplyPrefixText, isSilentReplyText, SILENT_REPLY_TOKEN } from "../tokens.js";
17
17
  import { buildThreadingToolContext, resolveEnforceFinalTag } from "./agent-runner-utils.js";
18
18
  import { createBlockReplyPayloadKey } from "./block-reply-pipeline.js";
19
19
  import { parseReplyDirectives } from "./reply-directives.js";
20
20
  import { applyReplyTagsToPayload, isRenderablePayload } from "./reply-payloads.js";
21
21
  export async function runAgentTurnWithFallback(params) {
22
+ const TRANSIENT_HTTP_RETRY_DELAY_MS = 2_500;
22
23
  let didLogHeartbeatStrip = false;
23
24
  let autoCompactionCompleted = false;
25
+ let didRetryTransientHttpError = false;
24
26
  // Track payloads sent directly (not via pipeline) during tool flush to avoid duplicates.
25
27
  const directlySentBlockKeys = new Set();
26
28
  const runId = params.opts?.runId ?? crypto.randomUUID();
@@ -36,6 +38,7 @@ export async function runAgentTurnWithFallback(params) {
36
38
  let fallbackProvider = params.followupRun.run.provider;
37
39
  let fallbackModel = params.followupRun.run.model;
38
40
  let didResetAfterCompactionFailure = false;
41
+ let fallbackAttempts = [];
39
42
  while (true) {
40
43
  try {
41
44
  const allowPartialStream = !(params.followupRun.run.reasoningLevel === "stream" && params.opts?.onReasoningStream);
@@ -59,14 +62,21 @@ export async function runAgentTurnWithFallback(params) {
59
62
  if (isSilentReplyText(text, SILENT_REPLY_TOKEN)) {
60
63
  return { skip: true };
61
64
  }
62
- if (!text)
65
+ if (!text) {
66
+ // Allow media-only payloads through (no text but has media)
67
+ if (payload.mediaUrls?.length)
68
+ return { text: undefined, skip: false };
63
69
  return { skip: true };
64
- const sanitized = sanitizeUserFacingText(text);
70
+ }
71
+ const sanitized = sanitizeUserFacingText(text, { errorContext: Boolean(payload.isError) });
65
72
  if (!sanitized.trim())
66
73
  return { skip: true };
67
74
  return { text: sanitized, skip: false };
68
75
  };
69
76
  const handlePartialForTyping = async (payload) => {
77
+ if (isSilentReplyPrefixText(payload.text, SILENT_REPLY_TOKEN)) {
78
+ return undefined;
79
+ }
70
80
  const { text, skip } = normalizeStreamingText(payload);
71
81
  if (skip || !text)
72
82
  return undefined;
@@ -112,6 +122,7 @@ export async function runAgentTurnWithFallback(params) {
112
122
  thinkLevel: params.followupRun.run.thinkLevel,
113
123
  timeoutMs: params.followupRun.run.timeoutMs,
114
124
  runId,
125
+ agentId: resolveAgentIdFromSessionKey(params.followupRun.run.sessionKey),
115
126
  extraSystemPrompt: params.followupRun.run.extraSystemPrompt,
116
127
  ownerNumbers: params.followupRun.run.ownerNumbers,
117
128
  cliSessionId,
@@ -348,6 +359,16 @@ export async function runAgentTurnWithFallback(params) {
348
359
  runResult = fallbackResult.result;
349
360
  fallbackProvider = fallbackResult.provider;
350
361
  fallbackModel = fallbackResult.model;
362
+ fallbackAttempts = Array.isArray(fallbackResult.attempts)
363
+ ? fallbackResult.attempts.map((attempt) => ({
364
+ provider: String(attempt.provider ?? ""),
365
+ model: String(attempt.model ?? ""),
366
+ error: String(attempt.error ?? ""),
367
+ reason: attempt.reason ? String(attempt.reason) : undefined,
368
+ status: typeof attempt.status === "number" ? attempt.status : undefined,
369
+ code: attempt.code ? String(attempt.code) : undefined,
370
+ }))
371
+ : [];
351
372
  // Some embedded runs surface context overflow as an error payload instead of throwing.
352
373
  // Treat those as a session-level failure and auto-recover by starting a fresh session.
353
374
  const embeddedError = runResult.meta?.error;
@@ -382,6 +403,7 @@ export async function runAgentTurnWithFallback(params) {
382
403
  const isCompactionFailure = isCompactionFailureError(message);
383
404
  const isSessionCorruption = /function call turn comes immediately after/i.test(message);
384
405
  const isRoleOrderingError = /incorrect role information|roles must alternate/i.test(message);
406
+ const isTransientHttp = isTransientHttpError(message);
385
407
  if (isCompactionFailure &&
386
408
  !didResetAfterCompactionFailure &&
387
409
  (await params.resetSessionAfterCompactionFailure(message))) {
@@ -404,6 +426,14 @@ export async function runAgentTurnWithFallback(params) {
404
426
  };
405
427
  }
406
428
  }
429
+ if (isTransientHttp && !didRetryTransientHttpError) {
430
+ didRetryTransientHttpError = true;
431
+ defaultRuntime.error(`Transient HTTP provider error before reply (${message}). Retrying once in ${TRANSIENT_HTTP_RETRY_DELAY_MS}ms.`);
432
+ await new Promise((resolve) => {
433
+ setTimeout(resolve, TRANSIENT_HTTP_RETRY_DELAY_MS);
434
+ });
435
+ continue;
436
+ }
407
437
  // Auto-recover from Gemini session corruption by resetting the session
408
438
  if (isSessionCorruption &&
409
439
  params.sessionKey &&
@@ -441,7 +471,10 @@ export async function runAgentTurnWithFallback(params) {
441
471
  };
442
472
  }
443
473
  defaultRuntime.error(`Embedded agent failed before reply: ${message}`);
444
- const trimmedMessage = message.replace(/\.\s*$/, "");
474
+ const safeMessage = isTransientHttp
475
+ ? sanitizeUserFacingText(message, { errorContext: true })
476
+ : message;
477
+ const trimmedMessage = safeMessage.replace(/\.\s*$/, "");
445
478
  const fallbackText = isContextOverflow
446
479
  ? "⚠️ Context overflow — prompt too large for this model. Try a shorter message or a larger-context model."
447
480
  : isRoleOrderingError
@@ -460,6 +493,8 @@ export async function runAgentTurnWithFallback(params) {
460
493
  runResult,
461
494
  fallbackProvider,
462
495
  fallbackModel,
496
+ runId,
497
+ fallbackAttempts,
463
498
  didLogHeartbeatStrip,
464
499
  autoCompactionCompleted,
465
500
  directlySentBlockKeys: directlySentBlockKeys.size > 0 ? directlySentBlockKeys : undefined,
@@ -7,8 +7,11 @@ import { isCliProvider } from "../../agents/model-selection.js";
7
7
  import { queueEmbeddedPiMessage } from "../../agents/pi-embedded.js";
8
8
  import { hasNonzeroUsage } from "../../agents/usage.js";
9
9
  import { resolveAgentIdFromSessionKey, resolveSessionFilePath, resolveSessionTranscriptPath, updateSessionStore, updateSessionStoreEntry, } from "../../config/sessions.js";
10
+ import { emitAgentEvent } from "../../infra/agent-events.js";
11
+ import { emitDiagnosticEvent, isDiagnosticsEnabled } from "../../infra/diagnostic-events.js";
10
12
  import { defaultRuntime } from "../../runtime.js";
11
13
  import { estimateUsageCost, resolveModelCostConfig } from "../../utils/usage-format.js";
14
+ import { buildFallbackClearedNotice, buildFallbackNotice, resolveFallbackTransition, } from "../fallback-state.js";
12
15
  import { resolveResponseUsageMode } from "../thinking.js";
13
16
  import { runAgentTurnWithFallback } from "./agent-runner-execution.js";
14
17
  import { createShouldEmitToolOutput, createShouldEmitToolResult, finalizeWithFollowup, isAudioPayload, signalTypingIfNeeded, } from "./agent-runner-helpers.js";
@@ -20,11 +23,41 @@ import { resolveBlockStreamingCoalescing } from "./block-streaming.js";
20
23
  import { createFollowupRunner } from "./followup-runner.js";
21
24
  import { enqueueFollowupRun } from "./queue.js";
22
25
  import { createReplyToModeFilterForChannel, resolveReplyToMode } from "./reply-threading.js";
23
- import { persistSessionUsageUpdate } from "./session-usage.js";
24
- import { incrementCompactionCount } from "./session-updates.js";
26
+ import { incrementRunCompactionCount, persistRunSessionUsage } from "./session-run-accounting.js";
25
27
  import { createTypingSignaler } from "./typing-mode.js";
26
- import { emitDiagnosticEvent, isDiagnosticsEnabled } from "../../infra/diagnostic-events.js";
27
28
  const BLOCK_REPLY_SEND_TIMEOUT_MS = 15_000;
29
+ const UNSCHEDULED_REMINDER_NOTE = "Note: I did not schedule a reminder in this turn, so this will not trigger automatically.";
30
+ const REMINDER_COMMITMENT_PATTERNS = [
31
+ /\b(?:i\s*['']?ll|i will)\s+(?:make sure to\s+)?(?:remember|remind|ping|follow up|follow-up|check back|circle back)\b/i,
32
+ /\b(?:i\s*['']?ll|i will)\s+(?:set|create|schedule)\s+(?:a\s+)?reminder\b/i,
33
+ ];
34
+ function hasUnbackedReminderCommitment(text) {
35
+ const normalized = text.toLowerCase();
36
+ if (!normalized.trim()) {
37
+ return false;
38
+ }
39
+ if (normalized.includes(UNSCHEDULED_REMINDER_NOTE.toLowerCase())) {
40
+ return false;
41
+ }
42
+ return REMINDER_COMMITMENT_PATTERNS.some((pattern) => pattern.test(text));
43
+ }
44
+ function appendUnscheduledReminderNote(payloads) {
45
+ let appended = false;
46
+ return payloads.map((payload) => {
47
+ if (appended || payload.isError || typeof payload.text !== "string") {
48
+ return payload;
49
+ }
50
+ if (!hasUnbackedReminderCommitment(payload.text)) {
51
+ return payload;
52
+ }
53
+ appended = true;
54
+ const trimmed = payload.text.trimEnd();
55
+ return {
56
+ ...payload,
57
+ text: `${trimmed}\n\n${UNSCHEDULED_REMINDER_NOTE}`,
58
+ };
59
+ });
60
+ }
28
61
  export async function runReplyAgent(params) {
29
62
  const { commandBody, followupRun, queueKey, resolvedQueue, shouldSteer, shouldFollowup, isActive, isStreaming, opts, typing, sessionEntry, sessionStore, sessionKey, storePath, defaultModel, agentCfgContextTokens, resolvedVerboseLevel, isNewSession, blockStreamingEnabled, blockReplyChunking, resolvedBlockStreamingBreak, sessionCtx, shouldInjectGroupIntro, typingMode, } = params;
30
63
  let activeSessionEntry = sessionEntry;
@@ -64,27 +97,7 @@ export async function runReplyAgent(params) {
64
97
  buffer: createAudioAsVoiceBuffer({ isAudioPayload }),
65
98
  })
66
99
  : null;
67
- if (shouldSteer && isStreaming) {
68
- const steered = queueEmbeddedPiMessage(followupRun.run.sessionId, followupRun.prompt);
69
- if (steered && !shouldFollowup) {
70
- if (activeSessionEntry && activeSessionStore && sessionKey) {
71
- const updatedAt = Date.now();
72
- activeSessionEntry.updatedAt = updatedAt;
73
- activeSessionStore[sessionKey] = activeSessionEntry;
74
- if (storePath) {
75
- await updateSessionStoreEntry({
76
- storePath,
77
- sessionKey,
78
- update: async () => ({ updatedAt }),
79
- });
80
- }
81
- }
82
- typing.cleanup();
83
- return undefined;
84
- }
85
- }
86
- if (isActive && (shouldFollowup || resolvedQueue.mode === "steer")) {
87
- enqueueFollowupRun(queueKey, followupRun, resolvedQueue);
100
+ const touchActiveSessionEntry = async () => {
88
101
  if (activeSessionEntry && activeSessionStore && sessionKey) {
89
102
  const updatedAt = Date.now();
90
103
  activeSessionEntry.updatedAt = updatedAt;
@@ -97,6 +110,18 @@ export async function runReplyAgent(params) {
97
110
  });
98
111
  }
99
112
  }
113
+ };
114
+ if (shouldSteer && isStreaming) {
115
+ const steered = queueEmbeddedPiMessage(followupRun.run.sessionId, followupRun.prompt);
116
+ if (steered && !shouldFollowup) {
117
+ await touchActiveSessionEntry();
118
+ typing.cleanup();
119
+ return undefined;
120
+ }
121
+ }
122
+ if (isActive && (shouldFollowup || resolvedQueue.mode === "steer")) {
123
+ enqueueFollowupRun(queueKey, followupRun, resolvedQueue);
124
+ await touchActiveSessionEntry();
100
125
  typing.cleanup();
101
126
  return undefined;
102
127
  }
@@ -141,6 +166,9 @@ export async function runReplyAgent(params) {
141
166
  updatedAt: Date.now(),
142
167
  systemSent: false,
143
168
  abortedLastRun: false,
169
+ fallbackNoticeSelectedModel: undefined,
170
+ fallbackNoticeActiveModel: undefined,
171
+ fallbackNoticeReason: undefined,
144
172
  };
145
173
  const agentId = resolveAgentIdFromSessionKey(sessionKey);
146
174
  const nextSessionFile = resolveSessionTranscriptPath(nextSessionId, agentId, sessionCtx.MessageThreadId);
@@ -213,7 +241,7 @@ export async function runReplyAgent(params) {
213
241
  if (runOutcome.kind === "final") {
214
242
  return finalizeWithFollowup(runOutcome.payload, queueKey, runFollowupTurn);
215
243
  }
216
- const { runResult, fallbackProvider, fallbackModel, directlySentBlockKeys } = runOutcome;
244
+ const { runId, runResult, fallbackProvider, fallbackModel, fallbackAttempts, directlySentBlockKeys, } = runOutcome;
217
245
  let { didLogHeartbeatStrip, autoCompactionCompleted } = runOutcome;
218
246
  if (shouldInjectGroupIntro &&
219
247
  activeSessionEntry &&
@@ -243,24 +271,62 @@ export async function runReplyAgent(params) {
243
271
  if (pendingToolTasks.size > 0) {
244
272
  await Promise.allSettled(pendingToolTasks);
245
273
  }
246
- const usage = runResult.meta.agentMeta?.usage;
247
- const modelUsed = runResult.meta.agentMeta?.model ?? fallbackModel ?? defaultModel;
248
- const providerUsed = runResult.meta.agentMeta?.provider ?? fallbackProvider ?? followupRun.run.provider;
274
+ const usage = runResult.meta?.agentMeta?.usage;
275
+ const promptTokens = runResult.meta?.agentMeta?.promptTokens;
276
+ const modelUsed = runResult.meta?.agentMeta?.model ?? fallbackModel ?? defaultModel;
277
+ const providerUsed = runResult.meta?.agentMeta?.provider ?? fallbackProvider ?? followupRun.run.provider;
278
+ const verboseEnabled = resolvedVerboseLevel !== "off";
279
+ const selectedProvider = followupRun.run.provider;
280
+ const selectedModel = followupRun.run.model;
281
+ const fallbackStateEntry = activeSessionEntry ?? (sessionKey ? activeSessionStore?.[sessionKey] : undefined);
282
+ const fallbackTransition = resolveFallbackTransition({
283
+ selectedProvider,
284
+ selectedModel,
285
+ activeProvider: providerUsed,
286
+ activeModel: modelUsed,
287
+ attempts: fallbackAttempts,
288
+ state: fallbackStateEntry,
289
+ });
290
+ if (fallbackTransition.stateChanged) {
291
+ if (fallbackStateEntry) {
292
+ fallbackStateEntry.fallbackNoticeSelectedModel = fallbackTransition.nextState.selectedModel;
293
+ fallbackStateEntry.fallbackNoticeActiveModel = fallbackTransition.nextState.activeModel;
294
+ fallbackStateEntry.fallbackNoticeReason = fallbackTransition.nextState.reason;
295
+ fallbackStateEntry.updatedAt = Date.now();
296
+ activeSessionEntry = fallbackStateEntry;
297
+ }
298
+ if (sessionKey && fallbackStateEntry && activeSessionStore) {
299
+ activeSessionStore[sessionKey] = fallbackStateEntry;
300
+ }
301
+ if (sessionKey && storePath) {
302
+ await updateSessionStoreEntry({
303
+ storePath,
304
+ sessionKey,
305
+ update: async () => ({
306
+ fallbackNoticeSelectedModel: fallbackTransition.nextState.selectedModel,
307
+ fallbackNoticeActiveModel: fallbackTransition.nextState.activeModel,
308
+ fallbackNoticeReason: fallbackTransition.nextState.reason,
309
+ }),
310
+ });
311
+ }
312
+ }
249
313
  const cliSessionId = isCliProvider(providerUsed, cfg)
250
- ? runResult.meta.agentMeta?.sessionId?.trim()
314
+ ? runResult.meta?.agentMeta?.sessionId?.trim()
251
315
  : undefined;
252
316
  const contextTokensUsed = agentCfgContextTokens ??
253
317
  lookupContextTokens(modelUsed) ??
254
318
  activeSessionEntry?.contextTokens ??
255
319
  DEFAULT_CONTEXT_TOKENS;
256
- await persistSessionUsageUpdate({
320
+ await persistRunSessionUsage({
257
321
  storePath,
258
322
  sessionKey,
259
323
  usage,
324
+ lastCallUsage: runResult.meta?.agentMeta?.lastCallUsage,
325
+ promptTokens,
260
326
  modelUsed,
261
327
  providerUsed,
262
328
  contextTokensUsed,
263
- systemPromptReport: runResult.meta.systemPromptReport,
329
+ systemPromptReport: runResult.meta?.systemPromptReport,
264
330
  cliSessionId,
265
331
  });
266
332
  // Drain any late tool/block deliveries before deciding there's "nothing to send".
@@ -288,7 +354,14 @@ export async function runReplyAgent(params) {
288
354
  didLogHeartbeatStrip = payloadResult.didLogHeartbeatStrip;
289
355
  if (replyPayloads.length === 0)
290
356
  return finalizeWithFollowup(undefined, queueKey, runFollowupTurn);
291
- await signalTypingIfNeeded(replyPayloads, typingSignals);
357
+ const successfulCronAdds = runResult.successfulCronAdds ?? 0;
358
+ const hasReminderCommitment = replyPayloads.some((payload) => !payload.isError &&
359
+ typeof payload.text === "string" &&
360
+ hasUnbackedReminderCommitment(payload.text));
361
+ const guardedReplyPayloads = hasReminderCommitment && successfulCronAdds === 0
362
+ ? appendUnscheduledReminderNote(replyPayloads)
363
+ : replyPayloads;
364
+ await signalTypingIfNeeded(guardedReplyPayloads, typingSignals);
292
365
  if (isDiagnosticsEnabled(cfg) && hasNonzeroUsage(usage)) {
293
366
  const input = usage.input ?? 0;
294
367
  const output = usage.output ?? 0;
@@ -323,6 +396,7 @@ export async function runReplyAgent(params) {
323
396
  },
324
397
  costUsd,
325
398
  durationMs: Date.now() - runStartedAt,
399
+ lastCallUsage: runResult.meta?.agentMeta?.lastCallUsage,
326
400
  });
327
401
  }
328
402
  const responseUsageRaw = activeSessionEntry?.responseUsage ??
@@ -349,23 +423,75 @@ export async function runReplyAgent(params) {
349
423
  if (formatted)
350
424
  responseUsageLine = formatted;
351
425
  }
352
- // If verbose is enabled and this is a new session, prepend a session hint.
353
- let finalPayloads = replyPayloads;
354
- const verboseEnabled = resolvedVerboseLevel !== "off";
426
+ let finalPayloads = guardedReplyPayloads;
427
+ const verboseNotices = [];
428
+ if (activeIsNewSession && verboseEnabled) {
429
+ verboseNotices.push(`🧭 New session: ${followupRun.run.sessionId}`);
430
+ }
431
+ if (fallbackTransition.fallbackTransitioned) {
432
+ const notice = buildFallbackNotice({
433
+ selectedProvider,
434
+ selectedModel,
435
+ activeProvider: providerUsed,
436
+ activeModel: modelUsed,
437
+ attempts: fallbackAttempts,
438
+ });
439
+ if (runId) {
440
+ emitAgentEvent({
441
+ runId,
442
+ stream: "lifecycle",
443
+ data: {
444
+ kind: "model.fallback.transitioned",
445
+ selected: fallbackTransition.selectedModelRef,
446
+ active: fallbackTransition.activeModelRef,
447
+ reason: fallbackTransition.reasonSummary,
448
+ attempts: fallbackTransition.attemptSummaries,
449
+ },
450
+ sessionKey,
451
+ });
452
+ }
453
+ if (notice && verboseEnabled) {
454
+ verboseNotices.push(notice);
455
+ }
456
+ }
457
+ if (fallbackTransition.fallbackCleared) {
458
+ const notice = buildFallbackClearedNotice({
459
+ selectedProvider,
460
+ selectedModel,
461
+ previousActiveModel: fallbackTransition.previousState.activeModel,
462
+ });
463
+ if (runId) {
464
+ emitAgentEvent({
465
+ runId,
466
+ stream: "lifecycle",
467
+ data: {
468
+ kind: "model.fallback.cleared",
469
+ selected: fallbackTransition.selectedModelRef,
470
+ previousActive: fallbackTransition.previousState.activeModel,
471
+ },
472
+ sessionKey,
473
+ });
474
+ }
475
+ if (verboseEnabled) {
476
+ verboseNotices.push(notice);
477
+ }
478
+ }
355
479
  if (autoCompactionCompleted) {
356
- const count = await incrementCompactionCount({
480
+ const count = await incrementRunCompactionCount({
357
481
  sessionEntry: activeSessionEntry,
358
482
  sessionStore: activeSessionStore,
359
483
  sessionKey,
360
484
  storePath,
485
+ lastCallUsage: runResult.meta?.agentMeta?.lastCallUsage,
486
+ contextTokensUsed,
361
487
  });
362
488
  if (verboseEnabled) {
363
489
  const suffix = typeof count === "number" ? ` (count ${count})` : "";
364
- finalPayloads = [{ text: `🧹 Auto-compaction complete${suffix}.` }, ...finalPayloads];
490
+ verboseNotices.push(`🧹 Auto-compaction complete${suffix}.`);
365
491
  }
366
492
  }
367
- if (verboseEnabled && activeIsNewSession) {
368
- finalPayloads = [{ text: `🧭 New session: ${followupRun.run.sessionId}` }, ...finalPayloads];
493
+ if (verboseNotices.length > 0) {
494
+ finalPayloads = [...verboseNotices.map((text) => ({ text })), ...finalPayloads];
369
495
  }
370
496
  if (responseUsageLine) {
371
497
  finalPayloads = appendUsageLine(finalPayloads, responseUsageLine);