@poolzin/pool-bot 2026.2.24 → 2026.2.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (646) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/acp/client.js +207 -18
  3. package/dist/acp/event-mapper.js +87 -22
  4. package/dist/acp/meta.js +12 -6
  5. package/dist/acp/secret-file.js +22 -0
  6. package/dist/agents/agent-paths.js +8 -9
  7. package/dist/agents/agent-scope.js +17 -5
  8. package/dist/agents/auth-profiles/oauth.js +148 -64
  9. package/dist/agents/auth-profiles/session-override.js +13 -7
  10. package/dist/agents/bash-process-registry.test-helpers.js +29 -0
  11. package/dist/agents/bash-tools.exec-approval-request.js +20 -0
  12. package/dist/agents/bash-tools.exec-host-gateway.js +240 -0
  13. package/dist/agents/bash-tools.exec-host-node.js +235 -0
  14. package/dist/agents/bash-tools.exec-runtime.js +2 -25
  15. package/dist/agents/bash-tools.exec-types.js +1 -0
  16. package/dist/agents/bash-tools.process.js +224 -218
  17. package/dist/agents/bedrock-discovery.js +3 -1
  18. package/dist/agents/byteplus-models.js +97 -0
  19. package/dist/agents/chutes-oauth.js +1 -0
  20. package/dist/agents/cli-runner/helpers.js +4 -0
  21. package/dist/agents/compaction.js +41 -14
  22. package/dist/agents/content-blocks.js +16 -0
  23. package/dist/agents/doubao-models.js +121 -0
  24. package/dist/agents/failover-error.js +2 -0
  25. package/dist/agents/huggingface-models.js +5 -3
  26. package/dist/agents/live-model-filter.js +5 -0
  27. package/dist/agents/minimax-vlm.js +10 -8
  28. package/dist/agents/model-auth.js +6 -0
  29. package/dist/agents/model-catalog.js +3 -1
  30. package/dist/agents/model-fallback.js +96 -101
  31. package/dist/agents/model-selection.js +7 -1
  32. package/dist/agents/models-config.providers.js +364 -165
  33. package/dist/agents/ollama-stream.js +117 -4
  34. package/dist/agents/opencode-zen-models.js +22 -11
  35. package/dist/agents/pi-embedded-helpers/errors.js +55 -33
  36. package/dist/agents/pi-embedded-helpers/messaging-dedupe.js +10 -5
  37. package/dist/agents/pi-embedded-helpers/thinking.js +10 -5
  38. package/dist/agents/pi-embedded-helpers.js +1 -1
  39. package/dist/agents/pi-embedded-payloads.js +1 -0
  40. package/dist/agents/pi-embedded-runner/compact.js +29 -7
  41. package/dist/agents/pi-embedded-runner/extensions.js +28 -26
  42. package/dist/agents/pi-embedded-runner/google.js +20 -8
  43. package/dist/agents/pi-embedded-runner/run/attempt.js +95 -36
  44. package/dist/agents/pi-embedded-runner/run.js +71 -12
  45. package/dist/agents/pi-embedded-runner/run.overflow-compaction.fixture.js +34 -0
  46. package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +11 -2
  47. package/dist/agents/pi-embedded-runner/session-manager-cache.js +11 -7
  48. package/dist/agents/pi-embedded-runner/system-prompt.js +2 -0
  49. package/dist/agents/pi-embedded-runner/thinking.js +42 -0
  50. package/dist/agents/pi-embedded-runner/tool-name-allowlist.js +19 -0
  51. package/dist/agents/pi-embedded-runner/utils.js +7 -10
  52. package/dist/agents/pi-embedded-subscribe.handlers.lifecycle.js +45 -56
  53. package/dist/agents/pi-embedded-subscribe.handlers.tools.js +2 -2
  54. package/dist/agents/pi-embedded-subscribe.js +9 -4
  55. package/dist/agents/pi-embedded-subscribe.tools.js +68 -14
  56. package/dist/agents/pi-embedded-utils.js +3 -0
  57. package/dist/agents/pi-extensions/compaction-safeguard-runtime.js +4 -20
  58. package/dist/agents/pi-extensions/compaction-safeguard.js +75 -33
  59. package/dist/agents/pi-settings.js +40 -0
  60. package/dist/agents/pi-tools.policy.js +2 -1
  61. package/dist/agents/provider/config-loader.js +1 -1
  62. package/dist/agents/sandbox/browser.js +170 -33
  63. package/dist/agents/sandbox/config-hash.js +14 -27
  64. package/dist/agents/sandbox/config.js +21 -2
  65. package/dist/agents/sandbox/constants.js +2 -0
  66. package/dist/agents/sandbox/docker.js +16 -2
  67. package/dist/agents/sandbox/novnc-auth.js +62 -0
  68. package/dist/agents/sandbox/sanitize-env-vars.js +1 -1
  69. package/dist/agents/sandbox/shared.js +10 -6
  70. package/dist/agents/sandbox-paths.js +24 -11
  71. package/dist/agents/schema/clean-for-gemini.js +132 -85
  72. package/dist/agents/session-slug.js +10 -5
  73. package/dist/agents/session-tool-result-guard-wrapper.js +1 -0
  74. package/dist/agents/session-tool-result-guard.js +3 -1
  75. package/dist/agents/session-transcript-repair.js +40 -6
  76. package/dist/agents/skills/bundled-dir.js +19 -5
  77. package/dist/agents/skills/env-overrides.js +124 -43
  78. package/dist/agents/skills/frontmatter.js +6 -6
  79. package/dist/agents/skills/plugin-skills.js +14 -7
  80. package/dist/agents/skills/workspace.js +1 -0
  81. package/dist/agents/skills.test-helpers.js +13 -0
  82. package/dist/agents/stable-stringify.js +12 -0
  83. package/dist/agents/subagent-announce.js +251 -49
  84. package/dist/agents/subagent-lifecycle-events.js +19 -0
  85. package/dist/agents/subagent-registry-cleanup.js +31 -0
  86. package/dist/agents/subagent-registry-completion.js +68 -0
  87. package/dist/agents/subagent-registry-queries.js +117 -0
  88. package/dist/agents/subagent-registry-state.js +46 -0
  89. package/dist/agents/subagent-registry.js +252 -221
  90. package/dist/agents/subagent-registry.mocks.shared.js +12 -0
  91. package/dist/agents/subagent-registry.store.js +1 -0
  92. package/dist/agents/subagent-registry.types.js +1 -0
  93. package/dist/agents/subagent-spawn.js +195 -7
  94. package/dist/agents/system-prompt.js +22 -6
  95. package/dist/agents/test-helpers/assistant-message-fixtures.js +29 -0
  96. package/dist/agents/test-helpers/fast-coding-tools.js +1 -18
  97. package/dist/agents/test-helpers/fast-core-tools.js +1 -17
  98. package/dist/agents/test-helpers/pi-tools-sandbox-context.js +27 -0
  99. package/dist/agents/timeout.js +18 -6
  100. package/dist/agents/tool-call-id.js +1 -1
  101. package/dist/agents/tool-display-common.js +162 -29
  102. package/dist/agents/tool-images.js +82 -9
  103. package/dist/agents/tool-policy-shared.js +108 -0
  104. package/dist/agents/tool-policy.js +51 -26
  105. package/dist/agents/tools/browser-tool.js +160 -54
  106. package/dist/agents/tools/canvas-tool.js +27 -1
  107. package/dist/agents/tools/common.js +45 -0
  108. package/dist/agents/tools/cron-tool.test-helpers.js +12 -0
  109. package/dist/agents/tools/discord-actions-guild.js +4 -1
  110. package/dist/agents/tools/discord-actions-moderation-shared.js +27 -0
  111. package/dist/agents/tools/gateway-tool.js +3 -1
  112. package/dist/agents/tools/image-tool.js +214 -99
  113. package/dist/agents/tools/nodes-utils.js +1 -10
  114. package/dist/agents/tools/sessions-history-tool.js +140 -108
  115. package/dist/agents/tools/sessions-send-helpers.js +12 -6
  116. package/dist/agents/tools/sessions-spawn-tool.js +8 -2
  117. package/dist/agents/tools/subagents-tool.js +2 -1
  118. package/dist/agents/tools/whatsapp-actions.js +10 -2
  119. package/dist/agents/tools/whatsapp-target-auth.js +18 -0
  120. package/dist/agents/transcript-policy.js +22 -8
  121. package/dist/agents/venice-models.js +11 -3
  122. package/dist/agents/workspace.js +222 -46
  123. package/dist/auto-reply/commands-registry.data.js +51 -0
  124. package/dist/auto-reply/commands-registry.js +19 -21
  125. package/dist/auto-reply/fallback-state.js +114 -0
  126. package/dist/auto-reply/group-activation.js +10 -5
  127. package/dist/auto-reply/inbound-debounce.js +10 -5
  128. package/dist/auto-reply/model-runtime.js +68 -0
  129. package/dist/auto-reply/reply/abort.js +1 -1
  130. package/dist/auto-reply/reply/agent-runner-execution.js +40 -5
  131. package/dist/auto-reply/reply/agent-runner.js +165 -39
  132. package/dist/auto-reply/reply/bash-command.js +41 -39
  133. package/dist/auto-reply/reply/command-gates.js +25 -0
  134. package/dist/auto-reply/reply/commands-allowlist.js +111 -72
  135. package/dist/auto-reply/reply/commands-bash.js +6 -5
  136. package/dist/auto-reply/reply/commands-config.js +30 -28
  137. package/dist/auto-reply/reply/commands-core.js +2 -1
  138. package/dist/auto-reply/reply/commands-info.js +1 -0
  139. package/dist/auto-reply/reply/commands-models.js +65 -14
  140. package/dist/auto-reply/reply/commands-session.js +237 -82
  141. package/dist/auto-reply/reply/commands-setunset-standard.js +13 -0
  142. package/dist/auto-reply/reply/commands-setunset.js +45 -0
  143. package/dist/auto-reply/reply/commands-subagents/action-agents.js +44 -0
  144. package/dist/auto-reply/reply/commands-subagents/action-focus.js +64 -0
  145. package/dist/auto-reply/reply/commands-subagents/action-help.js +4 -0
  146. package/dist/auto-reply/reply/commands-subagents/action-info.js +45 -0
  147. package/dist/auto-reply/reply/commands-subagents/action-kill.js +60 -0
  148. package/dist/auto-reply/reply/commands-subagents/action-list.js +44 -0
  149. package/dist/auto-reply/reply/commands-subagents/action-log.js +29 -0
  150. package/dist/auto-reply/reply/commands-subagents/action-send.js +119 -0
  151. package/dist/auto-reply/reply/commands-subagents/action-spawn.js +52 -0
  152. package/dist/auto-reply/reply/commands-subagents/action-unfocus.js +30 -0
  153. package/dist/auto-reply/reply/commands-subagents/shared.js +303 -0
  154. package/dist/auto-reply/reply/commands-subagents.js +51 -587
  155. package/dist/auto-reply/reply/commands-tts.js +10 -5
  156. package/dist/auto-reply/reply/config-value.js +10 -5
  157. package/dist/auto-reply/reply/directive-handling.model-picker.js +12 -6
  158. package/dist/auto-reply/reply/directive-handling.persist.js +9 -21
  159. package/dist/auto-reply/reply/directive-handling.shared.js +24 -4
  160. package/dist/auto-reply/reply/followup-runner.js +1 -0
  161. package/dist/auto-reply/reply/get-reply-directives-utils.js +23 -14
  162. package/dist/auto-reply/reply/get-reply-directives.js +17 -28
  163. package/dist/auto-reply/reply/get-reply-inline-actions.js +1 -0
  164. package/dist/auto-reply/reply/get-reply.js +71 -12
  165. package/dist/auto-reply/reply/model-selection.js +80 -39
  166. package/dist/auto-reply/reply/queue/enqueue.js +10 -5
  167. package/dist/auto-reply/reply/queue/state.js +13 -12
  168. package/dist/auto-reply/reply/reply-payloads.js +67 -36
  169. package/dist/auto-reply/reply/reply-reference.js +9 -8
  170. package/dist/auto-reply/reply/route-reply.js +15 -8
  171. package/dist/auto-reply/reply/session-reset-prompt.js +1 -1
  172. package/dist/auto-reply/reply/session.js +22 -6
  173. package/dist/auto-reply/reply/strip-inbound-meta.js +147 -0
  174. package/dist/auto-reply/reply/subagents-utils.js +56 -30
  175. package/dist/auto-reply/reply/typing.js +46 -21
  176. package/dist/auto-reply/send-policy.js +14 -7
  177. package/dist/auto-reply/status.js +140 -16
  178. package/dist/auto-reply/templating.js +10 -5
  179. package/dist/auto-reply/thinking.js +7 -16
  180. package/dist/auto-reply/tokens.js +21 -5
  181. package/dist/browser/bridge-server.js +36 -20
  182. package/dist/browser/cdp.helpers.js +7 -14
  183. package/dist/browser/cdp.js +35 -15
  184. package/dist/browser/chrome.profile-decoration.js +7 -4
  185. package/dist/browser/config.js +30 -0
  186. package/dist/browser/extension-relay-auth.js +55 -0
  187. package/dist/browser/extension-relay.js +74 -29
  188. package/dist/browser/navigation-guard.js +39 -0
  189. package/dist/browser/paths.js +77 -0
  190. package/dist/browser/profiles.js +13 -8
  191. package/dist/browser/pw-ai-module.js +10 -5
  192. package/dist/browser/pw-session.js +76 -39
  193. package/dist/browser/pw-tools-core.interactions.js +14 -7
  194. package/dist/browser/pw-tools-core.state.js +12 -6
  195. package/dist/browser/routes/agent.act.js +431 -424
  196. package/dist/browser/routes/agent.shared.js +47 -3
  197. package/dist/browser/routes/agent.snapshot.js +122 -116
  198. package/dist/browser/routes/agent.storage.js +303 -297
  199. package/dist/browser/routes/tabs.js +154 -100
  200. package/dist/browser/server-context.js +7 -0
  201. package/dist/browser/server-lifecycle.js +37 -0
  202. package/dist/build-info.json +3 -3
  203. package/dist/channels/allow-from.js +26 -0
  204. package/dist/channels/allowlists/resolve-utils.js +43 -19
  205. package/dist/channels/channel-config.js +14 -7
  206. package/dist/channels/draft-stream-loop.js +7 -0
  207. package/dist/channels/model-overrides.js +82 -0
  208. package/dist/channels/plugins/account-action-gate.js +13 -0
  209. package/dist/channels/plugins/message-actions.js +10 -0
  210. package/dist/channels/plugins/normalize/imessage.js +14 -7
  211. package/dist/channels/plugins/normalize/slack.js +10 -5
  212. package/dist/channels/plugins/normalize/telegram.js +14 -7
  213. package/dist/channels/plugins/outbound/discord.js +80 -8
  214. package/dist/channels/plugins/outbound/signal.js +11 -11
  215. package/dist/channels/plugins/setup-helpers.js +10 -5
  216. package/dist/channels/sender-label.js +14 -7
  217. package/dist/channels/session.js +4 -2
  218. package/dist/channels/status-reactions.js +297 -0
  219. package/dist/channels/telegram/api.js +18 -0
  220. package/dist/cli/argv.js +84 -21
  221. package/dist/cli/banner.js +3 -2
  222. package/dist/cli/browser-cli-actions-input/register.files-downloads.js +65 -56
  223. package/dist/cli/cli-name.js +11 -11
  224. package/dist/cli/cli-utils.js +13 -3
  225. package/dist/cli/command-format.js +1 -1
  226. package/dist/cli/config-cli.js +1 -1
  227. package/dist/cli/daemon-cli/lifecycle-core.js +31 -19
  228. package/dist/cli/daemon-cli/lifecycle.js +64 -2
  229. package/dist/cli/daemon-cli/restart-health.js +126 -0
  230. package/dist/cli/daemon-cli/status.gather.js +9 -13
  231. package/dist/cli/daemon-cli/status.print.js +2 -10
  232. package/dist/cli/deps.js +27 -22
  233. package/dist/cli/exec-approvals-cli.js +92 -124
  234. package/dist/cli/gateway-cli/run-loop.js +23 -5
  235. package/dist/cli/memory-cli.js +158 -61
  236. package/dist/cli/node-cli/register.js +14 -5
  237. package/dist/cli/nodes-cli/register.push.js +63 -0
  238. package/dist/cli/nodes-media-utils.js +26 -0
  239. package/dist/cli/outbound-send-deps.js +2 -9
  240. package/dist/cli/outbound-send-mapping.js +11 -0
  241. package/dist/cli/pairing-cli.js +40 -14
  242. package/dist/cli/plugins-cli.js +250 -73
  243. package/dist/cli/ports.js +11 -10
  244. package/dist/cli/program/build-program.js +3 -1
  245. package/dist/cli/program/command-registry.js +214 -136
  246. package/dist/cli/program/command-tree.js +16 -0
  247. package/dist/cli/program/help.js +43 -12
  248. package/dist/cli/program/preaction.js +13 -9
  249. package/dist/cli/program/register.configure.js +3 -18
  250. package/dist/cli/program/register.maintenance.js +2 -2
  251. package/dist/cli/program/register.onboard.js +2 -0
  252. package/dist/cli/program/register.status-health-sessions.js +16 -17
  253. package/dist/cli/program/register.subclis.js +93 -52
  254. package/dist/cli/route.js +12 -8
  255. package/dist/cli/system-cli.js +36 -46
  256. package/dist/cli/test-runtime-capture.js +24 -0
  257. package/dist/cli/update-cli/shared.js +22 -9
  258. package/dist/cli/update-cli/update-command.js +89 -14
  259. package/dist/cli/update-cli/wizard.js +6 -12
  260. package/dist/commands/agent/run-context.js +18 -5
  261. package/dist/commands/agent/session-store.js +17 -4
  262. package/dist/commands/agent.js +185 -89
  263. package/dist/commands/agents.bindings.js +14 -7
  264. package/dist/commands/agents.commands.add.js +13 -9
  265. package/dist/commands/agents.commands.identity.js +12 -6
  266. package/dist/commands/agents.commands.list.js +11 -6
  267. package/dist/commands/agents.config.js +8 -10
  268. package/dist/commands/agents.providers.js +12 -6
  269. package/dist/commands/auth-choice-options.js +103 -75
  270. package/dist/commands/auth-choice.apply.byteplus.js +55 -0
  271. package/dist/commands/auth-choice.apply.js +4 -0
  272. package/dist/commands/auth-choice.apply.minimax.js +61 -13
  273. package/dist/commands/auth-choice.apply.openai.js +3 -1
  274. package/dist/commands/auth-choice.apply.volcengine.js +55 -0
  275. package/dist/commands/auth-choice.preferred-provider.js +2 -0
  276. package/dist/commands/channels/remove.js +13 -6
  277. package/dist/commands/channels/shared.js +4 -14
  278. package/dist/commands/channels.mock-harness.js +23 -0
  279. package/dist/commands/configure.commands.js +14 -0
  280. package/dist/commands/configure.gateway.js +2 -4
  281. package/dist/commands/configure.js +1 -1
  282. package/dist/commands/configure.shared.js +11 -0
  283. package/dist/commands/daemon-install-helpers.js +2 -2
  284. package/dist/commands/daemon-install-runtime-warning.js +11 -0
  285. package/dist/commands/dashboard.js +12 -10
  286. package/dist/commands/docs.js +14 -8
  287. package/dist/commands/doctor-config-flow.js +11 -9
  288. package/dist/commands/doctor-legacy-config.js +281 -0
  289. package/dist/commands/doctor-state-integrity.js +99 -23
  290. package/dist/commands/doctor-update.js +12 -9
  291. package/dist/commands/models/list.list-command.js +7 -5
  292. package/dist/commands/models/set-image.js +2 -21
  293. package/dist/commands/node-daemon-install-helpers.js +10 -8
  294. package/dist/commands/onboard-auth.config-minimax.js +54 -80
  295. package/dist/commands/onboard-auth.config-opencode.js +2 -18
  296. package/dist/commands/onboard-auth.credentials.js +90 -13
  297. package/dist/commands/onboard-auth.js +1 -1
  298. package/dist/commands/onboard-auth.models.js +6 -5
  299. package/dist/commands/onboard-hooks.js +1 -1
  300. package/dist/commands/onboard-non-interactive/api-keys.js +14 -7
  301. package/dist/commands/onboard-non-interactive/local/auth-choice.js +64 -49
  302. package/dist/commands/onboard-provider-auth-flags.js +14 -0
  303. package/dist/commands/onboard-remote.js +14 -7
  304. package/dist/commands/onboard.js +11 -13
  305. package/dist/commands/sandbox-display.js +6 -5
  306. package/dist/commands/sessions.test-helpers.js +61 -0
  307. package/dist/commands/status-all/diagnosis.js +14 -10
  308. package/dist/commands/status-all/format.js +1 -0
  309. package/dist/commands/status.gateway-probe.js +1 -16
  310. package/dist/commands/systemd-linger.js +12 -6
  311. package/dist/config/agent-limits.js +2 -0
  312. package/dist/config/commands.js +32 -15
  313. package/dist/config/config-paths.js +9 -11
  314. package/dist/config/config.js +1 -1
  315. package/dist/config/defaults.js +22 -2
  316. package/dist/config/discord-preview-streaming.js +104 -0
  317. package/dist/config/env-substitution.js +62 -34
  318. package/dist/config/env-vars.js +45 -7
  319. package/dist/config/includes.js +4 -0
  320. package/dist/config/io.js +656 -171
  321. package/dist/config/legacy.migrations.part-1.js +189 -78
  322. package/dist/config/legacy.shared.js +3 -1
  323. package/dist/config/merge-patch.js +54 -4
  324. package/dist/config/prototype-keys.js +4 -0
  325. package/dist/config/redact-snapshot.js +404 -76
  326. package/dist/config/schema.help.js +44 -7
  327. package/dist/config/schema.js +58 -570
  328. package/dist/config/schema.labels.js +38 -6
  329. package/dist/config/sessions/delivery-info.js +10 -3
  330. package/dist/config/sessions/main-session.js +10 -5
  331. package/dist/config/sessions/session-file.js +33 -0
  332. package/dist/config/sessions/session-key.js +10 -5
  333. package/dist/config/sessions/store.js +1 -1
  334. package/dist/config/sessions.js +1 -0
  335. package/dist/config/validation.js +140 -85
  336. package/dist/config/zod-schema.agent-runtime.js +11 -0
  337. package/dist/config/zod-schema.hooks.js +40 -11
  338. package/dist/config/zod-schema.installs.js +20 -0
  339. package/dist/config/zod-schema.js +156 -20
  340. package/dist/config/zod-schema.providers-core.js +78 -4
  341. package/dist/config/zod-schema.providers.js +6 -1
  342. package/dist/config/zod-schema.session.js +41 -2
  343. package/dist/cron/run-log.js +3 -0
  344. package/dist/cron/schedule.js +21 -10
  345. package/dist/cron/service/ops.js +35 -21
  346. package/dist/cron/service/timer.js +116 -16
  347. package/dist/cron/stagger.js +3 -1
  348. package/dist/daemon/cmd-argv.js +21 -0
  349. package/dist/daemon/cmd-set.js +58 -0
  350. package/dist/daemon/service-types.js +1 -0
  351. package/dist/discord/api.js +12 -6
  352. package/dist/discord/draft-chunking.js +22 -0
  353. package/dist/discord/draft-stream.js +124 -0
  354. package/dist/discord/monitor/agent-components.js +1 -1
  355. package/dist/discord/monitor/commands.js +5 -0
  356. package/dist/discord/monitor/exec-approvals.js +357 -162
  357. package/dist/discord/monitor/gateway-plugin.js +2 -1
  358. package/dist/discord/monitor/listeners.js +37 -27
  359. package/dist/discord/monitor/message-handler.js +4 -1
  360. package/dist/discord/monitor/message-handler.preflight.js +65 -8
  361. package/dist/discord/monitor/message-handler.process.js +246 -217
  362. package/dist/discord/monitor/message-utils.js +143 -6
  363. package/dist/discord/monitor/model-picker-preferences.js +143 -0
  364. package/dist/discord/monitor/model-picker.js +651 -0
  365. package/dist/discord/monitor/native-command.js +573 -16
  366. package/dist/discord/monitor/provider.allowlist.js +223 -0
  367. package/dist/discord/monitor/provider.js +275 -347
  368. package/dist/discord/monitor/provider.lifecycle.js +100 -0
  369. package/dist/discord/monitor/reply-delivery.js +123 -16
  370. package/dist/discord/monitor/thread-bindings.discord-api.js +215 -0
  371. package/dist/discord/monitor/thread-bindings.js +4 -0
  372. package/dist/discord/monitor/thread-bindings.lifecycle.js +177 -0
  373. package/dist/discord/monitor/thread-bindings.manager.js +423 -0
  374. package/dist/discord/monitor/thread-bindings.messages.js +55 -0
  375. package/dist/discord/monitor/thread-bindings.state.js +358 -0
  376. package/dist/discord/monitor/thread-bindings.types.js +6 -0
  377. package/dist/discord/resolve-users.js +33 -21
  378. package/dist/discord/send.channels.js +15 -0
  379. package/dist/discord/send.js +3 -2
  380. package/dist/discord/send.outbound.js +82 -26
  381. package/dist/discord/send.permissions.js +83 -30
  382. package/dist/discord/send.reactions.js +8 -4
  383. package/dist/discord/token.js +10 -5
  384. package/dist/discord/voice/command.js +263 -0
  385. package/dist/discord/voice/manager.js +531 -0
  386. package/dist/gateway/auth.js +72 -13
  387. package/dist/gateway/call.js +152 -83
  388. package/dist/gateway/canvas-capability.js +75 -0
  389. package/dist/gateway/client.js +28 -4
  390. package/dist/gateway/config-reload.js +3 -4
  391. package/dist/gateway/control-plane-audit.js +28 -0
  392. package/dist/gateway/control-plane-rate-limit.js +53 -0
  393. package/dist/gateway/control-ui.js +219 -96
  394. package/dist/gateway/events.js +1 -0
  395. package/dist/gateway/hooks-mapping.js +88 -38
  396. package/dist/gateway/hooks.js +109 -54
  397. package/dist/gateway/http-auth-helpers.js +3 -2
  398. package/dist/gateway/http-common.js +22 -0
  399. package/dist/gateway/http-endpoint-helpers.js +1 -0
  400. package/dist/gateway/method-scopes.js +169 -0
  401. package/dist/gateway/net.js +74 -9
  402. package/dist/gateway/node-invoke-system-run-approval.js +14 -35
  403. package/dist/gateway/node-registry.js +10 -5
  404. package/dist/gateway/openai-http.js +1 -0
  405. package/dist/gateway/openresponses-http.js +121 -110
  406. package/dist/gateway/origin-check.js +1 -18
  407. package/dist/gateway/probe-auth.js +2 -0
  408. package/dist/gateway/protocol/index.js +4 -2
  409. package/dist/gateway/protocol/schema/cron.js +1 -0
  410. package/dist/gateway/protocol/schema/devices.js +1 -0
  411. package/dist/gateway/protocol/schema/protocol-schemas.js +4 -1
  412. package/dist/gateway/protocol/schema/push.js +18 -0
  413. package/dist/gateway/protocol/schema/sessions.js +6 -0
  414. package/dist/gateway/protocol/schema.js +1 -0
  415. package/dist/gateway/role-policy.js +17 -0
  416. package/dist/gateway/server/ws-connection/connect-policy.js +37 -0
  417. package/dist/gateway/server/ws-connection/message-handler.js +175 -148
  418. package/dist/gateway/server-chat.js +83 -25
  419. package/dist/gateway/server-constants.js +10 -9
  420. package/dist/gateway/server-cron.js +1 -0
  421. package/dist/gateway/server-http.js +247 -54
  422. package/dist/gateway/server-maintenance.js +20 -5
  423. package/dist/gateway/server-methods/agent.js +162 -24
  424. package/dist/gateway/server-methods/chat.js +465 -130
  425. package/dist/gateway/server-methods/config.js +193 -152
  426. package/dist/gateway/server-methods/devices.js +17 -3
  427. package/dist/gateway/server-methods/models.js +11 -1
  428. package/dist/gateway/server-methods/nodes.helpers.js +12 -0
  429. package/dist/gateway/server-methods/nodes.js +251 -69
  430. package/dist/gateway/server-methods/push.js +53 -0
  431. package/dist/gateway/server-methods/sessions.js +64 -8
  432. package/dist/gateway/server-methods/usage.js +162 -75
  433. package/dist/gateway/server-node-events.js +29 -0
  434. package/dist/gateway/server-reload-handlers.js +2 -3
  435. package/dist/gateway/server-runtime-config.js +39 -13
  436. package/dist/gateway/server-runtime-state.js +2 -0
  437. package/dist/gateway/server-startup-memory.js +17 -11
  438. package/dist/gateway/server-ws-runtime.js +1 -0
  439. package/dist/gateway/server.impl.js +296 -139
  440. package/dist/gateway/session-preview.test-helpers.js +11 -0
  441. package/dist/gateway/session-utils.fs.js +32 -34
  442. package/dist/gateway/sessions-resolve.js +17 -5
  443. package/dist/gateway/startup-auth.js +126 -0
  444. package/dist/gateway/test-helpers.agent-results.js +15 -0
  445. package/dist/gateway/test-helpers.mocks.js +37 -14
  446. package/dist/gateway/test-helpers.openai-mock.js +14 -7
  447. package/dist/gateway/test-helpers.server.js +161 -77
  448. package/dist/gateway/tools-invoke-http.js +21 -10
  449. package/dist/hooks/bundled/bootstrap-extra-files/handler.js +3 -1
  450. package/dist/hooks/bundled/command-logger/handler.js +7 -2
  451. package/dist/hooks/bundled/session-memory/handler.js +170 -38
  452. package/dist/hooks/frontmatter.js +6 -6
  453. package/dist/hooks/gmail-watcher-lifecycle.js +23 -0
  454. package/dist/hooks/gmail-watcher.js +11 -6
  455. package/dist/hooks/internal-hooks.js +11 -1
  456. package/dist/hooks/llm-slug-generator.js +4 -1
  457. package/dist/hooks/workspace.js +47 -17
  458. package/dist/imessage/accounts.js +9 -20
  459. package/dist/imessage/monitor/inbound-processing.js +2 -1
  460. package/dist/infra/archive-path.js +49 -0
  461. package/dist/infra/archive.js +174 -73
  462. package/dist/infra/control-ui-assets.js +14 -6
  463. package/dist/infra/device-pairing.js +204 -144
  464. package/dist/infra/env.js +10 -5
  465. package/dist/infra/exec-approvals-allowlist.js +141 -70
  466. package/dist/infra/exec-approvals-analysis.js +78 -20
  467. package/dist/infra/exec-approvals.js +5 -17
  468. package/dist/infra/exec-safe-bin-policy.js +277 -0
  469. package/dist/infra/fixed-window-rate-limit.js +33 -0
  470. package/dist/infra/fs-safe.js +71 -39
  471. package/dist/infra/gateway-lock.js +6 -2
  472. package/dist/infra/git-root.js +61 -0
  473. package/dist/infra/heartbeat-active-hours.js +2 -2
  474. package/dist/infra/heartbeat-reason.js +40 -0
  475. package/dist/infra/heartbeat-runner.js +72 -32
  476. package/dist/infra/heartbeat-wake.js +6 -12
  477. package/dist/infra/host-env-security-policy.json +19 -0
  478. package/dist/infra/host-env-security.js +66 -0
  479. package/dist/infra/install-source-utils.js +91 -7
  480. package/dist/infra/net/ssrf.js +131 -38
  481. package/dist/infra/node-pairing.js +50 -105
  482. package/dist/infra/npm-integrity.js +45 -0
  483. package/dist/infra/npm-pack-install.js +40 -0
  484. package/dist/infra/outbound/bound-delivery-router.js +88 -0
  485. package/dist/infra/outbound/channel-adapters.js +20 -7
  486. package/dist/infra/outbound/channel-selection.js +12 -6
  487. package/dist/infra/outbound/envelope.js +1 -1
  488. package/dist/infra/outbound/format.js +12 -6
  489. package/dist/infra/outbound/message-action-runner.js +107 -327
  490. package/dist/infra/outbound/message.js +59 -36
  491. package/dist/infra/outbound/outbound-policy.js +52 -25
  492. package/dist/infra/outbound/outbound-send-service.js +58 -71
  493. package/dist/infra/outbound/payloads.js +14 -7
  494. package/dist/infra/outbound/session-binding-service.js +123 -0
  495. package/dist/infra/pairing-files.js +10 -0
  496. package/dist/infra/path-guards.js +25 -0
  497. package/dist/infra/plain-object.js +9 -0
  498. package/dist/infra/provider-usage.fetch.codex.js +7 -15
  499. package/dist/infra/provider-usage.fetch.gemini.js +14 -11
  500. package/dist/infra/provider-usage.fetch.shared.js +30 -1
  501. package/dist/infra/provider-usage.fetch.zai.js +10 -9
  502. package/dist/infra/push-apns.js +365 -0
  503. package/dist/infra/restart-sentinel.js +16 -1
  504. package/dist/infra/restart.js +229 -26
  505. package/dist/infra/retry-policy.js +4 -2
  506. package/dist/infra/retry.js +9 -5
  507. package/dist/infra/scp-host.js +54 -0
  508. package/dist/infra/session-cost-usage.js +107 -59
  509. package/dist/infra/session-maintenance-warning.js +3 -1
  510. package/dist/infra/shell-env.js +98 -34
  511. package/dist/infra/ssh-config.js +12 -6
  512. package/dist/infra/system-run-command.js +49 -4
  513. package/dist/infra/update-channels.js +10 -5
  514. package/dist/infra/update-startup.js +86 -9
  515. package/dist/line/accounts.js +5 -7
  516. package/dist/line/bot-access.js +8 -20
  517. package/dist/line/bot-handlers.js +3 -1
  518. package/dist/link-understanding/detect.js +15 -7
  519. package/dist/media/constants.js +15 -6
  520. package/dist/media/image-ops.js +7 -0
  521. package/dist/media/inbound-path-policy.js +114 -0
  522. package/dist/media/input-files.js +16 -0
  523. package/dist/media/local-roots.js +3 -2
  524. package/dist/media-understanding/apply.js +4 -1
  525. package/dist/media-understanding/concurrency.js +8 -20
  526. package/dist/memory/backend-config.js +45 -6
  527. package/dist/memory/embeddings.js +10 -4
  528. package/dist/memory/fs-utils.js +23 -0
  529. package/dist/memory/manager-search.js +12 -6
  530. package/dist/memory/manager-sync-ops.js +12 -2
  531. package/dist/memory/qmd-manager.js +466 -53
  532. package/dist/memory/query-expansion.js +167 -3
  533. package/dist/memory/status-format.js +10 -5
  534. package/dist/memory/sync-memory-files.js +1 -1
  535. package/dist/memory/test-manager.js +8 -0
  536. package/dist/node-host/invoke-system-run.js +281 -0
  537. package/dist/node-host/invoke.js +55 -337
  538. package/dist/pairing/pairing-store.js +22 -0
  539. package/dist/plugin-sdk/allow-from.js +1 -1
  540. package/dist/plugin-sdk/command-auth.js +3 -1
  541. package/dist/plugin-sdk/index.js +6 -3
  542. package/dist/plugin-sdk/temp-path.js +47 -0
  543. package/dist/plugin-sdk/webhook-targets.js +32 -0
  544. package/dist/plugins/bundled-dir.js +9 -6
  545. package/dist/plugins/discovery.js +217 -23
  546. package/dist/plugins/hook-runner-global.js +16 -0
  547. package/dist/plugins/hooks.js +50 -0
  548. package/dist/plugins/install.js +28 -16
  549. package/dist/plugins/loader.js +192 -26
  550. package/dist/plugins/logger.js +8 -0
  551. package/dist/plugins/manifest-registry.js +3 -0
  552. package/dist/plugins/path-safety.js +34 -0
  553. package/dist/plugins/registry.js +5 -2
  554. package/dist/plugins/runtime/index.js +271 -206
  555. package/dist/plugins/runtime.js +3 -17
  556. package/dist/plugins/update.js +78 -12
  557. package/dist/process/spawn-utils.js +14 -7
  558. package/dist/providers/github-copilot-models.js +4 -1
  559. package/dist/providers/github-copilot-token.js +11 -6
  560. package/dist/providers/qwen-portal-oauth.js +14 -6
  561. package/dist/routing/account-id.js +30 -0
  562. package/dist/routing/resolve-route.js +3 -7
  563. package/dist/routing/session-key.js +2 -16
  564. package/dist/security/audit-channel.js +100 -20
  565. package/dist/security/audit-extra.async.js +505 -179
  566. package/dist/security/audit-extra.js +12 -2
  567. package/dist/security/audit-extra.sync.js +421 -35
  568. package/dist/security/audit-fs.js +31 -13
  569. package/dist/security/audit.js +180 -370
  570. package/dist/security/dm-policy-shared.js +68 -0
  571. package/dist/security/external-content.js +46 -14
  572. package/dist/security/fix.js +49 -85
  573. package/dist/security/scan-paths.js +20 -0
  574. package/dist/security/secret-equal.js +3 -7
  575. package/dist/security/windows-acl.js +30 -15
  576. package/dist/shared/entry-status.js +6 -0
  577. package/dist/shared/frontmatter.js +5 -5
  578. package/dist/shared/node-list-parse.js +13 -0
  579. package/dist/shared/node-match.js +11 -4
  580. package/dist/shared/operator-scope-compat.js +42 -0
  581. package/dist/shared/text-chunking.js +29 -0
  582. package/dist/signal/accounts.js +7 -20
  583. package/dist/signal/monitor/event-handler.js +3 -1
  584. package/dist/slack/accounts.js +6 -19
  585. package/dist/slack/actions.js +11 -3
  586. package/dist/slack/blocks.test-helpers.js +31 -0
  587. package/dist/slack/monitor/auth.js +1 -1
  588. package/dist/slack/monitor/message-handler/dispatch.js +50 -29
  589. package/dist/slack/monitor/mrkdwn.js +8 -0
  590. package/dist/slack/monitor/replies.js +15 -7
  591. package/dist/slack/monitor/slash.js +22 -13
  592. package/dist/slack/resolve-channels.js +10 -5
  593. package/dist/slack/send.js +102 -12
  594. package/dist/slack/stream-mode.js +10 -0
  595. package/dist/slack/streaming.js +4 -2
  596. package/dist/telegram/accounts.js +19 -14
  597. package/dist/telegram/bot/helpers.js +3 -5
  598. package/dist/telegram/bot-access.js +35 -36
  599. package/dist/telegram/bot-handlers.js +120 -148
  600. package/dist/telegram/bot-message-context.js +68 -9
  601. package/dist/telegram/bot-message-dispatch.js +477 -210
  602. package/dist/telegram/bot-native-commands.js +16 -0
  603. package/dist/telegram/draft-stream.js +44 -8
  604. package/dist/telegram/inline-buttons.js +5 -15
  605. package/dist/telegram/monitor.js +11 -7
  606. package/dist/telegram/network-config.js +19 -7
  607. package/dist/telegram/reasoning-lane-coordinator.js +128 -0
  608. package/dist/telegram/send.js +3 -2
  609. package/dist/telegram/sent-message-cache.js +5 -6
  610. package/dist/telegram/status-reaction-variants.js +208 -0
  611. package/dist/telegram/sticker-cache.js +11 -9
  612. package/dist/terminal/prompt-select-styled.js +9 -0
  613. package/dist/terminal/theme.js +12 -12
  614. package/dist/test-utils/command-runner.js +6 -0
  615. package/dist/test-utils/internal-hook-event-payload.js +10 -0
  616. package/dist/test-utils/model-auth-mock.js +12 -0
  617. package/dist/test-utils/provider-usage-fetch.js +14 -0
  618. package/dist/test-utils/temp-home.js +33 -0
  619. package/dist/tts/tts.js +80 -567
  620. package/dist/tui/components/chat-log.js +50 -8
  621. package/dist/tui/theme/theme.js +10 -12
  622. package/dist/tui/tui-command-handlers.js +36 -27
  623. package/dist/tui/tui-event-handlers.js +122 -32
  624. package/dist/tui/tui-local-shell.js +16 -6
  625. package/dist/tui/tui.js +236 -48
  626. package/dist/utils/account-id.js +2 -4
  627. package/dist/utils/boolean.js +10 -5
  628. package/dist/utils/directive-tags.js +11 -0
  629. package/dist/utils/mask-api-key.js +10 -0
  630. package/dist/utils/queue-helpers.js +67 -12
  631. package/dist/utils/run-with-concurrency.js +39 -0
  632. package/dist/web/auto-reply/deliver-reply.js +8 -4
  633. package/dist/web/auto-reply/mentions.js +10 -5
  634. package/dist/web/auto-reply/monitor/group-members.js +14 -7
  635. package/dist/web/auto-reply/monitor/process-message.js +45 -24
  636. package/dist/web/inbound/access-control.js +5 -2
  637. package/dist/web/login-qr.js +12 -6
  638. package/dist/web/media.js +126 -15
  639. package/docs/tools/slash-commands.md +5 -1
  640. package/extensions/bluebubbles/src/monitor-processing.ts +580 -139
  641. package/extensions/bluebubbles/src/monitor.ts +208 -1950
  642. package/extensions/feishu/src/external-keys.ts +19 -0
  643. package/extensions/lobster/src/windows-spawn.ts +193 -0
  644. package/extensions/matrix/src/matrix/actions/limits.ts +6 -0
  645. package/extensions/mattermost/src/mattermost/reactions.test-helpers.ts +83 -0
  646. package/package.json +1 -1
