@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
@@ -4,20 +4,51 @@ import { AssistantMessageComponent } from "./assistant-message.js";
4
4
  import { ToolExecutionComponent } from "./tool-execution.js";
5
5
  import { UserMessageComponent } from "./user-message.js";
6
6
  export class ChatLog extends Container {
7
+ maxComponents;
7
8
  toolById = new Map();
8
9
  streamingRuns = new Map();
9
10
  toolsExpanded = false;
11
+ constructor(maxComponents = 180) {
12
+ super();
13
+ this.maxComponents = Math.max(20, Math.floor(maxComponents));
14
+ }
15
+ dropComponentReferences(component) {
16
+ for (const [toolId, tool] of this.toolById.entries()) {
17
+ if (tool === component) {
18
+ this.toolById.delete(toolId);
19
+ }
20
+ }
21
+ for (const [runId, message] of this.streamingRuns.entries()) {
22
+ if (message === component) {
23
+ this.streamingRuns.delete(runId);
24
+ }
25
+ }
26
+ }
27
+ pruneOverflow() {
28
+ while (this.children.length > this.maxComponents) {
29
+ const oldest = this.children[0];
30
+ if (!oldest) {
31
+ return;
32
+ }
33
+ this.removeChild(oldest);
34
+ this.dropComponentReferences(oldest);
35
+ }
36
+ }
37
+ append(component) {
38
+ this.addChild(component);
39
+ this.pruneOverflow();
40
+ }
10
41
  clearAll() {
11
42
  this.clear();
12
43
  this.toolById.clear();
13
44
  this.streamingRuns.clear();
14
45
  }
15
46
  addSystem(text) {
16
- this.addChild(new Spacer(1));
17
- this.addChild(new Text(theme.system(text), 1, 0));
47
+ this.append(new Spacer(1));
48
+ this.append(new Text(theme.system(text), 1, 0));
18
49
  }
19
50
  addUser(text) {
20
- this.addChild(new UserMessageComponent(text));
51
+ this.append(new UserMessageComponent(text));
21
52
  }
22
53
  resolveRunId(runId) {
23
54
  return runId ?? "default";
@@ -25,7 +56,7 @@ export class ChatLog extends Container {
25
56
  startAssistant(text, runId) {
26
57
  const component = new AssistantMessageComponent(text);
27
58
  this.streamingRuns.set(this.resolveRunId(runId), component);
28
- this.addChild(component);
59
+ this.append(component);
29
60
  return component;
30
61
  }
31
62
  updateAssistant(text, runId) {
@@ -45,7 +76,16 @@ export class ChatLog extends Container {
45
76
  this.streamingRuns.delete(effectiveRunId);
46
77
  return;
47
78
  }
48
- this.addChild(new AssistantMessageComponent(text));
79
+ this.append(new AssistantMessageComponent(text));
80
+ }
81
+ dropAssistant(runId) {
82
+ const effectiveRunId = this.resolveRunId(runId);
83
+ const existing = this.streamingRuns.get(effectiveRunId);
84
+ if (!existing) {
85
+ return;
86
+ }
87
+ this.removeChild(existing);
88
+ this.streamingRuns.delete(effectiveRunId);
49
89
  }
50
90
  startTool(toolCallId, toolName, args) {
51
91
  const existing = this.toolById.get(toolCallId);
@@ -56,19 +96,21 @@ export class ChatLog extends Container {
56
96
  const component = new ToolExecutionComponent(toolName, args);
57
97
  component.setExpanded(this.toolsExpanded);
58
98
  this.toolById.set(toolCallId, component);
59
- this.addChild(component);
99
+ this.append(component);
60
100
  return component;
61
101
  }
62
102
  updateToolArgs(toolCallId, args) {
63
103
  const existing = this.toolById.get(toolCallId);
64
- if (!existing)
104
+ if (!existing) {
65
105
  return;
106
+ }
66
107
  existing.setArgs(args);
67
108
  }
68
109
  updateToolResult(toolCallId, result, opts) {
69
110
  const existing = this.toolById.get(toolCallId);
70
- if (!existing)
111
+ if (!existing) {
71
112
  return;
113
+ }
72
114
  if (opts?.partial) {
73
115
  existing.setPartialResult(result);
74
116
  return;
@@ -4,20 +4,20 @@ import { createSyntaxTheme } from "./syntax-theme.js";
4
4
  const palette = {
5
5
  text: "#E8E3D5",
6
6
  dim: "#7B7F87",
7
- accent: "#A855F7", // vivid purple (was gold #F6C453)
8
- accentSoft: "#C084FC", // soft purple (was orange #F2A65A)
7
+ accent: "#F6C453",
8
+ accentSoft: "#F2A65A",
9
9
  border: "#3C414B",
10
10
  userBg: "#2B2F36",
11
11
  userText: "#F3EEE0",
12
12
  systemText: "#9BA3B2",
13
- toolPendingBg: "#1F1F2F", // slight purple tint (was teal #1F2A2F)
13
+ toolPendingBg: "#1F2A2F",
14
14
  toolSuccessBg: "#1E2D23",
15
15
  toolErrorBg: "#2F1F1F",
16
- toolTitle: "#A855F7", // vivid purple (was gold #F6C453)
16
+ toolTitle: "#F6C453",
17
17
  toolOutput: "#E1DACB",
18
18
  quote: "#8CC8FF",
19
19
  quoteBorder: "#3B4D6B",
20
- code: "#D4BBFF", // light lavender (was gold #F0C987)
20
+ code: "#F0C987",
21
21
  codeBlock: "#1E232A",
22
22
  codeBorder: "#343A45",
23
23
  link: "#7DD3A5",
@@ -50,6 +50,7 @@ function highlightCode(code, lang) {
50
50
  }
51
51
  export const theme = {
52
52
  fg: fg(palette.text),
53
+ assistantText: (text) => text,
53
54
  dim: fg(palette.dim),
54
55
  accent: fg(palette.accent),
55
56
  accentSoft: fg(palette.accentSoft),
@@ -85,15 +86,16 @@ export const markdownTheme = {
85
86
  underline: (text) => chalk.underline(text),
86
87
  highlightCode,
87
88
  };
88
- export const selectListTheme = {
89
+ const baseSelectListTheme = {
89
90
  selectedPrefix: (text) => fg(palette.accent)(text),
90
91
  selectedText: (text) => chalk.bold(fg(palette.accent)(text)),
91
92
  description: (text) => fg(palette.dim)(text),
92
93
  scrollInfo: (text) => fg(palette.dim)(text),
93
94
  noMatch: (text) => fg(palette.dim)(text),
94
95
  };
96
+ export const selectListTheme = baseSelectListTheme;
95
97
  export const filterableSelectListTheme = {
96
- ...selectListTheme,
98
+ ...baseSelectListTheme,
97
99
  filterLabel: (text) => fg(palette.dim)(text),
98
100
  };
99
101
  export const settingsListTheme = {
@@ -108,11 +110,7 @@ export const editorTheme = {
108
110
  selectList: selectListTheme,
109
111
  };
110
112
  export const searchableSelectListTheme = {
111
- selectedPrefix: (text) => fg(palette.accent)(text),
112
- selectedText: (text) => chalk.bold(fg(palette.accent)(text)),
113
- description: (text) => fg(palette.dim)(text),
114
- scrollInfo: (text) => fg(palette.dim)(text),
115
- noMatch: (text) => fg(palette.dim)(text),
113
+ ...baseSelectListTheme,
116
114
  searchPrompt: (text) => fg(palette.accentSoft)(text),
117
115
  searchInput: (text) => fg(palette.text)(text),
118
116
  matchHighlight: (text) => chalk.bold(fg(palette.accent)(text)),
@@ -1,20 +1,15 @@
1
- import { truncateToWidth } from "@mariozechner/pi-tui";
2
1
  import { formatThinkingLevels, normalizeUsageDisplay, resolveResponseUsageMode, } from "../auto-reply/thinking.js";
2
+ import { formatRelativeTimestamp } from "../infra/format-time/format-relative.js";
3
3
  import { normalizeAgentId } from "../routing/session-key.js";
4
- import { formatRelativeTime } from "../utils/time-format.js";
5
4
  import { helpText, parseCommand } from "./commands.js";
6
5
  import { createFilterableSelectList, createSearchableSelectList, createSettingsList, } from "./components/selectors.js";
7
6
  import { formatStatusSummary } from "./tui-status-summary.js";
8
7
  export function createCommandHandlers(context) {
9
- const { client, chatLog, tui, opts, state, deliverDefault, openOverlay, closeOverlay, refreshSessionInfo, loadHistory, setSession, refreshAgents, abortActive, setActivityStatus, formatSessionKey, } = context;
8
+ const { client, chatLog, tui, opts, state, deliverDefault, openOverlay, closeOverlay, refreshSessionInfo, loadHistory, setSession, refreshAgents, abortActive, setActivityStatus, formatSessionKey, applySessionInfoFromPatch, noteLocalRunId, forgetLocalRunId, } = context;
10
9
  const setAgent = async (id) => {
11
10
  state.currentAgentId = normalizeAgentId(id);
12
11
  await setSession("");
13
12
  };
14
- // Maximum visible width for overlay item strings. The overlay has its own
15
- // padding/chrome (~4 chars). We subtract a generous margin so that even
16
- // after ANSI formatting, lines stay within terminal bounds.
17
- const overlayItemWidth = () => Math.max(30, (tui.terminal.columns ?? 80) - 6);
18
13
  const openModelSelector = async () => {
19
14
  try {
20
15
  const models = await client.listModels();
@@ -23,21 +18,21 @@ export function createCommandHandlers(context) {
23
18
  tui.requestRender();
24
19
  return;
25
20
  }
26
- const maxW = overlayItemWidth();
27
21
  const items = models.map((model) => ({
28
22
  value: `${model.provider}/${model.id}`,
29
- label: truncateToWidth(`${model.provider}/${model.id}`, maxW),
30
- description: model.name && model.name !== model.id ? truncateToWidth(model.name, maxW) : "",
23
+ label: `${model.provider}/${model.id}`,
24
+ description: model.name && model.name !== model.id ? model.name : "",
31
25
  }));
32
26
  const selector = createSearchableSelectList(items, 9);
33
27
  selector.onSelect = (item) => {
34
28
  void (async () => {
35
29
  try {
36
- await client.patchSession({
30
+ const result = await client.patchSession({
37
31
  key: state.currentSessionKey,
38
32
  model: item.value,
39
33
  });
40
34
  chatLog.addSystem(`model set to ${item.value}`);
35
+ applySessionInfoFromPatch(result);
41
36
  await refreshSessionInfo();
42
37
  }
43
38
  catch (err) {
@@ -66,10 +61,9 @@ export function createCommandHandlers(context) {
66
61
  tui.requestRender();
67
62
  return;
68
63
  }
69
- const maxW = overlayItemWidth();
70
64
  const items = state.agents.map((agent) => ({
71
65
  value: agent.id,
72
- label: truncateToWidth(agent.name ? `${agent.id} (${agent.name})` : agent.id, maxW),
66
+ label: agent.name ? `${agent.id} (${agent.name})` : agent.id,
73
67
  description: agent.id === state.agentDefaultId ? "default" : "",
74
68
  }));
75
69
  const selector = createSearchableSelectList(items, 9);
@@ -96,20 +90,21 @@ export function createCommandHandlers(context) {
96
90
  includeLastMessage: true,
97
91
  agentId: state.currentAgentId,
98
92
  });
99
- const maxW = overlayItemWidth();
100
93
  const items = result.sessions.map((session) => {
101
94
  const title = session.derivedTitle ?? session.displayName;
102
95
  const formattedKey = formatSessionKey(session.key);
103
96
  // Avoid redundant "title (key)" when title matches key
104
97
  const label = title && title !== formattedKey ? `${title} (${formattedKey})` : formattedKey;
105
98
  // Build description: time + message preview
106
- const timePart = session.updatedAt ? formatRelativeTime(session.updatedAt) : "";
99
+ const timePart = session.updatedAt
100
+ ? formatRelativeTimestamp(session.updatedAt, { dateFallback: true, fallback: "" })
101
+ : "";
107
102
  const preview = session.lastMessagePreview?.replace(/\s+/g, " ").trim();
108
103
  const description = timePart && preview ? `${timePart} · ${preview}` : (preview ?? timePart);
109
104
  return {
110
105
  value: session.key,
111
- label: truncateToWidth(label, maxW),
112
- description: truncateToWidth(description, maxW),
106
+ label,
107
+ description,
113
108
  searchText: [
114
109
  session.displayName,
115
110
  session.label,
@@ -176,8 +171,9 @@ export function createCommandHandlers(context) {
176
171
  };
177
172
  const handleCommand = async (raw) => {
178
173
  const { name, args } = parseCommand(raw);
179
- if (!name)
174
+ if (!name) {
180
175
  return;
176
+ }
181
177
  switch (name) {
182
178
  case "help":
183
179
  chatLog.addSystem(helpText({
@@ -194,8 +190,9 @@ export function createCommandHandlers(context) {
194
190
  }
195
191
  if (status && typeof status === "object") {
196
192
  const lines = formatStatusSummary(status);
197
- for (const line of lines)
193
+ for (const line of lines) {
198
194
  chatLog.addSystem(line);
195
+ }
199
196
  break;
200
197
  }
201
198
  chatLog.addSystem("status: unknown response");
@@ -232,11 +229,12 @@ export function createCommandHandlers(context) {
232
229
  }
233
230
  else {
234
231
  try {
235
- await client.patchSession({
232
+ const result = await client.patchSession({
236
233
  key: state.currentSessionKey,
237
234
  model: args,
238
235
  });
239
236
  chatLog.addSystem(`model set to ${args}`);
237
+ applySessionInfoFromPatch(result);
240
238
  await refreshSessionInfo();
241
239
  }
242
240
  catch (err) {
@@ -254,11 +252,12 @@ export function createCommandHandlers(context) {
254
252
  break;
255
253
  }
256
254
  try {
257
- await client.patchSession({
255
+ const result = await client.patchSession({
258
256
  key: state.currentSessionKey,
259
257
  thinkingLevel: args,
260
258
  });
261
259
  chatLog.addSystem(`thinking set to ${args}`);
260
+ applySessionInfoFromPatch(result);
262
261
  await refreshSessionInfo();
263
262
  }
264
263
  catch (err) {
@@ -271,12 +270,13 @@ export function createCommandHandlers(context) {
271
270
  break;
272
271
  }
273
272
  try {
274
- await client.patchSession({
273
+ const result = await client.patchSession({
275
274
  key: state.currentSessionKey,
276
275
  verboseLevel: args,
277
276
  });
278
277
  chatLog.addSystem(`verbose set to ${args}`);
279
- await refreshSessionInfo();
278
+ applySessionInfoFromPatch(result);
279
+ await loadHistory();
280
280
  }
281
281
  catch (err) {
282
282
  chatLog.addSystem(`verbose failed: ${String(err)}`);
@@ -288,11 +288,12 @@ export function createCommandHandlers(context) {
288
288
  break;
289
289
  }
290
290
  try {
291
- await client.patchSession({
291
+ const result = await client.patchSession({
292
292
  key: state.currentSessionKey,
293
293
  reasoningLevel: args,
294
294
  });
295
295
  chatLog.addSystem(`reasoning set to ${args}`);
296
+ applySessionInfoFromPatch(result);
296
297
  await refreshSessionInfo();
297
298
  }
298
299
  catch (err) {
@@ -309,11 +310,12 @@ export function createCommandHandlers(context) {
309
310
  const current = resolveResponseUsageMode(currentRaw);
310
311
  const next = normalized ?? (current === "off" ? "tokens" : current === "tokens" ? "full" : "off");
311
312
  try {
312
- await client.patchSession({
313
+ const result = await client.patchSession({
313
314
  key: state.currentSessionKey,
314
315
  responseUsage: next === "off" ? null : next,
315
316
  });
316
317
  chatLog.addSystem(`usage footer: ${next}`);
318
+ applySessionInfoFromPatch(result);
317
319
  await refreshSessionInfo();
318
320
  }
319
321
  catch (err) {
@@ -331,11 +333,12 @@ export function createCommandHandlers(context) {
331
333
  break;
332
334
  }
333
335
  try {
334
- await client.patchSession({
336
+ const result = await client.patchSession({
335
337
  key: state.currentSessionKey,
336
338
  elevatedLevel: args,
337
339
  });
338
340
  chatLog.addSystem(`elevated set to ${args}`);
341
+ applySessionInfoFromPatch(result);
339
342
  await refreshSessionInfo();
340
343
  }
341
344
  catch (err) {
@@ -348,11 +351,12 @@ export function createCommandHandlers(context) {
348
351
  break;
349
352
  }
350
353
  try {
351
- await client.patchSession({
354
+ const result = await client.patchSession({
352
355
  key: state.currentSessionKey,
353
356
  groupActivation: args === "always" ? "always" : "mention",
354
357
  });
355
358
  chatLog.addSystem(`activation set to ${args}`);
359
+ applySessionInfoFromPatch(result);
356
360
  await refreshSessionInfo();
357
361
  }
358
362
  catch (err) {
@@ -405,10 +409,15 @@ export function createCommandHandlers(context) {
405
409
  deliver: deliverDefault,
406
410
  timeoutMs: opts.timeoutMs,
407
411
  });
412
+ noteLocalRunId(runId);
408
413
  state.activeChatRunId = runId;
409
414
  setActivityStatus("waiting");
410
415
  }
411
416
  catch (err) {
417
+ if (state.activeChatRunId) {
418
+ forgetLocalRunId?.(state.activeChatRunId);
419
+ }
420
+ state.activeChatRunId = null;
412
421
  chatLog.addSystem(`send failed: ${String(err)}`);
413
422
  setActivityStatus("error");
414
423
  }
@@ -1,36 +1,42 @@
1
1
  import { asString, extractTextFromMessage, isCommandMessage } from "./tui-formatters.js";
2
2
  import { TuiStreamAssembler } from "./tui-stream-assembler.js";
3
3
  export function createEventHandlers(context) {
4
- const { chatLog, tui, state, setActivityStatus, refreshSessionInfo } = context;
4
+ const { chatLog, tui, state, setActivityStatus, refreshSessionInfo, loadHistory, isLocalRunId, forgetLocalRunId, clearLocalRunIds, } = context;
5
5
  const finalizedRuns = new Map();
6
6
  const sessionRuns = new Map();
7
7
  let streamAssembler = new TuiStreamAssembler();
8
8
  let lastSessionKey = state.currentSessionKey;
9
9
  const pruneRunMap = (runs) => {
10
- if (runs.size <= 200)
10
+ if (runs.size <= 200) {
11
11
  return;
12
+ }
12
13
  const keepUntil = Date.now() - 10 * 60 * 1000;
13
14
  for (const [key, ts] of runs) {
14
- if (runs.size <= 150)
15
+ if (runs.size <= 150) {
15
16
  break;
16
- if (ts < keepUntil)
17
+ }
18
+ if (ts < keepUntil) {
17
19
  runs.delete(key);
20
+ }
18
21
  }
19
22
  if (runs.size > 200) {
20
23
  for (const key of runs.keys()) {
21
24
  runs.delete(key);
22
- if (runs.size <= 150)
25
+ if (runs.size <= 150) {
23
26
  break;
27
+ }
24
28
  }
25
29
  }
26
30
  };
27
31
  const syncSessionKey = () => {
28
- if (state.currentSessionKey === lastSessionKey)
32
+ if (state.currentSessionKey === lastSessionKey) {
29
33
  return;
34
+ }
30
35
  lastSessionKey = state.currentSessionKey;
31
36
  finalizedRuns.clear();
32
37
  sessionRuns.clear();
33
38
  streamAssembler = new TuiStreamAssembler();
39
+ clearLocalRunIds?.();
34
40
  };
35
41
  const noteSessionRun = (runId) => {
36
42
  sessionRuns.set(runId, Date.now());
@@ -42,18 +48,44 @@ export function createEventHandlers(context) {
42
48
  streamAssembler.drop(runId);
43
49
  pruneRunMap(finalizedRuns);
44
50
  };
51
+ const clearActiveRunIfMatch = (runId) => {
52
+ if (state.activeChatRunId === runId) {
53
+ state.activeChatRunId = null;
54
+ }
55
+ };
56
+ const hasConcurrentActiveRun = (runId) => {
57
+ const activeRunId = state.activeChatRunId;
58
+ if (!activeRunId || activeRunId === runId) {
59
+ return false;
60
+ }
61
+ return sessionRuns.has(activeRunId);
62
+ };
63
+ const maybeRefreshHistoryForRun = (runId) => {
64
+ if (isLocalRunId?.(runId)) {
65
+ forgetLocalRunId?.(runId);
66
+ return;
67
+ }
68
+ if (hasConcurrentActiveRun(runId)) {
69
+ return;
70
+ }
71
+ void loadHistory?.();
72
+ };
45
73
  const handleChatEvent = (payload) => {
46
- if (!payload || typeof payload !== "object")
74
+ if (!payload || typeof payload !== "object") {
47
75
  return;
76
+ }
48
77
  const evt = payload;
49
78
  syncSessionKey();
50
- if (evt.sessionKey !== state.currentSessionKey)
79
+ if (evt.sessionKey !== state.currentSessionKey) {
51
80
  return;
81
+ }
52
82
  if (finalizedRuns.has(evt.runId)) {
53
- if (evt.state === "delta")
83
+ if (evt.state === "delta") {
54
84
  return;
55
- if (evt.state === "final")
85
+ }
86
+ if (evt.state === "final") {
56
87
  return;
88
+ }
57
89
  }
58
90
  noteSessionRun(evt.runId);
59
91
  if (!state.activeChatRunId) {
@@ -61,98 +93,156 @@ export function createEventHandlers(context) {
61
93
  }
62
94
  if (evt.state === "delta") {
63
95
  const displayText = streamAssembler.ingestDelta(evt.runId, evt.message, state.showThinking);
64
- if (!displayText)
96
+ if (!displayText) {
65
97
  return;
98
+ }
66
99
  chatLog.updateAssistant(displayText, evt.runId);
67
100
  setActivityStatus("streaming");
68
101
  }
69
102
  if (evt.state === "final") {
103
+ const wasActiveRun = state.activeChatRunId === evt.runId;
104
+ if (!evt.message) {
105
+ maybeRefreshHistoryForRun(evt.runId);
106
+ chatLog.dropAssistant(evt.runId);
107
+ noteFinalizedRun(evt.runId);
108
+ clearActiveRunIfMatch(evt.runId);
109
+ if (wasActiveRun) {
110
+ setActivityStatus("idle");
111
+ }
112
+ void refreshSessionInfo?.();
113
+ tui.requestRender();
114
+ return;
115
+ }
70
116
  if (isCommandMessage(evt.message)) {
117
+ maybeRefreshHistoryForRun(evt.runId);
71
118
  const text = extractTextFromMessage(evt.message);
72
- if (text)
119
+ if (text) {
73
120
  chatLog.addSystem(text);
121
+ }
74
122
  streamAssembler.drop(evt.runId);
75
123
  noteFinalizedRun(evt.runId);
76
- state.activeChatRunId = null;
77
- setActivityStatus("idle");
124
+ clearActiveRunIfMatch(evt.runId);
125
+ if (wasActiveRun) {
126
+ setActivityStatus("idle");
127
+ }
78
128
  void refreshSessionInfo?.();
79
129
  tui.requestRender();
80
130
  return;
81
131
  }
132
+ maybeRefreshHistoryForRun(evt.runId);
82
133
  const stopReason = evt.message && typeof evt.message === "object" && !Array.isArray(evt.message)
83
134
  ? typeof evt.message.stopReason === "string"
84
135
  ? evt.message.stopReason
85
136
  : ""
86
137
  : "";
87
138
  const finalText = streamAssembler.finalize(evt.runId, evt.message, state.showThinking);
88
- chatLog.finalizeAssistant(finalText, evt.runId);
139
+ const suppressEmptyExternalPlaceholder = finalText === "(no output)" && !isLocalRunId?.(evt.runId);
140
+ if (suppressEmptyExternalPlaceholder) {
141
+ chatLog.dropAssistant(evt.runId);
142
+ }
143
+ else {
144
+ chatLog.finalizeAssistant(finalText, evt.runId);
145
+ }
89
146
  noteFinalizedRun(evt.runId);
90
- state.activeChatRunId = null;
91
- setActivityStatus(stopReason === "error" ? "error" : "idle");
147
+ clearActiveRunIfMatch(evt.runId);
148
+ if (wasActiveRun) {
149
+ setActivityStatus(stopReason === "error" ? "error" : "idle");
150
+ }
92
151
  // Refresh session info to update token counts in footer
93
152
  void refreshSessionInfo?.();
94
153
  }
95
154
  if (evt.state === "aborted") {
155
+ const wasActiveRun = state.activeChatRunId === evt.runId;
96
156
  chatLog.addSystem("run aborted");
97
157
  streamAssembler.drop(evt.runId);
98
158
  sessionRuns.delete(evt.runId);
99
- state.activeChatRunId = null;
100
- setActivityStatus("aborted");
159
+ clearActiveRunIfMatch(evt.runId);
160
+ if (wasActiveRun) {
161
+ setActivityStatus("aborted");
162
+ }
101
163
  void refreshSessionInfo?.();
164
+ maybeRefreshHistoryForRun(evt.runId);
102
165
  }
103
166
  if (evt.state === "error") {
167
+ const wasActiveRun = state.activeChatRunId === evt.runId;
104
168
  chatLog.addSystem(`run error: ${evt.errorMessage ?? "unknown"}`);
105
169
  streamAssembler.drop(evt.runId);
106
170
  sessionRuns.delete(evt.runId);
107
- state.activeChatRunId = null;
108
- setActivityStatus("error");
171
+ clearActiveRunIfMatch(evt.runId);
172
+ if (wasActiveRun) {
173
+ setActivityStatus("error");
174
+ }
109
175
  void refreshSessionInfo?.();
176
+ maybeRefreshHistoryForRun(evt.runId);
110
177
  }
111
178
  tui.requestRender();
112
179
  };
113
180
  const handleAgentEvent = (payload) => {
114
- if (!payload || typeof payload !== "object")
181
+ if (!payload || typeof payload !== "object") {
115
182
  return;
183
+ }
116
184
  const evt = payload;
117
185
  syncSessionKey();
118
186
  // Agent events (tool streaming, lifecycle) are emitted per-run. Filter against the
119
- // active chat run id, not the session id.
187
+ // active chat run id, not the session id. Tool results can arrive after the chat
188
+ // final event, so accept finalized runs for tool updates.
120
189
  const isActiveRun = evt.runId === state.activeChatRunId;
121
- if (!isActiveRun && !sessionRuns.has(evt.runId))
190
+ const isKnownRun = isActiveRun || sessionRuns.has(evt.runId) || finalizedRuns.has(evt.runId);
191
+ if (!isKnownRun) {
122
192
  return;
193
+ }
123
194
  if (evt.stream === "tool") {
195
+ const verbose = state.sessionInfo.verboseLevel ?? "off";
196
+ const allowToolEvents = verbose !== "off";
197
+ const allowToolOutput = verbose === "full";
198
+ if (!allowToolEvents) {
199
+ return;
200
+ }
124
201
  const data = evt.data ?? {};
125
202
  const phase = asString(data.phase, "");
126
203
  const toolCallId = asString(data.toolCallId, "");
127
204
  const toolName = asString(data.name, "tool");
128
- if (!toolCallId)
205
+ if (!toolCallId) {
129
206
  return;
207
+ }
130
208
  if (phase === "start") {
131
209
  chatLog.startTool(toolCallId, toolName, data.args);
132
210
  }
133
211
  else if (phase === "update") {
212
+ if (!allowToolOutput) {
213
+ return;
214
+ }
134
215
  chatLog.updateToolResult(toolCallId, data.partialResult, {
135
216
  partial: true,
136
217
  });
137
218
  }
138
219
  else if (phase === "result") {
139
- chatLog.updateToolResult(toolCallId, data.result, {
140
- isError: Boolean(data.isError),
141
- });
220
+ if (allowToolOutput) {
221
+ chatLog.updateToolResult(toolCallId, data.result, {
222
+ isError: Boolean(data.isError),
223
+ });
224
+ }
225
+ else {
226
+ chatLog.updateToolResult(toolCallId, { content: [] }, { isError: Boolean(data.isError) });
227
+ }
142
228
  }
143
229
  tui.requestRender();
144
230
  return;
145
231
  }
146
232
  if (evt.stream === "lifecycle") {
147
- if (!isActiveRun)
233
+ if (!isActiveRun) {
148
234
  return;
235
+ }
149
236
  const phase = typeof evt.data?.phase === "string" ? evt.data.phase : "";
150
- if (phase === "start")
237
+ if (phase === "start") {
151
238
  setActivityStatus("running");
152
- if (phase === "end")
239
+ }
240
+ if (phase === "end") {
153
241
  setActivityStatus("idle");
154
- if (phase === "error")
242
+ }
243
+ if (phase === "error") {
155
244
  setActivityStatus("error");
245
+ }
156
246
  tui.requestRender();
157
247
  }
158
248
  };