@poolzin/pool-bot 2026.2.25 → 2026.2.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (506) hide show
  1. package/dist/acp/event-mapper.js +87 -22
  2. package/dist/acp/meta.js +12 -6
  3. package/dist/agents/agent-paths.js +8 -9
  4. package/dist/agents/agent-scope.js +7 -5
  5. package/dist/agents/auth-profiles/oauth.js +148 -64
  6. package/dist/agents/auth-profiles/session-override.js +13 -7
  7. package/dist/agents/bash-tools.exec-host-gateway.js +14 -4
  8. package/dist/agents/bash-tools.exec-runtime.js +2 -25
  9. package/dist/agents/bedrock-discovery.js +3 -1
  10. package/dist/agents/byteplus-models.js +97 -0
  11. package/dist/agents/chutes-oauth.js +1 -0
  12. package/dist/agents/cli-runner/helpers.js +4 -0
  13. package/dist/agents/compaction.js +41 -14
  14. package/dist/agents/doubao-models.js +121 -0
  15. package/dist/agents/failover-error.js +2 -0
  16. package/dist/agents/huggingface-models.js +5 -3
  17. package/dist/agents/live-model-filter.js +5 -0
  18. package/dist/agents/minimax-vlm.js +10 -8
  19. package/dist/agents/model-auth.js +6 -0
  20. package/dist/agents/model-catalog.js +3 -1
  21. package/dist/agents/model-selection.js +7 -1
  22. package/dist/agents/models-config.providers.js +93 -11
  23. package/dist/agents/ollama-stream.js +117 -4
  24. package/dist/agents/opencode-zen-models.js +22 -11
  25. package/dist/agents/pi-embedded-helpers/errors.js +55 -33
  26. package/dist/agents/pi-embedded-helpers/messaging-dedupe.js +10 -5
  27. package/dist/agents/pi-embedded-helpers/thinking.js +10 -5
  28. package/dist/agents/pi-embedded-helpers.js +1 -1
  29. package/dist/agents/pi-embedded-runner/compact.js +29 -7
  30. package/dist/agents/pi-embedded-runner/extensions.js +28 -26
  31. package/dist/agents/pi-embedded-runner/google.js +20 -8
  32. package/dist/agents/pi-embedded-runner/run/attempt.js +95 -36
  33. package/dist/agents/pi-embedded-runner/run.js +71 -12
  34. package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +11 -2
  35. package/dist/agents/pi-embedded-runner/session-manager-cache.js +11 -7
  36. package/dist/agents/pi-embedded-runner/system-prompt.js +2 -0
  37. package/dist/agents/pi-embedded-runner/thinking.js +42 -0
  38. package/dist/agents/pi-embedded-runner/tool-name-allowlist.js +19 -0
  39. package/dist/agents/pi-embedded-runner/utils.js +7 -10
  40. package/dist/agents/pi-embedded-subscribe.handlers.lifecycle.js +45 -56
  41. package/dist/agents/pi-embedded-subscribe.handlers.tools.js +2 -2
  42. package/dist/agents/pi-embedded-subscribe.js +9 -4
  43. package/dist/agents/pi-embedded-subscribe.tools.js +68 -14
  44. package/dist/agents/pi-embedded-utils.js +3 -0
  45. package/dist/agents/pi-extensions/compaction-safeguard-runtime.js +4 -20
  46. package/dist/agents/pi-extensions/compaction-safeguard.js +75 -33
  47. package/dist/agents/pi-settings.js +40 -0
  48. package/dist/agents/pi-tools.policy.js +2 -1
  49. package/dist/agents/provider/config-loader.js +1 -1
  50. package/dist/agents/sandbox/browser.js +170 -33
  51. package/dist/agents/sandbox/config-hash.js +14 -27
  52. package/dist/agents/sandbox/config.js +21 -2
  53. package/dist/agents/sandbox/constants.js +2 -0
  54. package/dist/agents/sandbox/docker.js +16 -2
  55. package/dist/agents/sandbox/novnc-auth.js +62 -0
  56. package/dist/agents/sandbox/sanitize-env-vars.js +1 -1
  57. package/dist/agents/sandbox/shared.js +10 -6
  58. package/dist/agents/sandbox-paths.js +24 -11
  59. package/dist/agents/schema/clean-for-gemini.js +132 -85
  60. package/dist/agents/session-slug.js +10 -5
  61. package/dist/agents/session-tool-result-guard-wrapper.js +1 -0
  62. package/dist/agents/session-tool-result-guard.js +3 -1
  63. package/dist/agents/session-transcript-repair.js +40 -6
  64. package/dist/agents/skills/bundled-dir.js +19 -5
  65. package/dist/agents/skills/env-overrides.js +124 -43
  66. package/dist/agents/skills/frontmatter.js +6 -6
  67. package/dist/agents/skills/plugin-skills.js +14 -7
  68. package/dist/agents/skills/workspace.js +1 -0
  69. package/dist/agents/subagent-announce.js +251 -49
  70. package/dist/agents/subagent-lifecycle-events.js +19 -0
  71. package/dist/agents/subagent-registry-cleanup.js +31 -0
  72. package/dist/agents/subagent-registry-completion.js +68 -0
  73. package/dist/agents/subagent-registry-queries.js +117 -0
  74. package/dist/agents/subagent-registry-state.js +46 -0
  75. package/dist/agents/subagent-registry.js +252 -221
  76. package/dist/agents/subagent-registry.store.js +1 -0
  77. package/dist/agents/subagent-registry.types.js +1 -0
  78. package/dist/agents/subagent-spawn.js +195 -7
  79. package/dist/agents/system-prompt.js +22 -6
  80. package/dist/agents/test-helpers/fast-coding-tools.js +1 -18
  81. package/dist/agents/test-helpers/fast-core-tools.js +1 -17
  82. package/dist/agents/timeout.js +18 -6
  83. package/dist/agents/tool-call-id.js +1 -1
  84. package/dist/agents/tool-display-common.js +162 -29
  85. package/dist/agents/tool-images.js +82 -9
  86. package/dist/agents/tool-policy.js +51 -26
  87. package/dist/agents/tools/browser-tool.js +2 -2
  88. package/dist/agents/tools/canvas-tool.js +27 -1
  89. package/dist/agents/tools/common.js +45 -0
  90. package/dist/agents/tools/discord-actions-guild.js +4 -1
  91. package/dist/agents/tools/gateway-tool.js +3 -1
  92. package/dist/agents/tools/nodes-utils.js +1 -10
  93. package/dist/agents/tools/sessions-send-helpers.js +12 -6
  94. package/dist/agents/tools/sessions-spawn-tool.js +8 -2
  95. package/dist/agents/tools/subagents-tool.js +2 -1
  96. package/dist/agents/tools/whatsapp-actions.js +10 -2
  97. package/dist/agents/tools/whatsapp-target-auth.js +18 -0
  98. package/dist/agents/transcript-policy.js +22 -8
  99. package/dist/agents/venice-models.js +11 -3
  100. package/dist/auto-reply/commands-registry.data.js +51 -0
  101. package/dist/auto-reply/commands-registry.js +4 -3
  102. package/dist/auto-reply/group-activation.js +10 -5
  103. package/dist/auto-reply/inbound-debounce.js +10 -5
  104. package/dist/auto-reply/reply/abort.js +1 -1
  105. package/dist/auto-reply/reply/agent-runner-execution.js +4 -1
  106. package/dist/auto-reply/reply/bash-command.js +41 -39
  107. package/dist/auto-reply/reply/command-gates.js +25 -0
  108. package/dist/auto-reply/reply/commands-allowlist.js +111 -72
  109. package/dist/auto-reply/reply/commands-bash.js +6 -5
  110. package/dist/auto-reply/reply/commands-config.js +30 -28
  111. package/dist/auto-reply/reply/commands-core.js +2 -1
  112. package/dist/auto-reply/reply/commands-info.js +1 -0
  113. package/dist/auto-reply/reply/commands-models.js +65 -14
  114. package/dist/auto-reply/reply/commands-session.js +237 -82
  115. package/dist/auto-reply/reply/commands-setunset.js +45 -0
  116. package/dist/auto-reply/reply/commands-subagents/action-agents.js +44 -0
  117. package/dist/auto-reply/reply/commands-subagents/action-focus.js +64 -0
  118. package/dist/auto-reply/reply/commands-subagents/action-help.js +4 -0
  119. package/dist/auto-reply/reply/commands-subagents/action-info.js +45 -0
  120. package/dist/auto-reply/reply/commands-subagents/action-kill.js +60 -0
  121. package/dist/auto-reply/reply/commands-subagents/action-list.js +44 -0
  122. package/dist/auto-reply/reply/commands-subagents/action-log.js +29 -0
  123. package/dist/auto-reply/reply/commands-subagents/action-send.js +119 -0
  124. package/dist/auto-reply/reply/commands-subagents/action-spawn.js +52 -0
  125. package/dist/auto-reply/reply/commands-subagents/action-unfocus.js +30 -0
  126. package/dist/auto-reply/reply/commands-subagents/shared.js +303 -0
  127. package/dist/auto-reply/reply/commands-subagents.js +51 -587
  128. package/dist/auto-reply/reply/commands-tts.js +10 -5
  129. package/dist/auto-reply/reply/config-value.js +10 -5
  130. package/dist/auto-reply/reply/directive-handling.model-picker.js +12 -6
  131. package/dist/auto-reply/reply/directive-handling.persist.js +9 -21
  132. package/dist/auto-reply/reply/directive-handling.shared.js +24 -4
  133. package/dist/auto-reply/reply/followup-runner.js +1 -0
  134. package/dist/auto-reply/reply/get-reply-directives-utils.js +23 -14
  135. package/dist/auto-reply/reply/get-reply-directives.js +17 -28
  136. package/dist/auto-reply/reply/get-reply-inline-actions.js +1 -0
  137. package/dist/auto-reply/reply/get-reply.js +71 -12
  138. package/dist/auto-reply/reply/model-selection.js +80 -39
  139. package/dist/auto-reply/reply/queue/enqueue.js +10 -5
  140. package/dist/auto-reply/reply/queue/state.js +13 -12
  141. package/dist/auto-reply/reply/reply-payloads.js +67 -36
  142. package/dist/auto-reply/reply/reply-reference.js +9 -8
  143. package/dist/auto-reply/reply/route-reply.js +15 -8
  144. package/dist/auto-reply/reply/session-reset-prompt.js +1 -1
  145. package/dist/auto-reply/reply/session.js +22 -6
  146. package/dist/auto-reply/reply/strip-inbound-meta.js +147 -0
  147. package/dist/auto-reply/reply/subagents-utils.js +56 -30
  148. package/dist/auto-reply/reply/typing.js +46 -21
  149. package/dist/auto-reply/send-policy.js +14 -7
  150. package/dist/auto-reply/status.js +140 -16
  151. package/dist/auto-reply/templating.js +10 -5
  152. package/dist/auto-reply/thinking.js +7 -16
  153. package/dist/auto-reply/tokens.js +21 -5
  154. package/dist/browser/bridge-server.js +36 -20
  155. package/dist/browser/cdp.helpers.js +7 -14
  156. package/dist/browser/cdp.js +35 -15
  157. package/dist/browser/chrome.profile-decoration.js +7 -4
  158. package/dist/browser/config.js +4 -0
  159. package/dist/browser/extension-relay-auth.js +55 -0
  160. package/dist/browser/extension-relay.js +74 -29
  161. package/dist/browser/navigation-guard.js +9 -1
  162. package/dist/browser/paths.js +77 -0
  163. package/dist/browser/profiles.js +13 -8
  164. package/dist/browser/pw-ai-module.js +10 -5
  165. package/dist/browser/pw-session.js +76 -39
  166. package/dist/browser/pw-tools-core.interactions.js +14 -7
  167. package/dist/browser/pw-tools-core.state.js +12 -6
  168. package/dist/browser/routes/agent.act.js +2 -2
  169. package/dist/browser/server-context.js +7 -0
  170. package/dist/build-info.json +3 -3
  171. package/dist/channels/allow-from.js +2 -1
  172. package/dist/channels/allowlists/resolve-utils.js +43 -19
  173. package/dist/channels/channel-config.js +14 -7
  174. package/dist/channels/draft-stream-loop.js +7 -0
  175. package/dist/channels/model-overrides.js +82 -0
  176. package/dist/channels/plugins/normalize/imessage.js +14 -7
  177. package/dist/channels/plugins/normalize/slack.js +10 -5
  178. package/dist/channels/plugins/normalize/telegram.js +14 -7
  179. package/dist/channels/plugins/outbound/discord.js +80 -8
  180. package/dist/channels/plugins/outbound/signal.js +11 -11
  181. package/dist/channels/plugins/setup-helpers.js +10 -5
  182. package/dist/channels/sender-label.js +14 -7
  183. package/dist/channels/session.js +4 -2
  184. package/dist/channels/status-reactions.js +297 -0
  185. package/dist/cli/banner.js +1 -1
  186. package/dist/cli/browser-cli-actions-input/register.files-downloads.js +65 -56
  187. package/dist/cli/cli-name.js +11 -11
  188. package/dist/cli/cli-utils.js +13 -3
  189. package/dist/cli/command-format.js +1 -1
  190. package/dist/cli/config-cli.js +1 -1
  191. package/dist/cli/daemon-cli/lifecycle-core.js +31 -19
  192. package/dist/cli/daemon-cli/lifecycle.js +64 -2
  193. package/dist/cli/daemon-cli/restart-health.js +126 -0
  194. package/dist/cli/daemon-cli/status.gather.js +9 -13
  195. package/dist/cli/daemon-cli/status.print.js +2 -10
  196. package/dist/cli/deps.js +27 -22
  197. package/dist/cli/gateway-cli/run-loop.js +23 -5
  198. package/dist/cli/node-cli/register.js +14 -5
  199. package/dist/cli/nodes-media-utils.js +7 -2
  200. package/dist/cli/outbound-send-deps.js +2 -9
  201. package/dist/cli/outbound-send-mapping.js +11 -0
  202. package/dist/cli/pairing-cli.js +40 -14
  203. package/dist/cli/plugins-cli.js +34 -41
  204. package/dist/cli/ports.js +11 -10
  205. package/dist/cli/program/command-registry.js +2 -11
  206. package/dist/cli/program/command-tree.js +16 -0
  207. package/dist/cli/program/preaction.js +13 -9
  208. package/dist/cli/program/register.configure.js +3 -18
  209. package/dist/cli/program/register.maintenance.js +2 -2
  210. package/dist/cli/program/register.onboard.js +2 -0
  211. package/dist/cli/program/register.status-health-sessions.js +16 -17
  212. package/dist/cli/program/register.subclis.js +93 -52
  213. package/dist/cli/route.js +11 -7
  214. package/dist/cli/system-cli.js +36 -46
  215. package/dist/cli/update-cli/shared.js +22 -9
  216. package/dist/cli/update-cli/update-command.js +89 -14
  217. package/dist/cli/update-cli/wizard.js +6 -12
  218. package/dist/commands/agent/run-context.js +18 -5
  219. package/dist/commands/agent/session-store.js +17 -4
  220. package/dist/commands/agent.js +22 -2
  221. package/dist/commands/agents.bindings.js +14 -7
  222. package/dist/commands/agents.commands.add.js +13 -9
  223. package/dist/commands/agents.commands.identity.js +12 -6
  224. package/dist/commands/agents.commands.list.js +11 -6
  225. package/dist/commands/agents.config.js +8 -10
  226. package/dist/commands/agents.providers.js +12 -6
  227. package/dist/commands/auth-choice-options.js +103 -75
  228. package/dist/commands/auth-choice.apply.byteplus.js +55 -0
  229. package/dist/commands/auth-choice.apply.js +4 -0
  230. package/dist/commands/auth-choice.apply.minimax.js +61 -13
  231. package/dist/commands/auth-choice.apply.openai.js +3 -1
  232. package/dist/commands/auth-choice.apply.volcengine.js +55 -0
  233. package/dist/commands/auth-choice.preferred-provider.js +2 -0
  234. package/dist/commands/channels/remove.js +13 -6
  235. package/dist/commands/channels/shared.js +4 -14
  236. package/dist/commands/configure.commands.js +14 -0
  237. package/dist/commands/configure.gateway.js +2 -4
  238. package/dist/commands/configure.js +1 -1
  239. package/dist/commands/configure.shared.js +11 -0
  240. package/dist/commands/daemon-install-helpers.js +2 -2
  241. package/dist/commands/dashboard.js +12 -10
  242. package/dist/commands/docs.js +14 -8
  243. package/dist/commands/doctor-config-flow.js +11 -9
  244. package/dist/commands/doctor-legacy-config.js +281 -0
  245. package/dist/commands/doctor-state-integrity.js +99 -23
  246. package/dist/commands/doctor-update.js +12 -9
  247. package/dist/commands/models/list.list-command.js +7 -5
  248. package/dist/commands/models/set-image.js +2 -21
  249. package/dist/commands/node-daemon-install-helpers.js +10 -8
  250. package/dist/commands/onboard-auth.config-minimax.js +54 -80
  251. package/dist/commands/onboard-auth.config-opencode.js +2 -18
  252. package/dist/commands/onboard-auth.credentials.js +90 -13
  253. package/dist/commands/onboard-auth.js +1 -1
  254. package/dist/commands/onboard-auth.models.js +6 -5
  255. package/dist/commands/onboard-hooks.js +1 -1
  256. package/dist/commands/onboard-non-interactive/api-keys.js +14 -7
  257. package/dist/commands/onboard-non-interactive/local/auth-choice.js +64 -49
  258. package/dist/commands/onboard-provider-auth-flags.js +14 -0
  259. package/dist/commands/onboard-remote.js +14 -7
  260. package/dist/commands/onboard.js +11 -13
  261. package/dist/commands/sandbox-display.js +6 -5
  262. package/dist/commands/status-all/diagnosis.js +14 -10
  263. package/dist/commands/status-all/format.js +1 -0
  264. package/dist/commands/status.gateway-probe.js +1 -16
  265. package/dist/commands/systemd-linger.js +12 -6
  266. package/dist/config/agent-limits.js +2 -0
  267. package/dist/config/commands.js +30 -16
  268. package/dist/config/config-paths.js +9 -11
  269. package/dist/config/defaults.js +22 -2
  270. package/dist/config/discord-preview-streaming.js +104 -0
  271. package/dist/config/env-vars.js +37 -8
  272. package/dist/config/includes.js +4 -0
  273. package/dist/config/io.js +97 -12
  274. package/dist/config/legacy.migrations.part-1.js +189 -78
  275. package/dist/config/legacy.shared.js +3 -1
  276. package/dist/config/merge-patch.js +4 -0
  277. package/dist/config/prototype-keys.js +4 -0
  278. package/dist/config/schema.help.js +44 -7
  279. package/dist/config/schema.labels.js +38 -6
  280. package/dist/config/sessions/delivery-info.js +10 -3
  281. package/dist/config/sessions/main-session.js +10 -5
  282. package/dist/config/sessions/session-file.js +33 -0
  283. package/dist/config/sessions/session-key.js +10 -5
  284. package/dist/config/sessions/store.js +1 -1
  285. package/dist/config/sessions.js +1 -0
  286. package/dist/config/zod-schema.agent-runtime.js +11 -0
  287. package/dist/config/zod-schema.js +148 -13
  288. package/dist/config/zod-schema.providers-core.js +78 -4
  289. package/dist/config/zod-schema.providers.js +6 -1
  290. package/dist/config/zod-schema.session.js +41 -2
  291. package/dist/cron/run-log.js +3 -0
  292. package/dist/cron/schedule.js +21 -10
  293. package/dist/cron/service/ops.js +35 -21
  294. package/dist/cron/service/timer.js +116 -16
  295. package/dist/cron/stagger.js +3 -1
  296. package/dist/discord/api.js +12 -6
  297. package/dist/discord/draft-chunking.js +22 -0
  298. package/dist/discord/draft-stream.js +124 -0
  299. package/dist/discord/monitor/agent-components.js +1 -1
  300. package/dist/discord/monitor/commands.js +5 -0
  301. package/dist/discord/monitor/gateway-plugin.js +2 -1
  302. package/dist/discord/monitor/listeners.js +37 -27
  303. package/dist/discord/monitor/message-handler.js +4 -1
  304. package/dist/discord/monitor/message-handler.preflight.js +65 -8
  305. package/dist/discord/monitor/message-handler.process.js +246 -217
  306. package/dist/discord/monitor/message-utils.js +143 -6
  307. package/dist/discord/monitor/model-picker-preferences.js +143 -0
  308. package/dist/discord/monitor/model-picker.js +651 -0
  309. package/dist/discord/monitor/native-command.js +573 -16
  310. package/dist/discord/monitor/provider.allowlist.js +223 -0
  311. package/dist/discord/monitor/provider.js +275 -347
  312. package/dist/discord/monitor/provider.lifecycle.js +100 -0
  313. package/dist/discord/monitor/reply-delivery.js +123 -16
  314. package/dist/discord/monitor/thread-bindings.discord-api.js +215 -0
  315. package/dist/discord/monitor/thread-bindings.js +4 -0
  316. package/dist/discord/monitor/thread-bindings.lifecycle.js +177 -0
  317. package/dist/discord/monitor/thread-bindings.manager.js +423 -0
  318. package/dist/discord/monitor/thread-bindings.messages.js +55 -0
  319. package/dist/discord/monitor/thread-bindings.state.js +358 -0
  320. package/dist/discord/monitor/thread-bindings.types.js +6 -0
  321. package/dist/discord/resolve-users.js +33 -21
  322. package/dist/discord/send.channels.js +15 -0
  323. package/dist/discord/send.js +3 -2
  324. package/dist/discord/send.outbound.js +82 -26
  325. package/dist/discord/send.permissions.js +83 -30
  326. package/dist/discord/send.reactions.js +8 -4
  327. package/dist/discord/token.js +10 -5
  328. package/dist/discord/voice/command.js +263 -0
  329. package/dist/discord/voice/manager.js +531 -0
  330. package/dist/gateway/auth.js +34 -10
  331. package/dist/gateway/call.js +4 -16
  332. package/dist/gateway/client.js +28 -4
  333. package/dist/gateway/config-reload.js +3 -4
  334. package/dist/gateway/control-ui.js +219 -96
  335. package/dist/gateway/hooks-mapping.js +88 -38
  336. package/dist/gateway/http-auth-helpers.js +3 -2
  337. package/dist/gateway/http-endpoint-helpers.js +1 -0
  338. package/dist/gateway/net.js +54 -12
  339. package/dist/gateway/node-invoke-system-run-approval.js +14 -35
  340. package/dist/gateway/node-registry.js +10 -5
  341. package/dist/gateway/openai-http.js +1 -0
  342. package/dist/gateway/openresponses-http.js +1 -0
  343. package/dist/gateway/origin-check.js +1 -18
  344. package/dist/gateway/protocol/index.js +4 -3
  345. package/dist/gateway/protocol/schema/cron.js +1 -0
  346. package/dist/gateway/protocol/schema/devices.js +1 -0
  347. package/dist/gateway/protocol/schema/protocol-schemas.js +2 -1
  348. package/dist/gateway/protocol/schema/sessions.js +6 -0
  349. package/dist/gateway/role-policy.js +17 -0
  350. package/dist/gateway/server/ws-connection/connect-policy.js +37 -0
  351. package/dist/gateway/server/ws-connection/message-handler.js +175 -148
  352. package/dist/gateway/server-chat.js +83 -25
  353. package/dist/gateway/server-constants.js +10 -9
  354. package/dist/gateway/server-cron.js +1 -0
  355. package/dist/gateway/server-http.js +16 -7
  356. package/dist/gateway/server-maintenance.js +20 -5
  357. package/dist/gateway/server-methods/chat.js +10 -6
  358. package/dist/gateway/server-methods/config.js +12 -14
  359. package/dist/gateway/server-methods/devices.js +17 -3
  360. package/dist/gateway/server-methods/models.js +11 -1
  361. package/dist/gateway/server-methods/sessions.js +64 -8
  362. package/dist/gateway/server-methods/usage.js +162 -75
  363. package/dist/gateway/server-node-events.js +29 -0
  364. package/dist/gateway/server-runtime-config.js +34 -13
  365. package/dist/gateway/server-startup-memory.js +17 -11
  366. package/dist/gateway/session-utils.fs.js +32 -34
  367. package/dist/gateway/sessions-resolve.js +17 -5
  368. package/dist/gateway/test-helpers.openai-mock.js +14 -7
  369. package/dist/gateway/tools-invoke-http.js +21 -10
  370. package/dist/hooks/bundled/bootstrap-extra-files/handler.js +3 -1
  371. package/dist/hooks/bundled/command-logger/handler.js +7 -2
  372. package/dist/hooks/bundled/session-memory/handler.js +6 -5
  373. package/dist/hooks/frontmatter.js +6 -6
  374. package/dist/hooks/gmail-watcher.js +11 -6
  375. package/dist/hooks/internal-hooks.js +11 -1
  376. package/dist/hooks/llm-slug-generator.js +4 -1
  377. package/dist/hooks/workspace.js +47 -17
  378. package/dist/imessage/accounts.js +9 -20
  379. package/dist/imessage/monitor/inbound-processing.js +2 -1
  380. package/dist/infra/archive.js +174 -73
  381. package/dist/infra/control-ui-assets.js +14 -6
  382. package/dist/infra/device-pairing.js +108 -29
  383. package/dist/infra/env.js +10 -5
  384. package/dist/infra/exec-approvals-allowlist.js +122 -0
  385. package/dist/infra/exec-approvals-analysis.js +34 -3
  386. package/dist/infra/exec-approvals.js +5 -17
  387. package/dist/infra/exec-safe-bin-policy.js +53 -45
  388. package/dist/infra/fs-safe.js +71 -39
  389. package/dist/infra/gateway-lock.js +6 -2
  390. package/dist/infra/heartbeat-wake.js +6 -12
  391. package/dist/infra/host-env-security-policy.json +19 -0
  392. package/dist/infra/host-env-security.js +66 -0
  393. package/dist/infra/net/ssrf.js +131 -38
  394. package/dist/infra/outbound/bound-delivery-router.js +88 -0
  395. package/dist/infra/outbound/channel-selection.js +12 -6
  396. package/dist/infra/outbound/envelope.js +1 -1
  397. package/dist/infra/outbound/format.js +12 -6
  398. package/dist/infra/outbound/payloads.js +14 -7
  399. package/dist/infra/outbound/session-binding-service.js +123 -0
  400. package/dist/infra/path-guards.js +25 -0
  401. package/dist/infra/provider-usage.fetch.codex.js +7 -15
  402. package/dist/infra/provider-usage.fetch.gemini.js +14 -11
  403. package/dist/infra/provider-usage.fetch.shared.js +30 -1
  404. package/dist/infra/provider-usage.fetch.zai.js +10 -9
  405. package/dist/infra/retry-policy.js +4 -2
  406. package/dist/infra/retry.js +9 -5
  407. package/dist/infra/session-cost-usage.js +107 -59
  408. package/dist/infra/session-maintenance-warning.js +3 -1
  409. package/dist/infra/shell-env.js +98 -34
  410. package/dist/infra/ssh-config.js +12 -6
  411. package/dist/infra/system-run-command.js +49 -4
  412. package/dist/infra/update-channels.js +10 -5
  413. package/dist/line/accounts.js +5 -7
  414. package/dist/line/bot-access.js +8 -20
  415. package/dist/line/bot-handlers.js +3 -1
  416. package/dist/link-understanding/detect.js +15 -7
  417. package/dist/media/constants.js +15 -6
  418. package/dist/media/image-ops.js +7 -0
  419. package/dist/media/local-roots.js +3 -2
  420. package/dist/media-understanding/apply.js +4 -1
  421. package/dist/media-understanding/concurrency.js +8 -20
  422. package/dist/memory/backend-config.js +45 -6
  423. package/dist/memory/embeddings.js +10 -4
  424. package/dist/memory/fs-utils.js +23 -0
  425. package/dist/memory/manager-search.js +12 -6
  426. package/dist/memory/manager-sync-ops.js +12 -2
  427. package/dist/memory/qmd-manager.js +466 -53
  428. package/dist/memory/query-expansion.js +167 -3
  429. package/dist/memory/status-format.js +10 -5
  430. package/dist/memory/sync-memory-files.js +1 -1
  431. package/dist/node-host/invoke-system-run.js +281 -0
  432. package/dist/node-host/invoke.js +55 -337
  433. package/dist/pairing/pairing-store.js +22 -0
  434. package/dist/plugin-sdk/allow-from.js +1 -1
  435. package/dist/plugin-sdk/command-auth.js +3 -1
  436. package/dist/plugin-sdk/index.js +6 -3
  437. package/dist/plugin-sdk/webhook-targets.js +32 -0
  438. package/dist/plugins/bundled-dir.js +9 -6
  439. package/dist/plugins/hooks.js +50 -0
  440. package/dist/plugins/install.js +28 -16
  441. package/dist/plugins/runtime.js +3 -17
  442. package/dist/plugins/update.js +78 -12
  443. package/dist/process/spawn-utils.js +14 -7
  444. package/dist/providers/github-copilot-token.js +11 -6
  445. package/dist/providers/qwen-portal-oauth.js +14 -6
  446. package/dist/routing/account-id.js +30 -0
  447. package/dist/routing/resolve-route.js +3 -7
  448. package/dist/routing/session-key.js +2 -16
  449. package/dist/security/audit-channel.js +93 -2
  450. package/dist/security/audit-extra.async.js +159 -5
  451. package/dist/security/audit-extra.js +1 -1
  452. package/dist/security/audit-extra.sync.js +85 -6
  453. package/dist/security/audit.js +40 -4
  454. package/dist/security/dm-policy-shared.js +44 -0
  455. package/dist/security/external-content.js +26 -6
  456. package/dist/shared/entry-status.js +6 -0
  457. package/dist/shared/frontmatter.js +5 -5
  458. package/dist/shared/node-match.js +11 -4
  459. package/dist/shared/operator-scope-compat.js +8 -3
  460. package/dist/signal/accounts.js +7 -20
  461. package/dist/signal/monitor/event-handler.js +3 -1
  462. package/dist/slack/accounts.js +6 -19
  463. package/dist/slack/actions.js +11 -3
  464. package/dist/slack/monitor/auth.js +1 -1
  465. package/dist/slack/monitor/message-handler/dispatch.js +50 -29
  466. package/dist/slack/monitor/replies.js +15 -7
  467. package/dist/slack/monitor/slash.js +22 -13
  468. package/dist/slack/resolve-channels.js +10 -5
  469. package/dist/slack/send.js +102 -12
  470. package/dist/slack/stream-mode.js +10 -0
  471. package/dist/slack/streaming.js +4 -2
  472. package/dist/telegram/accounts.js +19 -14
  473. package/dist/telegram/bot/helpers.js +3 -5
  474. package/dist/telegram/bot-access.js +35 -36
  475. package/dist/telegram/bot-handlers.js +120 -148
  476. package/dist/telegram/bot-message-context.js +68 -9
  477. package/dist/telegram/bot-message-dispatch.js +155 -90
  478. package/dist/telegram/bot-native-commands.js +16 -0
  479. package/dist/telegram/draft-stream.js +14 -1
  480. package/dist/telegram/inline-buttons.js +5 -15
  481. package/dist/telegram/monitor.js +11 -7
  482. package/dist/telegram/network-config.js +19 -7
  483. package/dist/telegram/send.js +3 -2
  484. package/dist/telegram/sent-message-cache.js +5 -6
  485. package/dist/telegram/status-reaction-variants.js +208 -0
  486. package/dist/telegram/sticker-cache.js +11 -9
  487. package/dist/terminal/theme.js +12 -12
  488. package/dist/tts/tts.js +80 -567
  489. package/dist/tui/components/chat-log.js +41 -8
  490. package/dist/tui/theme/theme.js +10 -12
  491. package/dist/tui/tui-local-shell.js +16 -6
  492. package/dist/tui/tui.js +58 -6
  493. package/dist/utils/account-id.js +2 -4
  494. package/dist/utils/boolean.js +10 -5
  495. package/dist/utils/directive-tags.js +11 -0
  496. package/dist/utils/queue-helpers.js +67 -12
  497. package/dist/web/auto-reply/deliver-reply.js +8 -4
  498. package/dist/web/auto-reply/mentions.js +10 -5
  499. package/dist/web/auto-reply/monitor/group-members.js +14 -7
  500. package/dist/web/auto-reply/monitor/process-message.js +45 -24
  501. package/dist/web/inbound/access-control.js +5 -2
  502. package/dist/web/login-qr.js +12 -6
  503. package/dist/web/media.js +123 -16
  504. package/extensions/bluebubbles/src/monitor-processing.ts +580 -139
  505. package/extensions/bluebubbles/src/monitor.ts +208 -1950
  506. package/package.json +1 -1
