@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
@@ -9,10 +9,12 @@ export function createLocalShellRunner(deps) {
9
9
  const env = deps.env ?? process.env;
10
10
  const maxChars = deps.maxOutputChars ?? 40_000;
11
11
  const ensureLocalExecAllowed = async () => {
12
- if (localExecAllowed)
12
+ if (localExecAllowed) {
13
13
  return true;
14
- if (localExecAsked)
14
+ }
15
+ if (localExecAsked) {
15
16
  return false;
17
+ }
16
18
  localExecAsked = true;
17
19
  return await new Promise((resolve) => {
18
20
  deps.chatLog.addSystem("Allow local shell commands for this session?");
@@ -49,20 +51,28 @@ export function createLocalShellRunner(deps) {
49
51
  const cmd = line.slice(1);
50
52
  // NOTE: A lone '!' is handled by the submit handler as a normal message.
51
53
  // Keep this guard anyway in case this is called directly.
52
- if (cmd === "")
54
+ if (cmd === "") {
53
55
  return;
56
+ }
54
57
  if (localExecAsked && !localExecAllowed) {
55
58
  deps.chatLog.addSystem("local shell: not enabled for this session");
56
59
  deps.tui.requestRender();
57
60
  return;
58
61
  }
59
62
  const allowed = await ensureLocalExecAllowed();
60
- if (!allowed)
63
+ if (!allowed) {
61
64
  return;
65
+ }
62
66
  deps.chatLog.addSystem(`[local] $ ${cmd}`);
63
67
  deps.tui.requestRender();
68
+ const appendWithCap = (text, chunk) => {
69
+ const combined = text + chunk;
70
+ return combined.length > maxChars ? combined.slice(-maxChars) : combined;
71
+ };
64
72
  await new Promise((resolve) => {
65
73
  const child = spawnCommand(cmd, {
74
+ // Intentionally a shell: this is an operator-only local TUI feature (prefixed with `!`)
75
+ // and is gated behind an explicit in-session approval prompt.
66
76
  shell: true,
67
77
  cwd: getCwd(),
68
78
  env,
@@ -70,10 +80,10 @@ export function createLocalShellRunner(deps) {
70
80
  let stdout = "";
71
81
  let stderr = "";
72
82
  child.stdout.on("data", (buf) => {
73
- stdout += buf.toString("utf8");
83
+ stdout = appendWithCap(stdout, buf.toString("utf8"));
74
84
  });
75
85
  child.stderr.on("data", (buf) => {
76
- stderr += buf.toString("utf8");
86
+ stderr = appendWithCap(stderr, buf.toString("utf8"));
77
87
  });
78
88
  child.on("close", (code, signal) => {
79
89
  const combined = (stdout + (stderr ? (stdout ? "\n" : "") + stderr : ""))
package/dist/tui/tui.js CHANGED
@@ -1,4 +1,4 @@
1
- import { CombinedAutocompleteProvider, Container, Loader, ProcessTerminal, Text, TUI, truncateToWidth, } from "@mariozechner/pi-tui";
1
+ import { CombinedAutocompleteProvider, Container, Key, Loader, matchesKey, ProcessTerminal, Text, TUI, } from "@mariozechner/pi-tui";
2
2
  import { resolveDefaultAgentId } from "../agents/agent-scope.js";
3
3
  import { loadConfig } from "../config/config.js";
4
4
  import { buildAgentMainSessionKey, normalizeAgentId, normalizeMainKey, parseAgentSessionKey, } from "../routing/session-key.js";
@@ -11,9 +11,9 @@ import { createCommandHandlers } from "./tui-command-handlers.js";
11
11
  import { createEventHandlers } from "./tui-event-handlers.js";
12
12
  import { formatTokens } from "./tui-formatters.js";
13
13
  import { createLocalShellRunner } from "./tui-local-shell.js";
14
- import { buildWaitingStatusMessage, defaultWaitingPhrases } from "./tui-waiting.js";
15
14
  import { createOverlayHandlers } from "./tui-overlays.js";
16
15
  import { createSessionActions } from "./tui-session-actions.js";
16
+ import { buildWaitingStatusMessage, defaultWaitingPhrases } from "./tui-waiting.js";
17
17
  export { resolveFinalAssistantText } from "./tui-formatters.js";
18
18
  export function createEditorSubmitHandler(params) {
19
19
  return (text) => {
@@ -21,8 +21,9 @@ export function createEditorSubmitHandler(params) {
21
21
  const value = raw.trim();
22
22
  params.editor.setText("");
23
23
  // Keep previous behavior: ignore empty/whitespace-only submissions.
24
- if (!value)
24
+ if (!value) {
25
25
  return;
26
+ }
26
27
  // Bash mode: only if the very first character is '!' and it's not just '!'.
27
28
  // IMPORTANT: use the raw (untrimmed) text so leading spaces do NOT trigger.
28
29
  // Per requirement: a lone '!' should be treated as a normal message.
@@ -40,6 +41,140 @@ export function createEditorSubmitHandler(params) {
40
41
  void params.sendMessage(value);
41
42
  };
42
43
  }
44
+ export function shouldEnableWindowsGitBashPasteFallback(params) {
45
+ const platform = params?.platform ?? process.platform;
46
+ const env = params?.env ?? process.env;
47
+ const termProgram = (env.TERM_PROGRAM ?? "").toLowerCase();
48
+ // Some macOS terminals emit multiline paste as rapid single-line submits.
49
+ // Enable burst coalescing so pasted blocks stay as one user message.
50
+ if (platform === "darwin") {
51
+ if (termProgram.includes("iterm") || termProgram.includes("apple_terminal")) {
52
+ return true;
53
+ }
54
+ return false;
55
+ }
56
+ if (platform !== "win32") {
57
+ return false;
58
+ }
59
+ const msystem = (env.MSYSTEM ?? "").toUpperCase();
60
+ const shell = env.SHELL ?? "";
61
+ if (msystem.startsWith("MINGW") || msystem.startsWith("MSYS")) {
62
+ return true;
63
+ }
64
+ if (shell.toLowerCase().includes("bash")) {
65
+ return true;
66
+ }
67
+ return termProgram.includes("mintty");
68
+ }
69
+ export function createSubmitBurstCoalescer(params) {
70
+ const windowMs = Math.max(1, params.burstWindowMs ?? 50);
71
+ const now = params.now ?? (() => Date.now());
72
+ const setTimer = params.setTimer ?? setTimeout;
73
+ const clearTimer = params.clearTimer ?? clearTimeout;
74
+ let pending = null;
75
+ let pendingAt = 0;
76
+ let flushTimer = null;
77
+ const clearFlushTimer = () => {
78
+ if (!flushTimer) {
79
+ return;
80
+ }
81
+ clearTimer(flushTimer);
82
+ flushTimer = null;
83
+ };
84
+ const flushPending = () => {
85
+ if (pending === null) {
86
+ return;
87
+ }
88
+ const value = pending;
89
+ pending = null;
90
+ pendingAt = 0;
91
+ clearFlushTimer();
92
+ params.submit(value);
93
+ };
94
+ const scheduleFlush = () => {
95
+ clearFlushTimer();
96
+ flushTimer = setTimer(() => {
97
+ flushPending();
98
+ }, windowMs);
99
+ };
100
+ return (value) => {
101
+ if (!params.enabled) {
102
+ params.submit(value);
103
+ return;
104
+ }
105
+ if (value.includes("\n")) {
106
+ flushPending();
107
+ params.submit(value);
108
+ return;
109
+ }
110
+ const ts = now();
111
+ if (pending === null) {
112
+ pending = value;
113
+ pendingAt = ts;
114
+ scheduleFlush();
115
+ return;
116
+ }
117
+ if (ts - pendingAt <= windowMs) {
118
+ pending = `${pending}\n${value}`;
119
+ pendingAt = ts;
120
+ scheduleFlush();
121
+ return;
122
+ }
123
+ flushPending();
124
+ pending = value;
125
+ pendingAt = ts;
126
+ scheduleFlush();
127
+ };
128
+ }
129
+ export function resolveTuiSessionKey(params) {
130
+ const trimmed = (params.raw ?? "").trim();
131
+ if (!trimmed) {
132
+ if (params.sessionScope === "global") {
133
+ return "global";
134
+ }
135
+ return buildAgentMainSessionKey({
136
+ agentId: params.currentAgentId,
137
+ mainKey: params.sessionMainKey,
138
+ });
139
+ }
140
+ if (trimmed === "global" || trimmed === "unknown") {
141
+ return trimmed;
142
+ }
143
+ if (trimmed.startsWith("agent:")) {
144
+ return trimmed;
145
+ }
146
+ return `agent:${params.currentAgentId}:${trimmed}`;
147
+ }
148
+ export function resolveGatewayDisconnectState(reason) {
149
+ const reasonLabel = reason?.trim() ? reason.trim() : "closed";
150
+ if (/pairing required/i.test(reasonLabel)) {
151
+ return {
152
+ connectionStatus: `gateway disconnected: ${reasonLabel}`,
153
+ activityStatus: "pairing required: run poolbot devices list",
154
+ pairingHint: "Pairing required. Run `poolbot devices list`, approve your request ID, then reconnect.",
155
+ };
156
+ }
157
+ return {
158
+ connectionStatus: `gateway disconnected: ${reasonLabel}`,
159
+ activityStatus: "idle",
160
+ };
161
+ }
162
+ export function createBackspaceDeduper(params) {
163
+ const dedupeWindowMs = Math.max(0, Math.floor(params?.dedupeWindowMs ?? 8));
164
+ const now = params?.now ?? (() => Date.now());
165
+ let lastBackspaceAt = -1;
166
+ return (data) => {
167
+ if (!matchesKey(data, Key.backspace)) {
168
+ return data;
169
+ }
170
+ const ts = now();
171
+ if (lastBackspaceAt >= 0 && ts - lastBackspaceAt <= dedupeWindowMs) {
172
+ return "";
173
+ }
174
+ lastBackspaceAt = ts;
175
+ return data;
176
+ };
177
+ }
43
178
  export async function runTui(opts) {
44
179
  const config = loadConfig();
45
180
  const initialSessionInput = (opts.session ?? "").trim();
@@ -58,6 +193,8 @@ export async function runTui(opts) {
58
193
  let wasDisconnected = false;
59
194
  let toolsExpanded = false;
60
195
  let showThinking = false;
196
+ let pairingHintShown = false;
197
+ const localRunIds = new Set();
61
198
  const deliverDefault = opts.deliver ?? false;
62
199
  const autoMessage = opts.message?.trim();
63
200
  let autoMessageSent = false;
@@ -185,12 +322,39 @@ export async function runTui(opts) {
185
322
  lastCtrlCAt = value;
186
323
  },
187
324
  };
325
+ const noteLocalRunId = (runId) => {
326
+ if (!runId) {
327
+ return;
328
+ }
329
+ localRunIds.add(runId);
330
+ if (localRunIds.size > 200) {
331
+ const [first] = localRunIds;
332
+ if (first) {
333
+ localRunIds.delete(first);
334
+ }
335
+ }
336
+ };
337
+ const forgetLocalRunId = (runId) => {
338
+ localRunIds.delete(runId);
339
+ };
340
+ const isLocalRunId = (runId) => localRunIds.has(runId);
341
+ const clearLocalRunIds = () => {
342
+ localRunIds.clear();
343
+ };
188
344
  const client = new GatewayChatClient({
189
345
  url: opts.url,
190
346
  token: opts.token,
191
347
  password: opts.password,
192
348
  });
193
349
  const tui = new TUI(new ProcessTerminal());
350
+ const dedupeBackspace = createBackspaceDeduper();
351
+ tui.addInputListener((data) => {
352
+ const next = dedupeBackspace(data);
353
+ if (next.length === 0) {
354
+ return { consume: true };
355
+ }
356
+ return { data: next };
357
+ });
194
358
  const header = new Text("", 1, 0);
195
359
  const statusContainer = new Container();
196
360
  const footer = new Text("", 1, 0);
@@ -212,8 +376,9 @@ export async function runTui(opts) {
212
376
  tui.addChild(root);
213
377
  tui.setFocus(editor);
214
378
  const formatSessionKey = (key) => {
215
- if (key === "global" || key === "unknown")
379
+ if (key === "global" || key === "unknown") {
216
380
  return key;
381
+ }
217
382
  const parsed = parseAgentSessionKey(key);
218
383
  return parsed?.rest ?? key;
219
384
  };
@@ -222,43 +387,35 @@ export async function runTui(opts) {
222
387
  return name ? `${id} (${name})` : id;
223
388
  };
224
389
  const resolveSessionKey = (raw) => {
225
- const trimmed = (raw ?? "").trim();
226
- if (sessionScope === "global")
227
- return "global";
228
- if (!trimmed) {
229
- return buildAgentMainSessionKey({
230
- agentId: currentAgentId,
231
- mainKey: sessionMainKey,
232
- });
233
- }
234
- if (trimmed === "global" || trimmed === "unknown")
235
- return trimmed;
236
- if (trimmed.startsWith("agent:"))
237
- return trimmed;
238
- return `agent:${currentAgentId}:${trimmed}`;
390
+ return resolveTuiSessionKey({
391
+ raw,
392
+ sessionScope,
393
+ currentAgentId,
394
+ sessionMainKey,
395
+ });
239
396
  };
240
397
  currentSessionKey = resolveSessionKey(initialSessionInput);
241
- const getContentWidth = () => Math.max(20, (tui.terminal.columns ?? 80) - 2); // paddingX=1 each side
242
398
  const updateHeader = () => {
243
399
  const sessionLabel = formatSessionKey(currentSessionKey);
244
400
  const agentLabel = formatAgentLabel(currentAgentId);
245
- const raw = `poolbot tui - ${client.connection.url} - agent ${agentLabel} - session ${sessionLabel}`;
246
- header.setText(theme.header(truncateToWidth(raw, getContentWidth())));
401
+ header.setText(theme.header(`poolbot tui - ${client.connection.url} - agent ${agentLabel} - session ${sessionLabel}`));
247
402
  };
248
403
  const busyStates = new Set(["sending", "waiting", "streaming", "running"]);
249
404
  let statusText = null;
250
405
  let statusLoader = null;
251
406
  const formatElapsed = (startMs) => {
252
407
  const totalSeconds = Math.max(0, Math.floor((Date.now() - startMs) / 1000));
253
- if (totalSeconds < 60)
408
+ if (totalSeconds < 60) {
254
409
  return `${totalSeconds}s`;
410
+ }
255
411
  const minutes = Math.floor(totalSeconds / 60);
256
412
  const seconds = totalSeconds % 60;
257
413
  return `${minutes}m ${seconds}s`;
258
414
  };
259
415
  const ensureStatusText = () => {
260
- if (statusText)
416
+ if (statusText) {
261
417
  return;
418
+ }
262
419
  statusContainer.clear();
263
420
  statusLoader?.stop();
264
421
  statusLoader = null;
@@ -266,8 +423,9 @@ export async function runTui(opts) {
266
423
  statusContainer.addChild(statusText);
267
424
  };
268
425
  const ensureStatusLoader = () => {
269
- if (statusLoader)
426
+ if (statusLoader) {
270
427
  return;
428
+ }
271
429
  statusContainer.clear();
272
430
  statusText = null;
273
431
  statusLoader = new Loader(tui, (spinner) => theme.accent(spinner), (text) => theme.bold(theme.accentSoft(text)), "");
@@ -277,44 +435,45 @@ export async function runTui(opts) {
277
435
  let waitingTimer = null;
278
436
  let waitingPhrase = null;
279
437
  const updateBusyStatusMessage = () => {
280
- if (!statusLoader || !statusStartedAt)
438
+ if (!statusLoader || !statusStartedAt) {
281
439
  return;
440
+ }
282
441
  const elapsed = formatElapsed(statusStartedAt);
283
- // Truncate status messages to terminal width to prevent TUI crash
284
- // (Loader adds spinner + space = 2 visible chars before the message)
285
- const maxMsgWidth = Math.max(10, getContentWidth() - 4);
286
442
  if (activityStatus === "waiting") {
287
443
  waitingTick++;
288
- const msg = buildWaitingStatusMessage({
444
+ statusLoader.setMessage(buildWaitingStatusMessage({
289
445
  theme,
290
446
  tick: waitingTick,
291
447
  elapsed,
292
448
  connectionStatus,
293
449
  phrases: waitingPhrase ? [waitingPhrase] : undefined,
294
- });
295
- statusLoader.setMessage(truncateToWidth(msg, maxMsgWidth));
450
+ }));
296
451
  return;
297
452
  }
298
- statusLoader.setMessage(truncateToWidth(`${activityStatus} • ${elapsed} | ${connectionStatus}`, maxMsgWidth));
453
+ statusLoader.setMessage(`${activityStatus} • ${elapsed} | ${connectionStatus}`);
299
454
  };
300
455
  const startStatusTimer = () => {
301
- if (statusTimer)
456
+ if (statusTimer) {
302
457
  return;
458
+ }
303
459
  statusTimer = setInterval(() => {
304
- if (!busyStates.has(activityStatus))
460
+ if (!busyStates.has(activityStatus)) {
305
461
  return;
462
+ }
306
463
  updateBusyStatusMessage();
307
464
  }, 1000);
308
465
  };
309
466
  const stopStatusTimer = () => {
310
- if (!statusTimer)
467
+ if (!statusTimer) {
311
468
  return;
469
+ }
312
470
  clearInterval(statusTimer);
313
471
  statusTimer = null;
314
472
  };
315
473
  const startWaitingTimer = () => {
316
- if (waitingTimer)
474
+ if (waitingTimer) {
317
475
  return;
476
+ }
318
477
  // Pick a phrase once per waiting session.
319
478
  if (!waitingPhrase) {
320
479
  const idx = Math.floor(Math.random() * defaultWaitingPhrases.length);
@@ -322,14 +481,16 @@ export async function runTui(opts) {
322
481
  }
323
482
  waitingTick = 0;
324
483
  waitingTimer = setInterval(() => {
325
- if (activityStatus !== "waiting")
484
+ if (activityStatus !== "waiting") {
326
485
  return;
486
+ }
327
487
  updateBusyStatusMessage();
328
488
  }, 120);
329
489
  };
330
490
  const stopWaitingTimer = () => {
331
- if (!waitingTimer)
491
+ if (!waitingTimer) {
332
492
  return;
493
+ }
333
494
  clearInterval(waitingTimer);
334
495
  waitingTimer = null;
335
496
  waitingPhrase = null;
@@ -366,8 +527,9 @@ export async function runTui(opts) {
366
527
  const setConnectionStatus = (text, ttlMs) => {
367
528
  connectionStatus = text;
368
529
  renderStatus();
369
- if (statusTimeout)
530
+ if (statusTimeout) {
370
531
  clearTimeout(statusTimeout);
532
+ }
371
533
  if (ttlMs && ttlMs > 0) {
372
534
  statusTimeout = setTimeout(() => {
373
535
  connectionStatus = isConnected ? "connected" : "disconnected";
@@ -404,12 +566,13 @@ export async function runTui(opts) {
404
566
  reasoningLabel,
405
567
  tokens,
406
568
  ].filter(Boolean);
407
- footer.setText(theme.dim(truncateToWidth(footerParts.join(" | "), getContentWidth())));
569
+ footer.setText(theme.dim(footerParts.join(" | ")));
408
570
  };
409
571
  const { openOverlay, closeOverlay } = createOverlayHandlers(tui, editor);
410
572
  const initialSessionAgentId = (() => {
411
- if (!initialSessionInput)
573
+ if (!initialSessionInput) {
412
574
  return null;
575
+ }
413
576
  const parsed = parseAgentSessionKey(initialSessionInput);
414
577
  return parsed ? normalizeAgentId(parsed.agentId) : null;
415
578
  })();
@@ -427,14 +590,19 @@ export async function runTui(opts) {
427
590
  updateFooter,
428
591
  updateAutocompleteProvider,
429
592
  setActivityStatus,
593
+ clearLocalRunIds,
430
594
  });
431
- const { refreshAgents, refreshSessionInfo, loadHistory, setSession, abortActive } = sessionActions;
595
+ const { refreshAgents, refreshSessionInfo, applySessionInfoFromPatch, loadHistory, setSession, abortActive, } = sessionActions;
432
596
  const { handleChatEvent, handleAgentEvent } = createEventHandlers({
433
597
  chatLog,
434
598
  tui,
435
599
  state,
436
600
  setActivityStatus,
437
601
  refreshSessionInfo,
602
+ loadHistory,
603
+ isLocalRunId,
604
+ forgetLocalRunId,
605
+ clearLocalRunIds,
438
606
  });
439
607
  const { handleCommand, sendMessage, openModelSelector, openAgentSelector, openSessionSelector } = createCommandHandlers({
440
608
  client,
@@ -446,12 +614,15 @@ export async function runTui(opts) {
446
614
  openOverlay,
447
615
  closeOverlay,
448
616
  refreshSessionInfo,
617
+ applySessionInfoFromPatch,
449
618
  loadHistory,
450
619
  setSession,
451
620
  refreshAgents,
452
621
  abortActive,
453
622
  setActivityStatus,
454
623
  formatSessionKey,
624
+ noteLocalRunId,
625
+ forgetLocalRunId,
455
626
  });
456
627
  const { runLocalShellLine } = createLocalShellRunner({
457
628
  chatLog,
@@ -460,12 +631,16 @@ export async function runTui(opts) {
460
631
  closeOverlay,
461
632
  });
462
633
  updateAutocompleteProvider();
463
- editor.onSubmit = createEditorSubmitHandler({
634
+ const submitHandler = createEditorSubmitHandler({
464
635
  editor,
465
636
  handleCommand,
466
637
  sendMessage,
467
638
  handleBangLine: runLocalShellLine,
468
639
  });
640
+ editor.onSubmit = createSubmitBurstCoalescer({
641
+ submit: submitHandler,
642
+ enabled: shouldEnableWindowsGitBashPasteFallback(),
643
+ });
469
644
  editor.onEscape = () => {
470
645
  void abortActive();
471
646
  };
@@ -511,13 +686,16 @@ export async function runTui(opts) {
511
686
  void loadHistory();
512
687
  };
513
688
  client.onEvent = (evt) => {
514
- if (evt.event === "chat")
689
+ if (evt.event === "chat") {
515
690
  handleChatEvent(evt.payload);
516
- if (evt.event === "agent")
691
+ }
692
+ if (evt.event === "agent") {
517
693
  handleAgentEvent(evt.payload);
694
+ }
518
695
  };
519
696
  client.onConnected = () => {
520
697
  isConnected = true;
698
+ pairingHintShown = false;
521
699
  const reconnected = wasDisconnected;
522
700
  wasDisconnected = false;
523
701
  setConnectionStatus("connected");
@@ -539,9 +717,13 @@ export async function runTui(opts) {
539
717
  isConnected = false;
540
718
  wasDisconnected = true;
541
719
  historyLoaded = false;
542
- const reasonLabel = reason?.trim() ? reason.trim() : "closed";
543
- setConnectionStatus(`gateway disconnected: ${reasonLabel}`, 5000);
544
- setActivityStatus("idle");
720
+ const disconnectState = resolveGatewayDisconnectState(reason);
721
+ setConnectionStatus(disconnectState.connectionStatus, 5000);
722
+ setActivityStatus(disconnectState.activityStatus);
723
+ if (disconnectState.pairingHint && !pairingHintShown) {
724
+ pairingHintShown = true;
725
+ chatLog.addSystem(disconnectState.pairingHint);
726
+ }
545
727
  updateFooter();
546
728
  tui.requestRender();
547
729
  };
@@ -554,4 +736,10 @@ export async function runTui(opts) {
554
736
  updateFooter();
555
737
  tui.start();
556
738
  client.start();
739
+ await new Promise((resolve) => {
740
+ const finish = () => resolve();
741
+ process.once("exit", finish);
742
+ process.once("SIGINT", finish);
743
+ process.once("SIGTERM", finish);
744
+ });
557
745
  }
@@ -1,6 +1,4 @@
1
+ import { normalizeOptionalAccountId } from "../routing/account-id.js";
1
2
  export function normalizeAccountId(value) {
2
- if (typeof value !== "string")
3
- return undefined;
4
- const trimmed = value.trim();
5
- return trimmed || undefined;
3
+ return normalizeOptionalAccountId(value);
6
4
  }
@@ -3,20 +3,25 @@ const DEFAULT_FALSY = ["false", "0", "no", "off"];
3
3
  const DEFAULT_TRUTHY_SET = new Set(DEFAULT_TRUTHY);
4
4
  const DEFAULT_FALSY_SET = new Set(DEFAULT_FALSY);
5
5
  export function parseBooleanValue(value, options = {}) {
6
- if (typeof value === "boolean")
6
+ if (typeof value === "boolean") {
7
7
  return value;
8
- if (typeof value !== "string")
8
+ }
9
+ if (typeof value !== "string") {
9
10
  return undefined;
11
+ }
10
12
  const normalized = value.trim().toLowerCase();
11
- if (!normalized)
13
+ if (!normalized) {
12
14
  return undefined;
15
+ }
13
16
  const truthy = options.truthy ?? DEFAULT_TRUTHY;
14
17
  const falsy = options.falsy ?? DEFAULT_FALSY;
15
18
  const truthySet = truthy === DEFAULT_TRUTHY ? DEFAULT_TRUTHY_SET : new Set(truthy);
16
19
  const falsySet = falsy === DEFAULT_FALSY ? DEFAULT_FALSY_SET : new Set(falsy);
17
- if (truthySet.has(normalized))
20
+ if (truthySet.has(normalized)) {
18
21
  return true;
19
- if (falsySet.has(normalized))
22
+ }
23
+ if (falsySet.has(normalized)) {
20
24
  return false;
25
+ }
21
26
  return undefined;
22
27
  }
@@ -6,6 +6,17 @@ function normalizeDirectiveWhitespace(text) {
6
6
  .replace(/[ \t]*\n[ \t]*/g, "\n")
7
7
  .trim();
8
8
  }
9
+ export function stripInlineDirectiveTagsForDisplay(text) {
10
+ if (!text) {
11
+ return { text, changed: false };
12
+ }
13
+ const withoutAudio = text.replace(AUDIO_TAG_RE, "");
14
+ const stripped = withoutAudio.replace(REPLY_TAG_RE, "");
15
+ return {
16
+ text: stripped,
17
+ changed: stripped !== text,
18
+ };
19
+ }
9
20
  export function parseInlineDirectives(text, options = {}) {
10
21
  const { currentMessageId, stripAudioTag = true, stripReplyTags = true } = options;
11
22
  if (!text) {
@@ -0,0 +1,10 @@
1
+ export const maskApiKey = (value) => {
2
+ const trimmed = value.trim();
3
+ if (!trimmed) {
4
+ return "missing";
5
+ }
6
+ if (trimmed.length <= 16) {
7
+ return trimmed;
8
+ }
9
+ return `${trimmed.slice(0, 8)}...${trimmed.slice(-8)}`;
10
+ };