@@ -1,28 +1,24 @@
1
1
  import { abortEmbeddedPiRun } from "../../agents/pi-embedded.js";
2
+ import { parseDurationMs } from "../../cli/parse-duration.js";
3
+ import { isRestartEnabled } from "../../config/commands.js";
2
4
  import { updateSessionStore } from "../../config/sessions.js";
5
+ import { formatThreadBindingTtlLabel, getThreadBindingManager, setThreadBindingTtlBySessionKey, } from "../../discord/monitor/thread-bindings.js";
3
6
  import { logVerbose } from "../../globals.js";
4
7
  import { createInternalHookEvent, triggerInternalHook } from "../../hooks/internal-hooks.js";
5
8
  import { scheduleGatewaySigusr1Restart, triggerPoolbotRestart } from "../../infra/restart.js";
9
+ import { loadCostUsageSummary, loadSessionCostSummary } from "../../infra/session-cost-usage.js";
10
+ import { formatTokenCount, formatUsd } from "../../utils/usage-format.js";
6
11
  import { parseActivationCommand } from "../group-activation.js";
7
12
  import { parseSendPolicyCommand } from "../send-policy.js";
8
13
  import { normalizeUsageDisplay, resolveResponseUsageMode } from "../thinking.js";
9
- import { loadCostUsageSummary, loadSessionCostSummary } from "../../infra/session-cost-usage.js";
10
- import { formatTokenCount, formatUsd } from "../../utils/usage-format.js";
11
- import { formatAbortReplyText, isAbortTrigger, setAbortMemory, stopSubagentsForRequester, } from "./abort.js";
14
+ import { formatAbortReplyText, isAbortTrigger, resolveSessionEntryForKey, setAbortMemory, stopSubagentsForRequester, } from "./abort.js";
12
15
  import { clearSessionQueues } from "./queue.js";