@@ -1,6 +1,8 @@
1
+ import { resolveAgentDir, resolveSessionAgentId } from "../../agents/agent-scope.js";
2
+ import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "../../agents/defaults.js";
3
+ import { resolveModelAuthLabel } from "../../agents/model-auth-label.js";
1
4
  import { loadModelCatalog } from "../../agents/model-catalog.js";
2
5
  import { buildAllowedModelSet, buildModelAliasIndex, normalizeProviderId, resolveConfiguredModelRef, resolveModelRefFromString, } from "../../agents/model-selection.js";
3
- import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "../../agents/defaults.js";
4
6
  import { buildModelsKeyboard, buildProviderKeyboard, calculateTotalPages, getModelsPageSize, } from "../../telegram/model-buttons.js";
5
7
  const PAGE_SIZE_DEFAULT = 20;
6
8
  const PAGE_SIZE_MAX = 100;
@@ -34,15 +36,17 @@ export async function buildModelsProviderData(cfg) {
34
36
  };
35
37
  const addRawModelRef = (raw) => {
36
38
  const trimmed = raw?.trim();
37
- if (!trimmed)
39
+ if (!trimmed) {
38
40
  return;
41
+ }
39
42
  const resolved = resolveModelRefFromString({
40
43
  raw: trimmed,
41
44
  defaultProvider: resolvedDefault.provider,
42
45
  aliasIndex,
43
46
  });
44
- if (!resolved)
47
+ if (!resolved) {
45
48
  return;
49
+ }
46
50
  add(resolved.ref.provider, resolved.ref.model);
47
51
  };
