@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,5 +1,6 @@
1
1
  import { ChannelType } from "@buape/carbon";
2
2
  import { resolveAckReaction, resolveHumanDelayConfig } from "../../agents/identity.js";
3
+ import { EmbeddedBlockChunker } from "../../agents/pi-embedded-block-chunker.js";
3
4
  import { resolveChunkMode } from "../../auto-reply/chunk.js";
4
5
  import { dispatchInboundMessage } from "../../auto-reply/dispatch.js";
5
6
  import { formatInboundEnvelope, resolveEnvelopeFormatOptions } from "../../auto-reply/envelope.js";
@@ -10,15 +11,22 @@ import { shouldAckReaction as shouldAckReactionGate } from "../../channels/ack-r
10
11
  import { logTypingFailure, logAckFailure } from "../../channels/logging.js";
11
12
  import { createReplyPrefixOptions } from "../../channels/reply-prefix.js";
12
13
  import { recordInboundSession } from "../../channels/session.js";
14
+ import { createStatusReactionController, DEFAULT_TIMING, } from "../../channels/status-reactions.js";
13
15
  import { createTypingCallbacks } from "../../channels/typing.js";
16
+ import { resolveDiscordPreviewStreamMode } from "../../config/discord-preview-streaming.js";
14
17
  import { resolveMarkdownTableMode } from "../../config/markdown-tables.js";
15
18
  import { readSessionUpdatedAt, resolveStorePath } from "../../config/sessions.js";
16
19
  import { danger, logVerbose, shouldLogVerbose } from "../../globals.js";
20
+ import { convertMarkdownTables } from "../../markdown/tables.js";
17
21
  import { buildAgentSessionKey } from "../../routing/resolve-route.js";
18
22
  import { resolveThreadSessionKeys } from "../../routing/session-key.js";
19
23
  import { buildUntrustedChannelMetadata } from "../../security/channel-metadata.js";
20
24
  import { truncateUtf16Safe } from "../../utils.js";
25
+ import { chunkDiscordTextWithMode } from "../chunk.js";
26
+ import { resolveDiscordDraftStreamingChunking } from "../draft-chunking.js";
27
+ import { createDiscordDraftStream } from "../draft-stream.js";
21
28
  import { reactMessageDiscord, removeReactionDiscord } from "../send.js";
29
+ import { editMessageDiscord } from "../send.messages.js";
22
30
  import { normalizeDiscordSlug, resolveDiscordOwnerAllowFrom } from "./allow-list.js";
23
31
  import { resolveTimestampMs } from "./format.js";
24
32
  import { buildDiscordMediaPayload, resolveDiscordMessageText, resolveForwardedMediaList, resolveMediaList, } from "./message-utils.js";
@@ -26,219 +34,13 @@ import { buildDirectLabel, buildGuildLabel, resolveReplyContext } from "./reply-
26
34
  import { deliverDiscordReply } from "./reply-delivery.js";
27
35
  import { resolveDiscordAutoThreadReplyPlan, resolveDiscordThreadStarter } from "./threading.js";
28
36
  import { sendTyping } from "./typing.js";
