@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,28 +1,30 @@
1
- import { readConfigFileSnapshot, validateConfigObjectWithPlugins, writeConfigFile, } from "../../config/config.js";
2
- import { resolveChannelConfigWrites } from "../../channels/plugins/config-writes.js";
3
1
  import { getChannelDock } from "../../channels/dock.js";
4
- import { normalizeChannelId } from "../../channels/registry.js";
2
+ import { resolveChannelConfigWrites } from "../../channels/plugins/config-writes.js";
5
3
  import { listPairingChannels } from "../../channels/plugins/pairing.js";
6
- import { logVerbose } from "../../globals.js";
7
- import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../routing/session-key.js";
4
+ import { normalizeChannelId } from "../../channels/registry.js";
5
+ import { readConfigFileSnapshot, validateConfigObjectWithPlugins, writeConfigFile, } from "../../config/config.js";
8
6
  import { resolveDiscordAccount } from "../../discord/accounts.js";
7
+ import { resolveDiscordUserAllowlist } from "../../discord/resolve-users.js";
9
8
  import { resolveIMessageAccount } from "../../imessage/accounts.js";
9
+ import { addChannelAllowFromStoreEntry, readChannelAllowFromStore, removeChannelAllowFromStoreEntry, } from "../../pairing/pairing-store.js";
10
+ import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../routing/session-key.js";
10
11
  import { resolveSignalAccount } from "../../signal/accounts.js";
11
12
  import { resolveSlackAccount } from "../../slack/accounts.js";
13
+ import { resolveSlackUserAllowlist } from "../../slack/resolve-users.js";
12
14
  import { resolveTelegramAccount } from "../../telegram/accounts.js";
13
15
  import { resolveWhatsAppAccount } from "../../web/accounts.js";
14
- import { resolveSlackUserAllowlist } from "../../slack/resolve-users.js";
15
- import { resolveDiscordUserAllowlist } from "../../discord/resolve-users.js";
16
- import { addChannelAllowFromStoreEntry, readChannelAllowFromStore, removeChannelAllowFromStoreEntry, } from "../../pairing/pairing-store.js";
16
+ import { rejectUnauthorizedCommand, requireCommandFlagEnabled } from "./command-gates.js";
17
17
  const ACTIONS = new Set(["list", "add", "remove"]);
18
18
  const SCOPES = new Set(["dm", "group", "all"]);