48
52
  const addModelConfigEntries = () => {
@@ -78,7 +82,7 @@ export async function buildModelsProviderData(cfg) {
78
82
  // curated catalog doesn't know about them (custom providers, dev builds, etc.).
79
83
  add(resolvedDefault.provider, resolvedDefault.model);
80
84
  addModelConfigEntries();
81
- const providers = [...byProvider.keys()].sort();
85
+ const providers = [...byProvider.keys()].toSorted();
82
86
  return { byProvider, providers, resolvedDefault };
83
87
  }
84
88
  function formatProviderLine(params) {
@@ -101,14 +105,16 @@ function parseModelsArgs(raw) {
101
105
  }
102
106
  if (lower.startsWith("page=")) {
103
107
  const value = Number.parseInt(lower.slice("page=".length), 10);
104
- if (Number.isFinite(value) && value > 0)
108
+ if (Number.isFinite(value) && value > 0) {
105
109
  page = value;
110
+ }
106
111
  continue;
107
112
  }
108
113
  if (/^[0-9]+$/.test(lower)) {
109
114
  const value = Number.parseInt(lower, 10);
110
- if (Number.isFinite(value) && value > 0)
115
+ if (Number.isFinite(value) && value > 0) {
111
116
  page = value;
117
+ }
112
118
  }
113
119
  }
114
120
  let pageSize = PAGE_SIZE_DEFAULT;
@@ -117,8 +123,9 @@ function parseModelsArgs(raw) {
117
123
  if (lower.startsWith("limit=") || lower.startsWith("size=")) {
118
124
  const rawValue = lower.slice(lower.indexOf("=") + 1);
119
125
  const value = Number.parseInt(rawValue, 10);
120
- if (Number.isFinite(value) && value > 0)
126
+ if (Number.isFinite(value) && value > 0) {
121
127
  pageSize = Math.min(PAGE_SIZE_MAX, value);
128
+ }
122
129
  }
123
130
  }
124
131
  return {
@@ -128,10 +135,32 @@ function parseModelsArgs(raw) {
128
135
  all,
129
136
  };
130
137
  }
138
+ function resolveProviderLabel(params) {
139
+ const authLabel = resolveModelAuthLabel({
140
+ provider: params.provider,
141
+ cfg: params.cfg,
142
+ sessionEntry: params.sessionEntry,
143
+ agentDir: params.agentDir,
144
+ });
145
+ if (!authLabel || authLabel === "unknown") {
146
+ return params.provider;
147
+ }
148
+ return `${params.provider} \u00b7 \uD83D\uDD11 ${authLabel}`;
149
+ }
150
+ export function formatModelsAvailableHeader(params) {
151
+ const providerLabel = resolveProviderLabel({
152
+ provider: params.provider,
153
+ cfg: params.cfg,
154
+ agentDir: params.agentDir,
155
+ sessionEntry: params.sessionEntry,
156
+ });
157
+ return `Models (${providerLabel}) \u2014 ${params.total} available`;
158
+ }
131
159
  export async function resolveModelsCommandReply(params) {
132
160
  const body = params.commandBodyNormalized.trim();
133
- if (!body.startsWith("/models"))
161
+ if (!body.startsWith("/models")) {
134
162
  return null;
163
+ }
135
164
  const argText = body.replace(/^\/models\b/i, "").trim();
136
165
  const { provider, page, pageSize, all } = parseModelsArgs(argText);
137
166
  const { byProvider, providers } = await buildModelsProviderData(params.cfg);
@@ -172,11 +201,17 @@ export async function resolveModelsCommandReply(params) {
172
201
  ];
173
202
  return { text: lines.join("\n") };
174
203
  }
175
- const models = [...(byProvider.get(provider) ?? new Set())].sort();
204
+ const models = [...(byProvider.get(provider) ?? new Set())].toSorted();
176
205
  const total = models.length;
206
+ const providerLabel = resolveProviderLabel({
207
+ provider,
208
+ cfg: params.cfg,
209
+ agentDir: params.agentDir,
210
+ sessionEntry: params.sessionEntry,
211
+ });
177
212
  if (total === 0) {
178
213
  const lines = [
179
- `Models (${provider}) none`,
214
+ `Models (${providerLabel}) \u2014 none`,
180
215
  "",
181
216
  "Browse: /models",
182
217
  "Switch: /model <provider/model>",
@@ -196,7 +231,13 @@ export async function resolveModelsCommandReply(params) {
196
231
  totalPages,
197
232
  pageSize: telegramPageSize,
198
233
  });
199
- const text = `Models (${provider}) — ${total} available`;
234
+ const text = formatModelsAvailableHeader({
235
+ provider,
236
+ total,
237
+ cfg: params.cfg,
238
+ agentDir: params.agentDir,
239
+ sessionEntry: params.sessionEntry,
240
+ });
200
241
  return {
201
242
  text,
202
243
  channelData: { telegram: { buttons } },
@@ -218,7 +259,7 @@ export async function resolveModelsCommandReply(params) {
218
259
  const startIndex = (safePage - 1) * effectivePageSize;
219
260
  const endIndexExclusive = Math.min(total, startIndex + effectivePageSize);
220
261
  const pageModels = models.slice(startIndex, endIndexExclusive);
221
- const header = `Models (${provider}) showing ${startIndex + 1}-${endIndexExclusive} of ${total} (page ${safePage}/${pageCount})`;
262
+ const header = `Models (${providerLabel}) \u2014 showing ${startIndex + 1}-${endIndexExclusive} of ${total} (page ${safePage}/${pageCount})`;
222
263
  const lines = [header];
223
264
  for (const id of pageModels) {
224
265
  lines.push(`- ${provider}/${id}`);
@@ -234,15 +275,25 @@ export async function resolveModelsCommandReply(params) {
234
275
  return payload;
235
276
  }
236
277
  export const handleModelsCommand = async (params, allowTextCommands) => {
237
- if (!allowTextCommands)
278
+ if (!allowTextCommands) {
238
279
  return null;
280
+ }
281
+ const modelsAgentId = params.agentId ??
282
+ resolveSessionAgentId({
283
+ sessionKey: params.sessionKey,
284
+ config: params.cfg,
285
+ });
286
+ const modelsAgentDir = resolveAgentDir(params.cfg, modelsAgentId);
239
287
  const reply = await resolveModelsCommandReply({
240
288
  cfg: params.cfg,
241
289
  commandBodyNormalized: params.command.commandBodyNormalized,
242
290
  surface: params.ctx.Surface,
243
291
  currentModel: params.model ? `${params.provider}/${params.model}` : undefined,
292
+ agentDir: modelsAgentDir,
293
+ sessionEntry: params.sessionEntry,
244
294
  });
245
- if (!reply)
295
+ if (!reply) {
246
296
  return null;
297
+ }
247
298
  return { reply, shouldContinue: false };
248
299
  };
@@ -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
  };
@@ -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
+ }