29
- const DISCORD_STATUS_THINKING_EMOJI = "🧠";
30
- const DISCORD_STATUS_TOOL_EMOJI = "🛠️";
31
- const DISCORD_STATUS_CODING_EMOJI = "💻";
32
- const DISCORD_STATUS_WEB_EMOJI = "🌐";
33
- const DISCORD_STATUS_DONE_EMOJI = "✅";
34
- const DISCORD_STATUS_ERROR_EMOJI = "❌";
35
- const DISCORD_STATUS_STALL_SOFT_EMOJI = "⏳";
36
- const DISCORD_STATUS_STALL_HARD_EMOJI = "⚠️";
37
- const DISCORD_STATUS_DONE_HOLD_MS = 1500;
38
- const DISCORD_STATUS_ERROR_HOLD_MS = 2500;
39
- const DISCORD_STATUS_DEBOUNCE_MS = 700;
40
- const DISCORD_STATUS_STALL_SOFT_MS = 10_000;
41
- const DISCORD_STATUS_STALL_HARD_MS = 30_000;
42
- const CODING_STATUS_TOOL_TOKENS = [
43
- "exec",
44
- "process",
45
- "read",
46
- "write",
47
- "edit",
48
- "session_status",
49
- "bash",
50
- ];
51
- const WEB_STATUS_TOOL_TOKENS = ["web_search", "web-search", "web_fetch", "web-fetch", "browser"];
52
- function resolveToolStatusEmoji(toolName) {
53
- const normalized = toolName?.trim().toLowerCase() ?? "";
54
- if (!normalized) {
55
- return DISCORD_STATUS_TOOL_EMOJI;
56
- }
57
- if (WEB_STATUS_TOOL_TOKENS.some((token) => normalized.includes(token))) {
58
- return DISCORD_STATUS_WEB_EMOJI;
59
- }
60
- if (CODING_STATUS_TOOL_TOKENS.some((token) => normalized.includes(token))) {
61
- return DISCORD_STATUS_CODING_EMOJI;
62
- }
63
- return DISCORD_STATUS_TOOL_EMOJI;
64
- }
65
37
  function sleep(ms) {
66
38
  return new Promise((resolve) => {
67
39
  setTimeout(resolve, ms);
68
40
  });
69
41
  }