19
19
  function parseAllowlistCommand(raw) {
20
20
  const trimmed = raw.trim();
21
- if (!trimmed.toLowerCase().startsWith("/allowlist"))
21
+ if (!trimmed.toLowerCase().startsWith("/allowlist")) {
22
22
  return null;
23
+ }
23
24
  const rest = trimmed.slice("/allowlist".length).trim();
24
- if (!rest)
25
+ if (!rest) {
25
26
  return { action: "list", scope: "dm" };
27
+ }
26
28
  const tokens = rest.split(/\s+/);
27
29
  let action = "list";
28
30
  let scope = "dm";
@@ -70,13 +72,15 @@ function parseAllowlistCommand(raw) {
70
72
  const key = kv[0]?.trim().toLowerCase();
71
73
  const value = kv[1]?.trim();
72
74
  if (key === "channel") {
73
- if (value)
75
+ if (value) {
74
76
  channel = value;
77
+ }
75
78
  continue;
76
79
  }
77
80
  if (key === "account") {
78
- if (value)
81
+ if (value) {
79
82
  account = value;
83
+ }
80
84
  continue;
81
85
  }
82
86
  if (key === "scope" && value && SCOPES.has(value.toLowerCase())) {
@@ -107,8 +111,9 @@ function normalizeAllowFrom(params) {
107
111
  return params.values.map((entry) => String(entry).trim()).filter(Boolean);
108
112
  }
109
113
  function formatEntryList(entries, resolved) {
110
- if (entries.length === 0)
114
+ if (entries.length === 0) {
111
115
  return "(none)";
116
+ }
112
117
  return entries
113
118
  .map((entry) => {
114
119
  const name = resolved?.get(entry);
@@ -136,8 +141,9 @@ function resolveAccountTarget(parsed, channelId, accountId) {
136
141
  function getNestedValue(root, path) {
137
142
  let current = root;
138
143
  for (const key of path) {
139
- if (!current || typeof current !== "object")
144
+ if (!current || typeof current !== "object") {
140
145
  return undefined;
146
+ }
141
147
  current = current[key];
142
148
  }
143
149
  return current;
@@ -154,8 +160,9 @@ function ensureNestedObject(root, path) {
154
160
  return current;
155
161
  }
156
162
  function setNestedValue(root, path, value) {
157
- if (path.length === 0)
163
+ if (path.length === 0) {
158
164
  return;
165
+ }
159
166
  if (path.length === 1) {
160
167
  root[path[0]] = value;
161
168
  return;
@@ -164,80 +171,86 @@ function setNestedValue(root, path, value) {
164
171
  parent[path[path.length - 1]] = value;
165
172
  }
166
173
  function deleteNestedValue(root, path) {
167
- if (path.length === 0)
174
+ if (path.length === 0) {
168
175
  return;
176
+ }
169
177
  if (path.length === 1) {
170
178
  delete root[path[0]];
171
179
  return;
172
180
  }
173
181
  const parent = getNestedValue(root, path.slice(0, -1));
174
- if (!parent || typeof parent !== "object")
182
+ if (!parent || typeof parent !== "object") {
175
183
  return;
184
+ }
176
185
  delete parent[path[path.length - 1]];
177
186
  }
178
187
  function resolveChannelAllowFromPaths(channelId, scope) {
179
- if (scope === "all")
188
+ const supportsGroupAllowlist = channelId === "telegram" ||
189
+ channelId === "whatsapp" ||
190
+ channelId === "signal" ||
191
+ channelId === "imessage";
192
+ if (scope === "all") {
180
193
  return null;
194
+ }
181
195
  if (scope === "dm") {
182
- if (channelId === "slack" || channelId === "discord")
183
- return ["dm", "allowFrom"];
184
- if (channelId === "telegram" ||
185
- channelId === "whatsapp" ||
186
- channelId === "signal" ||
187
- channelId === "imessage") {
196
+ if (channelId === "slack" || channelId === "discord") {
197
+ // Canonical DM allowlist location for Slack/Discord. Legacy: dm.allowFrom.
198
+ return ["allowFrom"];
199
+ }
200
+ if (supportsGroupAllowlist) {
188
201
  return ["allowFrom"];
189
202
  }
190
203
  return null;
191
204
  }
192
205
  if (scope === "group") {
193
- if (channelId === "telegram" ||
194
- channelId === "whatsapp" ||
195
- channelId === "signal" ||
196
- channelId === "imessage") {
206
+ if (supportsGroupAllowlist) {
197
207
  return ["groupAllowFrom"];
198
208
  }
199
209
  return null;
200
210
  }
201
211
  return null;
202
212
  }
213
+ function mapResolvedAllowlistNames(entries) {
214
+ const map = new Map();
215
+ for (const entry of entries) {
216
+ if (entry.resolved && entry.name) {
217
+ map.set(entry.input, entry.name);
218
+ }
219
+ }
220
+ return map;
221
+ }
203
222
  async function resolveSlackNames(params) {
204
223
  const account = resolveSlackAccount({ cfg: params.cfg, accountId: params.accountId });
205
224
  const token = account.config.userToken?.trim() || account.botToken?.trim();
206
- if (!token)
225
+ if (!token) {
207
226
  return new Map();
208
- const resolved = await resolveSlackUserAllowlist({ token, entries: params.entries });
209
- const map = new Map();
210
- for (const entry of resolved) {
211
- if (entry.resolved && entry.name)
212
- map.set(entry.input, entry.name);
213
227
  }
214
- return map;
228
+ const resolved = await resolveSlackUserAllowlist({ token, entries: params.entries });
229
+ return mapResolvedAllowlistNames(resolved);
215
230
  }
216
231
  async function resolveDiscordNames(params) {
217
232
  const account = resolveDiscordAccount({ cfg: params.cfg, accountId: params.accountId });
218
233
  const token = account.token?.trim();
219
- if (!token)
234
+ if (!token) {
220
235
  return new Map();
221
- const resolved = await resolveDiscordUserAllowlist({ token, entries: params.entries });
222
- const map = new Map();
223
- for (const entry of resolved) {
224
- if (entry.resolved && entry.name)
225
- map.set(entry.input, entry.name);
226
236
  }
227
- return map;
237
+ const resolved = await resolveDiscordUserAllowlist({ token, entries: params.entries });
238
+ return mapResolvedAllowlistNames(resolved);
228
239
  }
229
240
  export const handleAllowlistCommand = async (params, allowTextCommands) => {
230
- if (!allowTextCommands)
241
+ if (!allowTextCommands) {
231
242
  return null;
243
+ }
232
244
  const parsed = parseAllowlistCommand(params.command.commandBodyNormalized);
233
- if (!parsed)
245
+ if (!parsed) {
234
246
  return null;
247
+ }
235
248
  if (parsed.action === "error") {
236
- return { shouldContinue: false, reply: { text: `⚠️ ${parsed.message}` } };
249
+ return { shouldContinue: false, reply: { text: `\u26a0\ufe0f ${parsed.message}` } };
237
250
  }
238
- if (!params.command.isAuthorizedSender) {
239
- logVerbose(`Ignoring /allowlist from unauthorized sender: ${params.command.senderId || "<unknown>"}`);
240
- return { shouldContinue: false };
251
+ const unauthorized = rejectUnauthorizedCommand(params, "/allowlist");
252
+ if (unauthorized) {
253
+ return unauthorized;
241
254
  }
242
255
  const channelId = normalizeChannelId(parsed.channel) ??
243
256
  params.command.channelId ??
@@ -245,7 +258,7 @@ export const handleAllowlistCommand = async (params, allowTextCommands) => {
245
258
  if (!channelId) {
246
259
  return {
247
260
  shouldContinue: false,
248
- reply: { text: "⚠️ Unknown channel. Add channel=<id> to the command." },
261
+ reply: { text: "\u26a0\ufe0f Unknown channel. Add channel=<id> to the command." },
249
262
  };
250
263
  }
251
264
  const accountId = normalizeAccountId(parsed.account ?? params.ctx.AccountId);
@@ -305,7 +318,7 @@ export const handleAllowlistCommand = async (params, allowTextCommands) => {
305
318
  }
306
319
  else if (channelId === "slack") {
307
320
  const account = resolveSlackAccount({ cfg: params.cfg, accountId });
308
- dmAllowFrom = (account.dm?.allowFrom ?? []).map(String);
321
+ dmAllowFrom = (account.config.allowFrom ?? account.config.dm?.allowFrom ?? []).map(String);
309
322
  groupPolicy = account.groupPolicy;
310
323
  const channels = account.channels ?? {};
311
324
  groupOverrides = Object.entries(channels)
@@ -317,7 +330,7 @@ export const handleAllowlistCommand = async (params, allowTextCommands) => {
317
330
  }
318
331
  else if (channelId === "discord") {
319
332
  const account = resolveDiscordAccount({ cfg: params.cfg, accountId });
320
- dmAllowFrom = (account.config.dm?.allowFrom ?? []).map(String);
333
+ dmAllowFrom = (account.config.allowFrom ?? account.config.dm?.allowFrom ?? []).map(String);
321
334
  groupPolicy = account.config.groupPolicy;
322
335
  const guilds = account.config.guilds ?? {};
323
336
  for (const [guildKey, guildCfg] of Object.entries(guilds)) {
@@ -374,12 +387,14 @@ export const handleAllowlistCommand = async (params, allowTextCommands) => {
374
387
  entries: groupOverrideDisplay,
375
388
  })
376
389
  : undefined;
377
- const lines = ["🧾 Allowlist"];
390
+ const lines = ["\ud83e\uddf6 Allowlist"];
378
391
  lines.push(`Channel: ${channelId}${accountId ? ` (account ${accountId})` : ""}`);
379
- if (dmPolicy)
392
+ if (dmPolicy) {
380
393
  lines.push(`DM policy: ${dmPolicy}`);
381
- if (groupPolicy)
394
+ }
395
+ if (groupPolicy) {
382
396
  lines.push(`Group policy: ${groupPolicy}`);
397
+ }
383
398
  const showDm = scope === "dm" || scope === "all";
384
399
  const showGroup = scope === "group" || scope === "all";
385
400
  if (showDm) {
@@ -413,11 +428,13 @@ export const handleAllowlistCommand = async (params, allowTextCommands) => {
413
428
  }
414
429
  return { shouldContinue: false, reply: { text: lines.join("\n") } };
415
430
  }
416
- if (params.cfg.commands?.config !== true) {
417
- return {
418
- shouldContinue: false,
419
- reply: { text: "⚠️ /allowlist edits are disabled. Set commands.config=true to enable." },
420
- };
431
+ const disabled = requireCommandFlagEnabled(params.cfg, {
432
+ label: "/allowlist edits",
433
+ configKey: "config",
434
+ disabledVerb: "are",
435
+ });
436
+ if (disabled) {
437
+ return disabled;
421
438
  }
422
439
  const shouldUpdateConfig = parsed.target !== "store";
423
440
  const shouldTouchStore = parsed.target !== "config" && listPairingChannels().includes(channelId);
@@ -431,7 +448,9 @@ export const handleAllowlistCommand = async (params, allowTextCommands) => {
431
448
  const hint = `channels.${channelId}.configWrites=true`;
432
449
  return {
433
450
  shouldContinue: false,
434
- reply: { text: `⚠️ Config writes are disabled for ${channelId}. Set ${hint} to enable.` },
451
+ reply: {
452
+ text: `\u26a0\ufe0f Config writes are disabled for ${channelId}. Set ${hint} to enable.`,
453
+ },
435
454
  };
436
455
  }
437
456
  const allowlistPath = resolveChannelAllowFromPaths(channelId, scope);
@@ -439,7 +458,7 @@ export const handleAllowlistCommand = async (params, allowTextCommands) => {
439
458
  return {
440
459
  shouldContinue: false,
441
460
  reply: {
442
- text: `⚠️ ${channelId} does not support ${scope} allowlist edits via /allowlist.`,
461
+ text: `\u26a0\ufe0f ${channelId} does not support ${scope} allowlist edits via /allowlist.`,
443
462
  },
444
463
  };
445
464
  }
@@ -447,15 +466,29 @@ export const handleAllowlistCommand = async (params, allowTextCommands) => {
447
466
  if (!snapshot.valid || !snapshot.parsed || typeof snapshot.parsed !== "object") {
448
467
  return {
449
468
  shouldContinue: false,
450
- reply: { text: "⚠️ Config file is invalid; fix it before using /allowlist." },
469
+ reply: { text: "\u26a0\ufe0f Config file is invalid; fix it before using /allowlist." },
451
470
  };
452
471
  }
453
472
  const parsedConfig = structuredClone(snapshot.parsed);
454
473
  const { target, pathPrefix, accountId: normalizedAccountId, } = resolveAccountTarget(parsedConfig, channelId, accountId);
455
- const existingRaw = getNestedValue(target, allowlistPath);
456
- const existing = Array.isArray(existingRaw)
457
- ? existingRaw.map((entry) => String(entry).trim()).filter(Boolean)
458
- : [];
474
+ const existing = [];
475
+ const existingPaths = scope === "dm" && (channelId === "slack" || channelId === "discord")
476
+ ? // Read both while legacy alias may still exist; write canonical below.
477
+ [allowlistPath, ["dm", "allowFrom"]]
478
+ : [allowlistPath];
479
+ for (const path of existingPaths) {
480
+ const existingRaw = getNestedValue(target, path);
481
+ if (!Array.isArray(existingRaw)) {
482
+ continue;
483
+ }
484
+ for (const entry of existingRaw) {
485
+ const value = String(entry).trim();
486
+ if (!value || existing.includes(value)) {
487
+ continue;
488
+ }
489
+ existing.push(value);
490
+ }
491
+ }
459
492
  const normalizedEntry = normalizeAllowFrom({
460
493
  cfg: params.cfg,
461
494
  channelId,
@@ -465,7 +498,7 @@ export const handleAllowlistCommand = async (params, allowTextCommands) => {
465
498
  if (normalizedEntry.length === 0) {
466
499
  return {
467
500
  shouldContinue: false,
468
- reply: { text: "⚠️ Invalid allowlist entry." },
501
+ reply: { text: "\u26a0\ufe0f Invalid allowlist entry." },
469
502
  };
470
503
  }
471
504
  const existingNormalized = normalizeAllowFrom({
@@ -508,6 +541,10 @@ export const handleAllowlistCommand = async (params, allowTextCommands) => {
508
541
  else {
509
542
  setNestedValue(target, allowlistPath, next);
510
543
  }
544
+ if (scope === "dm" && (channelId === "slack" || channelId === "discord")) {
545
+ // Remove legacy DM allowlist alias to prevent drift.
546
+ deleteNestedValue(target, ["dm", "allowFrom"]);
547
+ }
511
548
  }
512
549
  if (configChanged) {
513
550
  const validated = validateConfigObjectWithPlugins(parsedConfig);
@@ -515,13 +552,15 @@ export const handleAllowlistCommand = async (params, allowTextCommands) => {
515
552
  const issue = validated.issues[0];
516
553
  return {
517
554
  shouldContinue: false,
518
- reply: { text: `⚠️ Config invalid after update (${issue.path}: ${issue.message}).` },
555
+ reply: {
556
+ text: `\u26a0\ufe0f Config invalid after update (${issue.path}: ${issue.message}).`,
557
+ },
519
558
  };
520
559
  }
521
560
  await writeConfigFile(validated.config);
522
561
  }
523
562
  if (!configChanged && !shouldTouchStore) {
524
- const message = parsed.action === "add" ? " Already allowlisted." : "⚠️ Entry not found.";
563
+ const message = parsed.action === "add" ? "\u2705 Already allowlisted." : "\u26a0\ufe0f Entry not found.";
525
564
  return { shouldContinue: false, reply: { text: message } };
526
565
  }
527
566
  if (shouldTouchStore) {
@@ -545,14 +584,14 @@ export const handleAllowlistCommand = async (params, allowTextCommands) => {
545
584
  return {
546
585
  shouldContinue: false,
547
586
  reply: {
548
- text: `✅ ${scopeLabel} allowlist ${actionLabel}: ${targetLabel}.`,
587
+ text: `\u2705 ${scopeLabel} allowlist ${actionLabel}: ${targetLabel}.`,
549
588
  },
550
589
  };
551
590
  }
552
591
  if (!shouldTouchStore) {
553
592
  return {
554
593
  shouldContinue: false,
555
- reply: { text: "⚠️ This channel does not support allowlist storage." },
594
+ reply: { text: "\u26a0\ufe0f This channel does not support allowlist storage." },
556
595
  };
557
596
  }
558
597
  if (parsed.action === "add") {
@@ -565,6 +604,6 @@ export const handleAllowlistCommand = async (params, allowTextCommands) => {
565
604
  const scopeLabel = scope === "dm" ? "DM" : "group";
566
605
  return {
567
606
  shouldContinue: false,
568
- reply: { text: `✅ ${scopeLabel} allowlist ${actionLabel} in pairing store.` },
607
+ reply: { text: `\u2705 ${scopeLabel} allowlist ${actionLabel} in pairing store.` },
569
608
  };
570
609
  };
@@ -1,17 +1,18 @@
1
- import { logVerbose } from "../../globals.js";
2
1
  import { handleBashChatCommand } from "./bash-command.js";
2
+ import { rejectUnauthorizedCommand } from "./command-gates.js";
3
3
  export const handleBashCommand = async (params, allowTextCommands) => {
4
- if (!allowTextCommands)
4
+ if (!allowTextCommands) {
5
5
  return null;
6
+ }
6
7
  const { command } = params;
7
8
  const bashSlashRequested = command.commandBodyNormalized === "/bash" || command.commandBodyNormalized.startsWith("/bash ");
8
9
  const bashBangRequested = command.commandBodyNormalized.startsWith("!");
9
10
  if (!bashSlashRequested && !(bashBangRequested && command.isAuthorizedSender)) {
10
11
  return null;
11
12
  }
12
- if (!command.isAuthorizedSender) {
13
- logVerbose(`Ignoring /bash from unauthorized sender: ${command.senderId || "<unknown>"}`);
14
- return { shouldContinue: false };
13
+ const unauthorized = rejectUnauthorizedCommand(params, "/bash");
14
+ if (unauthorized) {
15
+ return unauthorized;
15
16
  }
16
17
  const reply = await handleBashChatCommand({
17
18
  ctx: params.ctx,
@@ -1,28 +1,29 @@
1
- import { readConfigFileSnapshot, validateConfigObjectWithPlugins, writeConfigFile, } from "../../config/config.js";
2
- import { getConfigValueAtPath, parseConfigPath, setConfigValueAtPath, unsetConfigValueAtPath, } from "../../config/config-paths.js";
3
- import { getConfigOverrides, resetConfigOverrides, setConfigOverride, unsetConfigOverride, } from "../../config/runtime-overrides.js";
4
1
  import { resolveChannelConfigWrites } from "../../channels/plugins/config-writes.js";
5
2
  import { normalizeChannelId } from "../../channels/registry.js";
6
- import { logVerbose } from "../../globals.js";
3
+ import { getConfigValueAtPath, parseConfigPath, setConfigValueAtPath, unsetConfigValueAtPath, } from "../../config/config-paths.js";
4
+ import { readConfigFileSnapshot, validateConfigObjectWithPlugins, writeConfigFile, } from "../../config/config.js";
5
+ import { getConfigOverrides, resetConfigOverrides, setConfigOverride, unsetConfigOverride, } from "../../config/runtime-overrides.js";
6
+ import { rejectUnauthorizedCommand, requireCommandFlagEnabled } from "./command-gates.js";
7
7
  import { parseConfigCommand } from "./config-commands.js";
8
8
  import { parseDebugCommand } from "./debug-commands.js";
9
9
  export const handleConfigCommand = async (params, allowTextCommands) => {
10
- if (!allowTextCommands)
10
+ if (!allowTextCommands) {
11
11
  return null;
12
+ }
12
13
  const configCommand = parseConfigCommand(params.command.commandBodyNormalized);
13
- if (!configCommand)
14
+ if (!configCommand) {
14
15
  return null;
15
- if (!params.command.isAuthorizedSender) {
16
- logVerbose(`Ignoring /config from unauthorized sender: ${params.command.senderId || "<unknown>"}`);
17
- return { shouldContinue: false };
18
16
  }
19
- if (params.cfg.commands?.config !== true) {
20
- return {
21
- shouldContinue: false,
22
- reply: {
23
- text: "⚠️ /config is disabled. Set commands.config=true to enable.",
24
- },
25
- };
17
+ const unauthorized = rejectUnauthorizedCommand(params, "/config");
18
+ if (unauthorized) {
19
+ return unauthorized;
20
+ }
21
+ const disabled = requireCommandFlagEnabled(params.cfg, {
22
+ label: "/config",
23
+ configKey: "config",
24
+ });
25
+ if (disabled) {
26
+ return disabled;
26
27
  }
27
28
  if (configCommand.action === "error") {
28
29
  return {
@@ -149,22 +150,23 @@ export const handleConfigCommand = async (params, allowTextCommands) => {
149
150
  return null;
150
151
  };
151
152
  export const handleDebugCommand = async (params, allowTextCommands) => {
152
- if (!allowTextCommands)
153
+ if (!allowTextCommands) {
153
154
  return null;
155
+ }
154
156
  const debugCommand = parseDebugCommand(params.command.commandBodyNormalized);
155
- if (!debugCommand)
157
+ if (!debugCommand) {
156
158
  return null;
157
- if (!params.command.isAuthorizedSender) {
158
- logVerbose(`Ignoring /debug from unauthorized sender: ${params.command.senderId || "<unknown>"}`);
159
- return { shouldContinue: false };
160
159
  }
161
- if (params.cfg.commands?.debug !== true) {
162
- return {
163
- shouldContinue: false,
164
- reply: {
165
- text: "⚠️ /debug is disabled. Set commands.debug=true to enable.",
166
- },
167
- };
160
+ const unauthorized = rejectUnauthorizedCommand(params, "/debug");
161
+ if (unauthorized) {
162
+ return unauthorized;
163
+ }
164
+ const disabled = requireCommandFlagEnabled(params.cfg, {
165
+ label: "/debug",
166
+ configKey: "debug",
167
+ });
168
+ if (disabled) {
169
+ return disabled;
168
170
  }
169
171
  if (debugCommand.action === "error") {
170
172
  return {
@@ -12,7 +12,7 @@ import { handleConfigCommand, handleDebugCommand } from "./commands-config.js";
12
12
  import { handleCommandsListCommand, handleContextCommand, handleExportSessionCommand, handleHelpCommand, handleStatusCommand, handleWhoamiCommand, } from "./commands-info.js";
13
13
  import { handleModelsCommand } from "./commands-models.js";
14
14
  import { handlePluginCommand } from "./commands-plugin.js";
15
- import { handleAbortTrigger, handleActivationCommand, handleRestartCommand, handleSendPolicyCommand, handleStopCommand, handleUsageCommand, } from "./commands-session.js";
15
+ import { handleAbortTrigger, handleActivationCommand, handleRestartCommand, handleSessionCommand, handleSendPolicyCommand, handleStopCommand, handleUsageCommand, } from "./commands-session.js";
16
16
  import { handleSubagentsCommand } from "./commands-subagents.js";
17
17
  import { handleTtsCommands } from "./commands-tts.js";
18
18
  import { routeReply } from "./route-reply.js";
@@ -26,6 +26,7 @@ export async function handleCommands(params) {
26
26
  handleActivationCommand,
27
27
  handleSendPolicyCommand,
28
28
  handleUsageCommand,
29
+ handleSessionCommand,
29
30
  handleRestartCommand,
30
31
  handleTtsCommands,
31
32
  handleHelpCommand,
@@ -103,6 +103,7 @@ export const handleStatusCommand = async (params, allowTextCommands) => {
103
103
  command: params.command,
104
104
  sessionEntry: params.sessionEntry,
105
105
  sessionKey: params.sessionKey,
106
+ parentSessionKey: params.ctx.ParentSessionKey,
106
107
  sessionScope: params.sessionScope,
107
108
  provider: params.provider,
108
109
  model: params.model,