13
- function resolveSessionEntryForKey(store, sessionKey) {
14
- if (!store || !sessionKey)
15
- return {};
16
- const direct = store[sessionKey];
17
- if (direct)
18
- return { entry: direct, key: sessionKey };
19
- return {};
20
- }
21
16
  function resolveAbortTarget(params) {
22
17
  const targetSessionKey = params.ctx.CommandTargetSessionKey?.trim() || params.sessionKey;
23
18
  const { entry, key } = resolveSessionEntryForKey(params.sessionStore, targetSessionKey);
24
- if (entry && key)
19
+ if (entry && key) {
25
20
  return { entry, key, sessionId: entry.sessionId };
21
+ }
26
22
  if (params.sessionEntry && params.sessionKey) {
27
23
  return {
28
24
  entry: params.sessionEntry,
@@ -32,12 +28,84 @@ function resolveAbortTarget(params) {
32
28
  }
33
29
  return { entry: undefined, key: targetSessionKey, sessionId: undefined };
34
30
  }
31
+ const SESSION_COMMAND_PREFIX = "/session";
32
+ const SESSION_TTL_OFF_VALUES = new Set(["off", "disable", "disabled", "none", "0"]);
33
+ function isDiscordSurface(params) {
34
+ const channel = params.ctx.OriginatingChannel ??
35
+ params.command.channel ??
36
+ params.ctx.Surface ??
37
+ params.ctx.Provider;
38
+ return (String(channel ?? "")
39
+ .trim()
40
+ .toLowerCase() === "discord");
41
+ }
42
+ function resolveDiscordAccountId(params) {
43
+ const accountId = typeof params.ctx.AccountId === "string" ? params.ctx.AccountId.trim() : "";
44
+ return accountId || "default";
45
+ }
46
+ function resolveSessionCommandUsage() {
47
+ return "Usage: /session ttl <duration|off> (example: /session ttl 24h)";
48
+ }
49
+ function parseSessionTtlMs(raw) {
50
+ const normalized = raw.trim().toLowerCase();
51
+ if (!normalized) {
52
+ throw new Error("missing ttl");
53
+ }
54
+ if (SESSION_TTL_OFF_VALUES.has(normalized)) {
55
+ return 0;
56
+ }
57
+ if (/^\d+(?:\.\d+)?$/.test(normalized)) {
58
+ const hours = Number(normalized);
59
+ if (!Number.isFinite(hours) || hours < 0) {
60
+ throw new Error("invalid ttl");
61
+ }
62
+ return Math.round(hours * 60 * 60 * 1000);
63
+ }
64
+ return parseDurationMs(normalized, { defaultUnit: "h" });
65
+ }
66
+ function formatSessionExpiry(expiresAt) {
67
+ return new Date(expiresAt).toISOString();
68
+ }
69
+ async function applyAbortTarget(params) {
70
+ const { abortTarget } = params;
71
+ if (abortTarget.sessionId) {
72
+ abortEmbeddedPiRun(abortTarget.sessionId);
73
+ }
74
+ if (abortTarget.entry && params.sessionStore && abortTarget.key) {
75
+ abortTarget.entry.abortedLastRun = true;
76
+ abortTarget.entry.updatedAt = Date.now();
77
+ params.sessionStore[abortTarget.key] = abortTarget.entry;
78
+ if (params.storePath) {
79
+ await updateSessionStore(params.storePath, (store) => {
80
+ store[abortTarget.key] = abortTarget.entry;
81
+ });
82
+ }
83
+ }
84
+ else if (params.abortKey) {
85
+ setAbortMemory(params.abortKey, true);
86
+ }
87
+ }
88
+ async function persistSessionEntry(params) {
89
+ if (!params.sessionEntry || !params.sessionStore || !params.sessionKey) {
90
+ return false;
91
+ }
92
+ params.sessionEntry.updatedAt = Date.now();
93
+ params.sessionStore[params.sessionKey] = params.sessionEntry;
94
+ if (params.storePath) {
95
+ await updateSessionStore(params.storePath, (store) => {
96
+ store[params.sessionKey] = params.sessionEntry;
97
+ });
98
+ }
99
+ return true;
100
+ }
35
101
  export const handleActivationCommand = async (params, allowTextCommands) => {
36
- if (!allowTextCommands)
102
+ if (!allowTextCommands) {
37
103
  return null;
104
+ }
38
105
  const activationCommand = parseActivationCommand(params.command.commandBodyNormalized);
39
- if (!activationCommand.hasCommand)
106
+ if (!activationCommand.hasCommand) {
40
107
  return null;
108
+ }
41
109
  if (!params.isGroup) {
42
110
  return {
43
111
  shouldContinue: false,
@@ -57,13 +125,7 @@ export const handleActivationCommand = async (params, allowTextCommands) => {
57
125
  if (params.sessionEntry && params.sessionStore && params.sessionKey) {
58
126
  params.sessionEntry.groupActivation = activationCommand.mode;
59
127
  params.sessionEntry.groupActivationNeedsSystemIntro = true;
60
- params.sessionEntry.updatedAt = Date.now();
61
- params.sessionStore[params.sessionKey] = params.sessionEntry;
62
- if (params.storePath) {
63
- await updateSessionStore(params.storePath, (store) => {
64
- store[params.sessionKey] = params.sessionEntry;
65
- });
66
- }
128
+ await persistSessionEntry(params);
67
129
  }
68
130
  return {
69
131
  shouldContinue: false,
@@ -73,11 +135,13 @@ export const handleActivationCommand = async (params, allowTextCommands) => {
73
135
  };
74
136
  };
75
137
  export const handleSendPolicyCommand = async (params, allowTextCommands) => {
76
- if (!allowTextCommands)
138
+ if (!allowTextCommands) {
77
139
  return null;
140
+ }
78
141
  const sendPolicyCommand = parseSendPolicyCommand(params.command.commandBodyNormalized);
79
- if (!sendPolicyCommand.hasCommand)
142
+ if (!sendPolicyCommand.hasCommand) {
80
143
  return null;
144
+ }
81
145
  if (!params.command.isAuthorizedSender) {
82
146
  logVerbose(`Ignoring /send from unauthorized sender: ${params.command.senderId || "<unknown>"}`);
83
147
  return { shouldContinue: false };
@@ -95,13 +159,7 @@ export const handleSendPolicyCommand = async (params, allowTextCommands) => {
95
159
  else {
96
160
  params.sessionEntry.sendPolicy = sendPolicyCommand.mode;
97
161
  }
98
- params.sessionEntry.updatedAt = Date.now();
99
- params.sessionStore[params.sessionKey] = params.sessionEntry;
100
- if (params.storePath) {
101
- await updateSessionStore(params.storePath, (store) => {
102
- store[params.sessionKey] = params.sessionEntry;
103
- });
104
- }
162
+ await persistSessionEntry(params);
105
163
  }
106
164
  const label = sendPolicyCommand.mode === "inherit"
107
165
  ? "inherit"
@@ -114,11 +172,13 @@ export const handleSendPolicyCommand = async (params, allowTextCommands) => {
114
172
  };
115
173
  };
116
174
  export const handleUsageCommand = async (params, allowTextCommands) => {
117
- if (!allowTextCommands)
175
+ if (!allowTextCommands) {
118
176
  return null;
177
+ }
119
178
  const normalized = params.command.commandBodyNormalized;
120
- if (normalized !== "/usage" && !normalized.startsWith("/usage "))
179
+ if (normalized !== "/usage" && !normalized.startsWith("/usage ")) {
121
180
  return null;
181
+ }
122
182
  if (!params.command.isAuthorizedSender) {
123
183
  logVerbose(`Ignoring /usage from unauthorized sender: ${params.command.senderId || "<unknown>"}`);
124
184
  return { shouldContinue: false };
@@ -131,6 +191,7 @@ export const handleUsageCommand = async (params, allowTextCommands) => {
131
191
  sessionEntry: params.sessionEntry,
132
192
  sessionFile: params.sessionEntry?.sessionFile,
133
193
  config: params.cfg,
194
+ agentId: params.agentId,
134
195
  });
135
196
  const summary = await loadCostUsageSummary({ days: 30, config: params.cfg });
136
197
  const sessionCost = formatUsd(sessionSummary?.totalCost);
@@ -168,17 +229,13 @@ export const handleUsageCommand = async (params, allowTextCommands) => {
168
229
  const current = resolveResponseUsageMode(currentRaw);
169
230
  const next = requested ?? (current === "off" ? "tokens" : current === "tokens" ? "full" : "off");
170
231
  if (params.sessionEntry && params.sessionStore && params.sessionKey) {
171
- if (next === "off")
232
+ if (next === "off") {
172
233
  delete params.sessionEntry.responseUsage;
173
- else
234
+ }
235
+ else {
174
236
  params.sessionEntry.responseUsage = next;
175
- params.sessionEntry.updatedAt = Date.now();
176
- params.sessionStore[params.sessionKey] = params.sessionEntry;
177
- if (params.storePath) {
178
- await updateSessionStore(params.storePath, (store) => {
179
- store[params.sessionKey] = params.sessionEntry;
180
- });
181
237
  }
238
+ await persistSessionEntry(params);
182
239
  }
183
240
  return {
184
241
  shouldContinue: false,
@@ -187,20 +244,134 @@ export const handleUsageCommand = async (params, allowTextCommands) => {
187
244
  },
188
245
  };
189
246
  };
247
+ export const handleSessionCommand = async (params, allowTextCommands) => {
248
+ if (!allowTextCommands) {
249
+ return null;
250
+ }
251
+ const normalized = params.command.commandBodyNormalized;
252
+ if (!/^\/session(?:\s|$)/.test(normalized)) {
253
+ return null;
254
+ }
255
+ if (!params.command.isAuthorizedSender) {
256
+ logVerbose(`Ignoring /session from unauthorized sender: ${params.command.senderId || "<unknown>"}`);
257
+ return { shouldContinue: false };
258
+ }
259
+ const rest = normalized.slice(SESSION_COMMAND_PREFIX.length).trim();
260
+ const tokens = rest.split(/\s+/).filter(Boolean);
261
+ const action = tokens[0]?.toLowerCase();
262
+ if (action !== "ttl") {
263
+ return {
264
+ shouldContinue: false,
265
+ reply: { text: resolveSessionCommandUsage() },
266
+ };
267
+ }
268
+ if (!isDiscordSurface(params)) {
269
+ return {
270
+ shouldContinue: false,
271
+ reply: { text: "⚠️ /session ttl is currently available for Discord thread-bound sessions." },
272
+ };
273
+ }
274
+ const threadId = params.ctx.MessageThreadId != null ? String(params.ctx.MessageThreadId).trim() : "";
275
+ if (!threadId) {
276
+ return {
277
+ shouldContinue: false,
278
+ reply: { text: "⚠️ /session ttl must be run inside a focused Discord thread." },
279
+ };
280
+ }
281
+ const accountId = resolveDiscordAccountId(params);
282
+ const threadBindings = getThreadBindingManager(accountId);
283
+ if (!threadBindings) {
284
+ return {
285
+ shouldContinue: false,
286
+ reply: { text: "⚠️ Discord thread bindings are unavailable for this account." },
287
+ };
288
+ }
289
+ const binding = threadBindings.getByThreadId(threadId);
290
+ if (!binding) {
291
+ return {
292
+ shouldContinue: false,
293
+ reply: { text: "ℹ️ This thread is not currently focused." },
294
+ };
295
+ }
296
+ const ttlArgRaw = tokens.slice(1).join("");
297
+ if (!ttlArgRaw) {
298
+ const expiresAt = binding.expiresAt;
299
+ if (typeof expiresAt === "number" && Number.isFinite(expiresAt) && expiresAt > Date.now()) {
300
+ return {
301
+ shouldContinue: false,
302
+ reply: {
303
+ text: `ℹ️ Session TTL active (${formatThreadBindingTtlLabel(expiresAt - Date.now())}, auto-unfocus at ${formatSessionExpiry(expiresAt)}).`,
304
+ },
305
+ };
306
+ }
307
+ return {
308
+ shouldContinue: false,
309
+ reply: { text: "ℹ️ Session TTL is currently disabled for this focused session." },
310
+ };
311
+ }
312
+ const senderId = params.command.senderId?.trim() || "";
313
+ if (binding.boundBy && binding.boundBy !== "system" && senderId && senderId !== binding.boundBy) {
314
+ return {
315
+ shouldContinue: false,
316
+ reply: { text: `⚠️ Only ${binding.boundBy} can update session TTL for this thread.` },
317
+ };
318
+ }
319
+ let ttlMs;
320
+ try {
321
+ ttlMs = parseSessionTtlMs(ttlArgRaw);
322
+ }
323
+ catch {
324
+ return {
325
+ shouldContinue: false,
326
+ reply: { text: resolveSessionCommandUsage() },
327
+ };
328
+ }
329
+ const updatedBindings = setThreadBindingTtlBySessionKey({
330
+ targetSessionKey: binding.targetSessionKey,
331
+ accountId,
332
+ ttlMs,
333
+ });
334
+ if (updatedBindings.length === 0) {
335
+ return {
336
+ shouldContinue: false,
337
+ reply: { text: "⚠️ Failed to update session TTL for the current binding." },
338
+ };
339
+ }
340
+ if (ttlMs <= 0) {
341
+ return {
342
+ shouldContinue: false,
343
+ reply: {
344
+ text: `✅ Session TTL disabled for ${updatedBindings.length} binding${updatedBindings.length === 1 ? "" : "s"}.`,
345
+ },
346
+ };
347
+ }
348
+ const expiresAt = updatedBindings[0]?.expiresAt;
349
+ const expiryLabel = typeof expiresAt === "number" && Number.isFinite(expiresAt)
350
+ ? formatSessionExpiry(expiresAt)
351
+ : "n/a";
352
+ return {
353
+ shouldContinue: false,
354
+ reply: {
355
+ text: `✅ Session TTL set to ${formatThreadBindingTtlLabel(ttlMs)} for ${updatedBindings.length} binding${updatedBindings.length === 1 ? "" : "s"} (auto-unfocus at ${expiryLabel}).`,
356
+ },
357
+ };
358
+ };
190
359
  export const handleRestartCommand = async (params, allowTextCommands) => {
191
- if (!allowTextCommands)
360
+ if (!allowTextCommands) {
192
361
  return null;
193
- if (params.command.commandBodyNormalized !== "/restart")
362
+ }
363
+ if (params.command.commandBodyNormalized !== "/restart") {
194
364
  return null;
365
+ }
195
366
  if (!params.command.isAuthorizedSender) {
196
367
  logVerbose(`Ignoring /restart from unauthorized sender: ${params.command.senderId || "<unknown>"}`);
197
368
  return { shouldContinue: false };
198
369
  }
199
- if (params.cfg.commands?.restart !== true) {
370
+ if (!isRestartEnabled(params.cfg)) {
200
371
  return {
201
372
  shouldContinue: false,
202
373
  reply: {
203
- text: "⚠️ /restart is disabled. Set commands.restart=true to enable.",
374
+ text: "⚠️ /restart is disabled (commands.restart=false).",
204
375
  },
205
376
  };
206
377
  }
@@ -210,7 +381,7 @@ export const handleRestartCommand = async (params, allowTextCommands) => {
210
381
  return {
211
382
  shouldContinue: false,
212
383
  reply: {
213
- text: "⚙️ Restarting poolbot in-process (SIGUSR1); back in a few seconds.",
384
+ text: "⚙️ Restarting Pool Bot in-process (SIGUSR1); back in a few seconds.",
214
385
  },
215
386
  };
216
387
  }
@@ -227,15 +398,17 @@ export const handleRestartCommand = async (params, allowTextCommands) => {
227
398
  return {
228
399
  shouldContinue: false,
229
400
  reply: {
230
- text: `⚙️ Restarting poolbot via ${restartMethod.method}; give me a few seconds to come back online.`,
401
+ text: `⚙️ Restarting Pool Bot via ${restartMethod.method}; give me a few seconds to come back online.`,
231
402
  },
232
403
  };
233
404
  };
234
405
  export const handleStopCommand = async (params, allowTextCommands) => {
235
- if (!allowTextCommands)
406
+ if (!allowTextCommands) {
236
407
  return null;
237
- if (params.command.commandBodyNormalized !== "/stop")
408
+ }
409
+ if (params.command.commandBodyNormalized !== "/stop") {
238
410
  return null;
411
+ }
239
412
  if (!params.command.isAuthorizedSender) {
240
413
  logVerbose(`Ignoring /stop from unauthorized sender: ${params.command.senderId || "<unknown>"}`);
241
414
  return { shouldContinue: false };
@@ -246,26 +419,16 @@ export const handleStopCommand = async (params, allowTextCommands) => {
246
419
  sessionEntry: params.sessionEntry,
247
420
  sessionStore: params.sessionStore,
248
421
  });
249
- if (abortTarget.sessionId) {
250
- abortEmbeddedPiRun(abortTarget.sessionId);
251
- }
252
422
  const cleared = clearSessionQueues([abortTarget.key, abortTarget.sessionId]);
253
423
  if (cleared.followupCleared > 0 || cleared.laneCleared > 0) {
254
424
  logVerbose(`stop: cleared followups=${cleared.followupCleared} lane=${cleared.laneCleared} keys=${cleared.keys.join(",")}`);
255
425
  }
256
- if (abortTarget.entry && params.sessionStore && abortTarget.key) {
257
- abortTarget.entry.abortedLastRun = true;
258
- abortTarget.entry.updatedAt = Date.now();
259
- params.sessionStore[abortTarget.key] = abortTarget.entry;
260
- if (params.storePath) {
261
- await updateSessionStore(params.storePath, (store) => {
262
- store[abortTarget.key] = abortTarget.entry;
263
- });
264
- }
265
- }
266
- else if (params.command.abortKey) {
267
- setAbortMemory(params.command.abortKey, true);
268
- }
426
+ await applyAbortTarget({
427
+ abortTarget,
428
+ sessionStore: params.sessionStore,
429
+ storePath: params.storePath,
430
+ abortKey: params.command.abortKey,
431
+ });
269
432
  // Trigger internal hook for stop command
270
433
  const hookEvent = createInternalHookEvent("command", "stop", abortTarget.key ?? params.sessionKey ?? "", {
271
434
  sessionEntry: abortTarget.entry ?? params.sessionEntry,
@@ -281,31 +444,23 @@ export const handleStopCommand = async (params, allowTextCommands) => {
281
444
  return { shouldContinue: false, reply: { text: formatAbortReplyText(stopped) } };
282
445
  };
283
446
  export const handleAbortTrigger = async (params, allowTextCommands) => {
284
- if (!allowTextCommands)
447
+ if (!allowTextCommands) {
285
448
  return null;
286
- if (!isAbortTrigger(params.command.rawBodyNormalized))
449
+ }
450
+ if (!isAbortTrigger(params.command.rawBodyNormalized)) {
287
451
  return null;
452
+ }
288
453
  const abortTarget = resolveAbortTarget({
289
454
  ctx: params.ctx,
290
455
  sessionKey: params.sessionKey,
291
456
  sessionEntry: params.sessionEntry,
292
457
  sessionStore: params.sessionStore,
293
458
  });
294
- if (abortTarget.sessionId) {
295
- abortEmbeddedPiRun(abortTarget.sessionId);
296
- }
297
- if (abortTarget.entry && params.sessionStore && abortTarget.key) {
298
- abortTarget.entry.abortedLastRun = true;
299
- abortTarget.entry.updatedAt = Date.now();
300
- params.sessionStore[abortTarget.key] = abortTarget.entry;
301
- if (params.storePath) {
302
- await updateSessionStore(params.storePath, (store) => {
303
- store[abortTarget.key] = abortTarget.entry;
304
- });
305
- }
306
- }
307
- else if (params.command.abortKey) {
308
- setAbortMemory(params.command.abortKey, true);
309
- }
459
+ await applyAbortTarget({
460
+ abortTarget,
461
+ sessionStore: params.sessionStore,
462
+ storePath: params.storePath,
463
+ abortKey: params.command.abortKey,
464
+ });
310
465
  return { shouldContinue: false, reply: { text: "⚙️ Agent was aborted." } };
311
466
  };
@@ -0,0 +1,13 @@
1
+ import { parseSlashCommandWithSetUnset } from "./commands-setunset.js";
2
+ export function parseStandardSetUnsetSlashCommand(params) {
3
+ return parseSlashCommandWithSetUnset({
4
+ raw: params.raw,
5
+ slash: params.slash,
6
+ invalidMessage: params.invalidMessage,
7
+ usageMessage: params.usageMessage,
8
+ onKnownAction: params.onKnownAction,
9
+ onSet: params.onSet ?? ((path, value) => ({ action: "set", path, value })),
10
+ onUnset: params.onUnset ?? ((path) => ({ action: "unset", path })),
11
+ onError: params.onError ?? ((message) => ({ action: "error", message })),
12
+ });
13
+ }
@@ -1,3 +1,4 @@
1
+ import { parseSlashCommandOrNull } from "./commands-slash-parse.js";
1
2
  import { parseConfigValue } from "./config-value.js";
2
3
  export function parseSetUnsetCommand(params) {
3
4
  const action = params.action;
@@ -26,3 +27,47 @@ export function parseSetUnsetCommand(params) {
26
27
  }
27
28
  return { kind: "set", path, value: parsed.value };
28
29
  }
30
+ export function parseSetUnsetCommandAction(params) {
31
+ if (params.action !== "set" && params.action !== "unset") {
32
+ return null;
33
+ }
34
+ const parsed = parseSetUnsetCommand({
35
+ slash: params.slash,
36
+ action: params.action,
37
+ args: params.args,
38
+ });
39
+ if (parsed.kind === "error") {
40
+ return params.onError(parsed.message);
41
+ }
42
+ return parsed.kind === "set"
43
+ ? params.onSet(parsed.path, parsed.value)
44
+ : params.onUnset(parsed.path);
45
+ }
46
+ export function parseSlashCommandWithSetUnset(params) {
47
+ const parsed = parseSlashCommandOrNull(params.raw, params.slash, {
48
+ invalidMessage: params.invalidMessage,
49
+ });
50
+ if (!parsed) {
51
+ return null;
52
+ }
53
+ if (!parsed.ok) {
54
+ return params.onError(parsed.message);
55
+ }
56
+ const { action, args } = parsed;
57
+ const setUnset = parseSetUnsetCommandAction({
58
+ slash: params.slash,
59
+ action,
60
+ args,
61
+ onSet: params.onSet,
62
+ onUnset: params.onUnset,
63
+ onError: params.onError,
64
+ });
65
+ if (setUnset) {
66
+ return setUnset;
67
+ }
68
+ const knownAction = params.onKnownAction(action, args);
69
+ if (knownAction) {
70
+ return knownAction;
71
+ }
72
+ return params.onError(params.usageMessage);
73
+ }
@@ -0,0 +1,44 @@
1
+ import { getThreadBindingManager } from "../../../discord/monitor/thread-bindings.js";
2
+ import { formatRunLabel, sortSubagentRuns } from "../subagents-utils.js";
3
+ import { isDiscordSurface, resolveDiscordAccountId, stopWithText, } from "./shared.js";
4
+ export function handleSubagentsAgentsAction(ctx) {
5
+ const { params, requesterKey, runs } = ctx;
6
+ const isDiscord = isDiscordSurface(params);
7
+ const accountId = isDiscord ? resolveDiscordAccountId(params) : undefined;
8
+ const threadBindings = accountId ? getThreadBindingManager(accountId) : null;
9
+ const visibleRuns = sortSubagentRuns(runs).filter((entry) => {
10
+ if (!entry.endedAt) {
11
+ return true;
12
+ }
13
+ return Boolean(threadBindings?.listBySessionKey(entry.childSessionKey)[0]);
14
+ });
15
+ const lines = ["agents:", "-----"];
16
+ if (visibleRuns.length === 0) {
17
+ lines.push("(none)");
18
+ }
19
+ else {
20
+ let index = 1;
21
+ for (const entry of visibleRuns) {
22
+ const threadBinding = threadBindings?.listBySessionKey(entry.childSessionKey)[0];
23
+ const bindingText = threadBinding
24
+ ? `thread:${threadBinding.threadId}`
25
+ : isDiscord
26
+ ? "unbound"
27
+ : "bindings available on discord";
28
+ lines.push(`${index}. ${formatRunLabel(entry)} (${bindingText})`);
29
+ index += 1;
30
+ }
31
+ }
32
+ if (threadBindings) {
33
+ const acpBindings = threadBindings
34
+ .listBindings()
35
+ .filter((entry) => entry.targetKind === "acp" && entry.targetSessionKey === requesterKey);
36
+ if (acpBindings.length > 0) {
37
+ lines.push("", "acp/session bindings:", "-----");
38
+ for (const binding of acpBindings) {
39
+ lines.push(`- ${binding.label ?? binding.targetSessionKey} (thread:${binding.threadId}, session:${binding.targetSessionKey})`);
40
+ }
41
+ }
42
+ }
43
+ return stopWithText(lines.join("\n"));
44
+ }
@@ -0,0 +1,64 @@
1
+ import { getThreadBindingManager, resolveThreadBindingIntroText, resolveThreadBindingThreadName, } from "../../../discord/monitor/thread-bindings.js";
2
+ import { isDiscordSurface, resolveDiscordAccountId, resolveDiscordChannelIdForFocus, resolveFocusTargetSession, stopWithText, } from "./shared.js";
3
+ export async function handleSubagentsFocusAction(ctx) {
4
+ const { params, runs, restTokens } = ctx;
5
+ if (!isDiscordSurface(params)) {
6
+ return stopWithText("⚠️ /focus is only available on Discord.");
7
+ }
8
+ const token = restTokens.join(" ").trim();
9
+ if (!token) {
10
+ return stopWithText("Usage: /focus <subagent-label|session-key|session-id|session-label>");
11
+ }
12
+ const accountId = resolveDiscordAccountId(params);
13
+ const threadBindings = getThreadBindingManager(accountId);
14
+ if (!threadBindings) {
15
+ return stopWithText("⚠️ Discord thread bindings are unavailable for this account.");
16
+ }
17
+ const focusTarget = await resolveFocusTargetSession({ runs, token });
18
+ if (!focusTarget) {
19
+ return stopWithText(`⚠️ Unable to resolve focus target: ${token}`);
20
+ }
21
+ const currentThreadId = params.ctx.MessageThreadId != null ? String(params.ctx.MessageThreadId).trim() : "";
22
+ const parentChannelId = currentThreadId ? undefined : resolveDiscordChannelIdForFocus(params);
23
+ if (!currentThreadId && !parentChannelId) {
24
+ return stopWithText("⚠️ Could not resolve a Discord channel for /focus.");
25
+ }
26
+ const senderId = params.command.senderId?.trim() || "";
27
+ if (currentThreadId) {
28
+ const existingBinding = threadBindings.getByThreadId(currentThreadId);
29
+ if (existingBinding &&
30
+ existingBinding.boundBy &&
31
+ existingBinding.boundBy !== "system" &&
32
+ senderId &&
33
+ senderId !== existingBinding.boundBy) {
34
+ return stopWithText(`⚠️ Only ${existingBinding.boundBy} can refocus this thread.`);
35
+ }
36
+ }
37
+ const label = focusTarget.label || token;
38
+ const binding = await threadBindings.bindTarget({
39
+ threadId: currentThreadId || undefined,
40
+ channelId: parentChannelId,
41
+ createThread: !currentThreadId,
42
+ threadName: resolveThreadBindingThreadName({
43
+ agentId: focusTarget.agentId,
44
+ label,
45
+ }),
46
+ targetKind: focusTarget.targetKind,
47
+ targetSessionKey: focusTarget.targetSessionKey,
48
+ agentId: focusTarget.agentId,
49
+ label,
50
+ boundBy: senderId || "unknown",
51
+ introText: resolveThreadBindingIntroText({
52
+ agentId: focusTarget.agentId,
53
+ label,
54
+ sessionTtlMs: threadBindings.getSessionTtlMs(),
55
+ }),
56
+ });
57
+ if (!binding) {
58
+ return stopWithText("⚠️ Failed to bind a Discord thread to the target session.");
59
+ }
60
+ const actionText = currentThreadId
61
+ ? `bound this thread to ${binding.targetSessionKey}`
62
+ : `created thread ${binding.threadId} and bound it to ${binding.targetSessionKey}`;
63
+ return stopWithText(`✅ ${actionText} (${binding.targetKind}).`);
64
+ }
@@ -0,0 +1,4 @@
1
+ import { buildSubagentsHelp, stopWithText } from "./shared.js";
2
+ export function handleSubagentsHelpAction() {
3
+ return stopWithText(buildSubagentsHelp());
4
+ }