70
- function createDiscordStatusReactionController(params) {
71
- let activeEmoji = null;
72
- let chain = Promise.resolve();
73
- let pendingEmoji = null;
74
- let pendingTimer = null;
75
- let finished = false;
76
- let softStallTimer = null;
77
- let hardStallTimer = null;
78
- const enqueue = (work) => {
79
- chain = chain.then(work).catch((err) => {
80
- logAckFailure({
81
- log: logVerbose,
82
- channel: "discord",
83
- target: `${params.channelId}/${params.messageId}`,
84
- error: err,
85
- });
86
- });
87
- return chain;
88
- };
89
- const clearStallTimers = () => {
90
- if (softStallTimer) {
91
- clearTimeout(softStallTimer);
92
- softStallTimer = null;
93
- }
94
- if (hardStallTimer) {
95
- clearTimeout(hardStallTimer);
96
- hardStallTimer = null;
97
- }
98
- };
99
- const clearPendingDebounce = () => {
100
- if (pendingTimer) {
101
- clearTimeout(pendingTimer);
102
- pendingTimer = null;
103
- }
104
- pendingEmoji = null;
105
- };
106
- const applyEmoji = (emoji) => enqueue(async () => {
107
- if (!params.enabled || !emoji || activeEmoji === emoji) {
108
- return;
109
- }
110
- const previousEmoji = activeEmoji;
111
- await reactMessageDiscord(params.channelId, params.messageId, emoji, {
112
- rest: params.rest,
113
- });
114
- activeEmoji = emoji;
115
- if (previousEmoji && previousEmoji !== emoji) {
116
- await removeReactionDiscord(params.channelId, params.messageId, previousEmoji, {
117
- rest: params.rest,
118
- });
119
- }
120
- });
121
- const requestEmoji = (emoji, options) => {
122
- if (!params.enabled || !emoji) {
123
- return Promise.resolve();
124
- }
125
- if (options?.immediate) {
126
- clearPendingDebounce();
127
- return applyEmoji(emoji);
128
- }
129
- pendingEmoji = emoji;
130
- if (pendingTimer) {
131
- clearTimeout(pendingTimer);
132
- }
133
- pendingTimer = setTimeout(() => {
134
- pendingTimer = null;
135
- const emojiToApply = pendingEmoji;
136
- pendingEmoji = null;
137
- if (!emojiToApply || emojiToApply === activeEmoji) {
138
- return;
139
- }
140
- void applyEmoji(emojiToApply);
141
- }, DISCORD_STATUS_DEBOUNCE_MS);
142
- return Promise.resolve();
143
- };
144
- const scheduleStallTimers = () => {
145
- if (!params.enabled || finished) {
146
- return;
147
- }
148
- clearStallTimers();
149
- softStallTimer = setTimeout(() => {
150
- if (finished) {
151
- return;
152
- }
153
- void requestEmoji(DISCORD_STATUS_STALL_SOFT_EMOJI, { immediate: true });
154
- }, DISCORD_STATUS_STALL_SOFT_MS);
155
- hardStallTimer = setTimeout(() => {
156
- if (finished) {
157
- return;
158
- }
159
- void requestEmoji(DISCORD_STATUS_STALL_HARD_EMOJI, { immediate: true });
160
- }, DISCORD_STATUS_STALL_HARD_MS);
161
- };
162
- const setPhase = (emoji) => {
163
- if (!params.enabled || finished) {
164
- return Promise.resolve();
165
- }
166
- scheduleStallTimers();
167
- return requestEmoji(emoji);
168
- };
169
- const setTerminal = async (emoji) => {
170
- if (!params.enabled) {
171
- return;
172
- }
173
- finished = true;
174
- clearStallTimers();
175
- await requestEmoji(emoji, { immediate: true });
176
- };
177
- const clear = async () => {
178
- if (!params.enabled) {
179
- return;
180
- }
181
- finished = true;
182
- clearStallTimers();
183
- clearPendingDebounce();
184
- await enqueue(async () => {
185
- const cleanupCandidates = new Set([
186
- params.initialEmoji,
187
- activeEmoji ?? "",
188
- DISCORD_STATUS_THINKING_EMOJI,
189
- DISCORD_STATUS_TOOL_EMOJI,
190
- DISCORD_STATUS_CODING_EMOJI,
191
- DISCORD_STATUS_WEB_EMOJI,
192
- DISCORD_STATUS_DONE_EMOJI,
193
- DISCORD_STATUS_ERROR_EMOJI,
194
- DISCORD_STATUS_STALL_SOFT_EMOJI,
195
- DISCORD_STATUS_STALL_HARD_EMOJI,
196
- ]);
197
- activeEmoji = null;
198
- for (const emoji of cleanupCandidates) {
199
- if (!emoji) {
200
- continue;
201
- }
202
- try {
203
- await removeReactionDiscord(params.channelId, params.messageId, emoji, {
204
- rest: params.rest,
205
- });
206
- }
207
- catch (err) {
208
- logAckFailure({
209
- log: logVerbose,
210
- channel: "discord",
211
- target: `${params.channelId}/${params.messageId}`,
212
- error: err,
213
- });
214
- }
215
- }
216
- });
217
- };
218
- const restoreInitial = async () => {
219
- if (!params.enabled) {
220
- return;
221
- }
222
- finished = true;
223
- clearStallTimers();
224
- clearPendingDebounce();
225
- await requestEmoji(params.initialEmoji, { immediate: true });
226
- };
227
- return {
228
- setQueued: () => {
229
- scheduleStallTimers();
230
- return requestEmoji(params.initialEmoji, { immediate: true });
231
- },
232
- setThinking: () => setPhase(DISCORD_STATUS_THINKING_EMOJI),
233
- setTool: (toolName) => setPhase(resolveToolStatusEmoji(toolName)),
234
- setDone: () => setTerminal(DISCORD_STATUS_DONE_EMOJI),
235
- setError: () => setTerminal(DISCORD_STATUS_ERROR_EMOJI),
236
- clear,
237
- restoreInitial,
238
- };
239
- }
240
42
  export async function processDiscordMessage(ctx) {
241
- const { cfg, discordConfig, accountId, token, runtime, guildHistories, historyLimit, mediaMaxBytes, textLimit, replyToMode, ackReactionScope, message, author, sender, data, client, channelInfo, channelName, messageChannelId, isGuildMessage, isDirectMessage, isGroupDm, baseText, messageText, shouldRequireMention, canDetectMention, effectiveWasMentioned, shouldBypassMention, threadChannel, threadParentId, threadParentName, threadParentType, threadName, displayChannelSlug, guildInfo, guildSlug, channelConfig, baseSessionKey, route, commandAuthorized, } = ctx;
43
+ const { cfg, discordConfig, accountId, token, runtime, guildHistories, historyLimit, mediaMaxBytes, textLimit, replyToMode, ackReactionScope, message, author, sender, data, client, channelInfo, channelName, messageChannelId, isGuildMessage, isDirectMessage, isGroupDm, baseText, messageText, shouldRequireMention, canDetectMention, effectiveWasMentioned, shouldBypassMention, threadChannel, threadParentId, threadParentName, threadParentType, threadName, displayChannelSlug, guildInfo, guildSlug, channelConfig, baseSessionKey, boundSessionKey, threadBindings, route, commandAuthorized, } = ctx;
242
44
  const mediaList = await resolveMediaList(message, mediaMaxBytes);
243
45
  const forwardedMediaList = await resolveForwardedMediaList(message, mediaMaxBytes);
244
46
  mediaList.push(...forwardedMediaList);
@@ -264,12 +66,30 @@ export async function processDiscordMessage(ctx) {
264
66
  shouldBypassMention,
265
67
  }));
266
68
  const statusReactionsEnabled = shouldAckReaction();
267
- const statusReactions = createDiscordStatusReactionController({
69
+ const discordAdapter = {
70
+ setReaction: async (emoji) => {
71
+ await reactMessageDiscord(messageChannelId, message.id, emoji, {
72
+ rest: client.rest,
73
+ });
74
+ },
75
+ removeReaction: async (emoji) => {
76
+ await removeReactionDiscord(messageChannelId, message.id, emoji, {
77
+ rest: client.rest,
78
+ });
79
+ },
80
+ };
81
+ const statusReactions = createStatusReactionController({
268
82
  enabled: statusReactionsEnabled,
269
- channelId: messageChannelId,
270
- messageId: message.id,
83
+ adapter: discordAdapter,
271
84
  initialEmoji: ackReaction,
272
- rest: client.rest,
85
+ onError: (err) => {
86
+ logAckFailure({
87
+ log: logVerbose,
88
+ channel: "discord",
89
+ target: `${messageChannelId}/${message.id}`,
90
+ error: err,
91
+ });
92
+ },
273
93
  });
274
94
  if (statusReactionsEnabled) {
275
95
  void statusReactions.setQueued();
@@ -430,7 +250,7 @@ export async function processDiscordMessage(ctx) {
430
250
  CommandBody: baseText,
431
251
  From: effectiveFrom,
432
252
  To: effectiveTo,
433
- SessionKey: autoThreadContext?.SessionKey ?? threadKeys.sessionKey,
253
+ SessionKey: boundSessionKey ?? autoThreadContext?.SessionKey ?? threadKeys.sessionKey,
434
254
  AccountId: route.accountId,
435
255
  ChatType: isDirectMessage ? "direct" : "channel",
436
256
  ConversationLabel: fromLabel,
@@ -452,6 +272,7 @@ export async function processDiscordMessage(ctx) {
452
272
  ReplyToBody: replyContext?.body,
453
273
  ReplyToSender: replyContext?.sender,
454
274
  ParentSessionKey: autoThreadContext?.ParentSessionKey ?? threadKeys.parentSessionKey,
275
+ MessageThreadId: threadChannel?.id ?? autoThreadContext?.createdThreadId ?? undefined,
455
276
  ThreadStarterBody: threadStarterBody,
456
277
  ThreadLabel: threadLabel,
457
278
  Timestamp: resolveTimestampMs(message.timestamp),
@@ -495,6 +316,7 @@ export async function processDiscordMessage(ctx) {
495
316
  channel: "discord",
496
317
  accountId,
497
318
  });
319
+ const chunkMode = resolveChunkMode(cfg, "discord", accountId);
498
320
  const typingCallbacks = createTypingCallbacks({
499
321
  start: () => sendTyping({ client, channelId: typingChannelId }),
500
322
  onStartError: (err) => {
@@ -506,10 +328,185 @@ export async function processDiscordMessage(ctx) {
506
328
  });
507
329
  },
508
330
  });
331
+ // --- Discord draft stream (edit-based preview streaming) ---
332
+ const discordStreamMode = resolveDiscordPreviewStreamMode(discordConfig);
333
+ const draftMaxChars = Math.min(textLimit, 2000);
334
+ const accountBlockStreamingEnabled = typeof discordConfig?.blockStreaming === "boolean"
335
+ ? discordConfig.blockStreaming
336
+ : cfg.agents?.defaults?.blockStreamingDefault === "on";
337
+ const canStreamDraft = discordStreamMode !== "off" && !accountBlockStreamingEnabled;
338
+ const draftReplyToMessageId = () => replyReference.use();
339
+ const deliverChannelId = deliverTarget.startsWith("channel:")
340
+ ? deliverTarget.slice("channel:".length)
341
+ : messageChannelId;
342
+ const draftStream = canStreamDraft
343
+ ? createDiscordDraftStream({
344
+ rest: client.rest,
345
+ channelId: deliverChannelId,
346
+ maxChars: draftMaxChars,
347
+ replyToMessageId: draftReplyToMessageId,
348
+ minInitialChars: 30,
349
+ throttleMs: 1200,
350
+ log: logVerbose,
351
+ warn: logVerbose,
352
+ })
353
+ : undefined;
354
+ const draftChunking = draftStream && discordStreamMode === "block"
355
+ ? resolveDiscordDraftStreamingChunking(cfg, accountId)
356
+ : undefined;
357
+ const shouldSplitPreviewMessages = discordStreamMode === "block";
358
+ const draftChunker = draftChunking ? new EmbeddedBlockChunker(draftChunking) : undefined;
359
+ let lastPartialText = "";
360
+ let draftText = "";
361
+ let hasStreamedMessage = false;
362
+ let finalizedViaPreviewMessage = false;
363
+ const resolvePreviewFinalText = (text) => {
364
+ if (typeof text !== "string") {
365
+ return undefined;
366
+ }
367
+ const formatted = convertMarkdownTables(text, tableMode);
368
+ const chunks = chunkDiscordTextWithMode(formatted, {
369
+ maxChars: draftMaxChars,
370
+ maxLines: discordConfig?.maxLinesPerMessage,
371
+ chunkMode,
372
+ });
373
+ if (!chunks.length && formatted) {
374
+ chunks.push(formatted);
375
+ }
376
+ if (chunks.length !== 1) {
377
+ return undefined;
378
+ }
379
+ const trimmed = chunks[0].trim();
380
+ if (!trimmed) {
381
+ return undefined;
382
+ }
383
+ const currentPreviewText = discordStreamMode === "block" ? draftText : lastPartialText;
384
+ if (currentPreviewText &&
385
+ currentPreviewText.startsWith(trimmed) &&
386
+ trimmed.length < currentPreviewText.length) {
387
+ return undefined;
388
+ }
389
+ return trimmed;
390
+ };
391
+ const updateDraftFromPartial = (text) => {
392
+ if (!draftStream || !text) {
393
+ return;
394
+ }
395
+ if (text === lastPartialText) {
396
+ return;
397
+ }
398
+ hasStreamedMessage = true;
399
+ if (discordStreamMode === "partial") {
400
+ // Keep the longer preview to avoid visible punctuation flicker.
401
+ if (lastPartialText &&
402
+ lastPartialText.startsWith(text) &&
403
+ text.length < lastPartialText.length) {
404
+ return;
405
+ }
406
+ lastPartialText = text;
407
+ draftStream.update(text);
408
+ return;
409
+ }
410
+ let delta = text;
411
+ if (text.startsWith(lastPartialText)) {
412
+ delta = text.slice(lastPartialText.length);
413
+ }
414
+ else {
415
+ // Streaming buffer reset (or non-monotonic stream). Start fresh.
416
+ draftChunker?.reset();
417
+ draftText = "";
418
+ }
419
+ lastPartialText = text;
420
+ if (!delta) {
421
+ return;
422
+ }
423
+ if (!draftChunker) {
424
+ draftText = text;
425
+ draftStream.update(draftText);
426
+ return;
427
+ }
428
+ draftChunker.append(delta);
429
+ draftChunker.drain({
430
+ force: false,
431
+ emit: (chunk) => {
432
+ draftText += chunk;
433
+ draftStream.update(draftText);
434
+ },
435
+ });
436
+ };
437
+ const flushDraft = async () => {
438
+ if (!draftStream) {
439
+ return;
440
+ }
441
+ if (draftChunker?.hasBuffered()) {
442
+ draftChunker.drain({
443
+ force: true,
444
+ emit: (chunk) => {
445
+ draftText += chunk;
446
+ },
447
+ });
448
+ draftChunker.reset();
449
+ if (draftText) {
450
+ draftStream.update(draftText);
451
+ }
452
+ }
453
+ await draftStream.flush();
454
+ };
455
+ // When draft streaming is active, suppress block streaming to avoid double-streaming.
456
+ const disableBlockStreamingForDraft = draftStream ? true : undefined;
509
457
  const { dispatcher, replyOptions, markDispatchIdle } = createReplyDispatcherWithTyping({
510
458
  ...prefixOptions,
511
459
  humanDelay: resolveHumanDelayConfig(cfg, route.agentId),
512
- deliver: async (payload) => {
460
+ deliver: async (payload, info) => {
461
+ const isFinal = info.kind === "final";
462
+ if (draftStream && isFinal) {
463
+ await flushDraft();
464
+ const hasMedia = Boolean(payload.mediaUrl) || (payload.mediaUrls?.length ?? 0) > 0;
465
+ const finalText = payload.text;
466
+ const previewFinalText = resolvePreviewFinalText(finalText);
467
+ const previewMessageId = draftStream.messageId();
468
+ // Try to finalize via preview edit (text-only, fits in 2000 chars, not an error)
469
+ const canFinalizeViaPreviewEdit = !finalizedViaPreviewMessage &&
470
+ !hasMedia &&
471
+ typeof previewFinalText === "string" &&
472
+ typeof previewMessageId === "string" &&
473
+ !payload.isError;
474
+ if (canFinalizeViaPreviewEdit) {
475
+ await draftStream.stop();
476
+ try {
477
+ await editMessageDiscord(deliverChannelId, previewMessageId, { content: previewFinalText }, { rest: client.rest });
478
+ finalizedViaPreviewMessage = true;
479
+ replyReference.markSent();
480
+ return;
481
+ }
482
+ catch (err) {
483
+ logVerbose(`discord: preview final edit failed; falling back to standard send (${String(err)})`);
484
+ }
485
+ }
486
+ // Check if stop() flushed a message we can edit
487
+ if (!finalizedViaPreviewMessage) {
488
+ await draftStream.stop();
489
+ const messageIdAfterStop = draftStream.messageId();
490
+ if (typeof messageIdAfterStop === "string" &&
491
+ typeof previewFinalText === "string" &&
492
+ !hasMedia &&
493
+ !payload.isError) {
494
+ try {
495
+ await editMessageDiscord(deliverChannelId, messageIdAfterStop, { content: previewFinalText }, { rest: client.rest });
496
+ finalizedViaPreviewMessage = true;
497
+ replyReference.markSent();
498
+ return;
499
+ }
500
+ catch (err) {
501
+ logVerbose(`discord: post-stop preview edit failed; falling back to standard send (${String(err)})`);
502
+ }
503
+ }
504
+ }
505
+ // Clear the preview and fall through to standard delivery
506
+ if (!finalizedViaPreviewMessage) {
507
+ await draftStream.clear();
508
+ }
509
+ }
513
510
  const replyToId = replyReference.use();
514
511
  await deliverDiscordReply({
515
512
  replies: [payload],
@@ -519,10 +516,13 @@ export async function processDiscordMessage(ctx) {
519
516
  rest: client.rest,
520
517
  runtime,
521
518
  replyToId,
519
+ replyToMode,
522
520
  textLimit,
523
521
  maxLinesPerMessage: discordConfig?.maxLinesPerMessage,
524
522
  tableMode,
525
- chunkMode: resolveChunkMode(cfg, "discord", accountId),
523
+ chunkMode,
524
+ sessionKey: ctxPayload.SessionKey,
525
+ threadBindings,
526
526
  });
527
527
  replyReference.markSent();
528
528
  },
@@ -544,8 +544,32 @@ export async function processDiscordMessage(ctx) {
544
544
  replyOptions: {
545
545
  ...replyOptions,
546
546
  skillFilter: channelConfig?.skills,
547
- disableBlockStreaming: typeof discordConfig?.blockStreaming === "boolean"
548
- ? !discordConfig.blockStreaming
547
+ disableBlockStreaming: disableBlockStreamingForDraft ??
548
+ (typeof discordConfig?.blockStreaming === "boolean"
549
+ ? !discordConfig.blockStreaming
550
+ : undefined),
551
+ onPartialReply: draftStream ? (payload) => updateDraftFromPartial(payload.text) : undefined,
552
+ onAssistantMessageStart: draftStream
553
+ ? () => {
554
+ if (shouldSplitPreviewMessages && hasStreamedMessage) {
555
+ logVerbose("discord: calling forceNewMessage() for draft stream");
556
+ draftStream.forceNewMessage();
557
+ }
558
+ lastPartialText = "";
559
+ draftText = "";
560
+ draftChunker?.reset();
561
+ }
562
+ : undefined,
563
+ onReasoningEnd: draftStream
564
+ ? () => {
565
+ if (shouldSplitPreviewMessages && hasStreamedMessage) {
566
+ logVerbose("discord: calling forceNewMessage() for draft stream");
567
+ draftStream.forceNewMessage();
568
+ }
569
+ lastPartialText = "";
570
+ draftText = "";
571
+ draftChunker?.reset();
572
+ }
549
573
  : undefined,
550
574
  onModelSelected,
551
575
  onReasoningStream: async () => {
@@ -562,6 +586,11 @@ export async function processDiscordMessage(ctx) {
562
586
  throw err;
563
587
  }
564
588
  finally {
589
+ // Must stop() first to flush debounced content before clear() wipes state
590
+ await draftStream?.stop();
591
+ if (!finalizedViaPreviewMessage) {
592
+ await draftStream?.clear();
593
+ }
565
594
  markDispatchIdle();
566
595
  if (statusReactionsEnabled) {
567
596
  if (dispatchError) {
@@ -572,7 +601,7 @@ export async function processDiscordMessage(ctx) {
572
601
  }
573
602
  if (removeAckAfterReply) {
574
603
  void (async () => {
575
- await sleep(dispatchError ? DISCORD_STATUS_ERROR_HOLD_MS : DISCORD_STATUS_DONE_HOLD_MS);
604
+ await sleep(dispatchError ? DEFAULT_TIMING.errorHoldMs : DEFAULT_TIMING.doneHoldMs);
576
605
  await statusReactions.clear();
577
606
  })();
578
607
  }