@poolzin/pool-bot 2026.2.24 → 2026.2.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (646) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/acp/client.js +207 -18
  3. package/dist/acp/event-mapper.js +87 -22
  4. package/dist/acp/meta.js +12 -6
  5. package/dist/acp/secret-file.js +22 -0
  6. package/dist/agents/agent-paths.js +8 -9
  7. package/dist/agents/agent-scope.js +17 -5
  8. package/dist/agents/auth-profiles/oauth.js +148 -64
  9. package/dist/agents/auth-profiles/session-override.js +13 -7
  10. package/dist/agents/bash-process-registry.test-helpers.js +29 -0
  11. package/dist/agents/bash-tools.exec-approval-request.js +20 -0
  12. package/dist/agents/bash-tools.exec-host-gateway.js +240 -0
  13. package/dist/agents/bash-tools.exec-host-node.js +235 -0
  14. package/dist/agents/bash-tools.exec-runtime.js +2 -25
  15. package/dist/agents/bash-tools.exec-types.js +1 -0
  16. package/dist/agents/bash-tools.process.js +224 -218
  17. package/dist/agents/bedrock-discovery.js +3 -1
  18. package/dist/agents/byteplus-models.js +97 -0
  19. package/dist/agents/chutes-oauth.js +1 -0
  20. package/dist/agents/cli-runner/helpers.js +4 -0
  21. package/dist/agents/compaction.js +41 -14
  22. package/dist/agents/content-blocks.js +16 -0
  23. package/dist/agents/doubao-models.js +121 -0
  24. package/dist/agents/failover-error.js +2 -0
  25. package/dist/agents/huggingface-models.js +5 -3
  26. package/dist/agents/live-model-filter.js +5 -0
  27. package/dist/agents/minimax-vlm.js +10 -8
  28. package/dist/agents/model-auth.js +6 -0
  29. package/dist/agents/model-catalog.js +3 -1
  30. package/dist/agents/model-fallback.js +96 -101
  31. package/dist/agents/model-selection.js +7 -1
  32. package/dist/agents/models-config.providers.js +364 -165
  33. package/dist/agents/ollama-stream.js +117 -4
  34. package/dist/agents/opencode-zen-models.js +22 -11
  35. package/dist/agents/pi-embedded-helpers/errors.js +55 -33
  36. package/dist/agents/pi-embedded-helpers/messaging-dedupe.js +10 -5
  37. package/dist/agents/pi-embedded-helpers/thinking.js +10 -5
  38. package/dist/agents/pi-embedded-helpers.js +1 -1
  39. package/dist/agents/pi-embedded-payloads.js +1 -0
  40. package/dist/agents/pi-embedded-runner/compact.js +29 -7
  41. package/dist/agents/pi-embedded-runner/extensions.js +28 -26
  42. package/dist/agents/pi-embedded-runner/google.js +20 -8
  43. package/dist/agents/pi-embedded-runner/run/attempt.js +95 -36
  44. package/dist/agents/pi-embedded-runner/run.js +71 -12
  45. package/dist/agents/pi-embedded-runner/run.overflow-compaction.fixture.js +34 -0
  46. package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +11 -2
  47. package/dist/agents/pi-embedded-runner/session-manager-cache.js +11 -7
  48. package/dist/agents/pi-embedded-runner/system-prompt.js +2 -0
  49. package/dist/agents/pi-embedded-runner/thinking.js +42 -0
  50. package/dist/agents/pi-embedded-runner/tool-name-allowlist.js +19 -0
  51. package/dist/agents/pi-embedded-runner/utils.js +7 -10
  52. package/dist/agents/pi-embedded-subscribe.handlers.lifecycle.js +45 -56
  53. package/dist/agents/pi-embedded-subscribe.handlers.tools.js +2 -2
  54. package/dist/agents/pi-embedded-subscribe.js +9 -4
  55. package/dist/agents/pi-embedded-subscribe.tools.js +68 -14
  56. package/dist/agents/pi-embedded-utils.js +3 -0
  57. package/dist/agents/pi-extensions/compaction-safeguard-runtime.js +4 -20
  58. package/dist/agents/pi-extensions/compaction-safeguard.js +75 -33
  59. package/dist/agents/pi-settings.js +40 -0
  60. package/dist/agents/pi-tools.policy.js +2 -1
  61. package/dist/agents/provider/config-loader.js +1 -1
  62. package/dist/agents/sandbox/browser.js +170 -33
  63. package/dist/agents/sandbox/config-hash.js +14 -27
  64. package/dist/agents/sandbox/config.js +21 -2
  65. package/dist/agents/sandbox/constants.js +2 -0
  66. package/dist/agents/sandbox/docker.js +16 -2
  67. package/dist/agents/sandbox/novnc-auth.js +62 -0
  68. package/dist/agents/sandbox/sanitize-env-vars.js +1 -1
  69. package/dist/agents/sandbox/shared.js +10 -6
  70. package/dist/agents/sandbox-paths.js +24 -11
  71. package/dist/agents/schema/clean-for-gemini.js +132 -85
  72. package/dist/agents/session-slug.js +10 -5
  73. package/dist/agents/session-tool-result-guard-wrapper.js +1 -0
  74. package/dist/agents/session-tool-result-guard.js +3 -1
  75. package/dist/agents/session-transcript-repair.js +40 -6
  76. package/dist/agents/skills/bundled-dir.js +19 -5
  77. package/dist/agents/skills/env-overrides.js +124 -43
  78. package/dist/agents/skills/frontmatter.js +6 -6
  79. package/dist/agents/skills/plugin-skills.js +14 -7
  80. package/dist/agents/skills/workspace.js +1 -0
  81. package/dist/agents/skills.test-helpers.js +13 -0
  82. package/dist/agents/stable-stringify.js +12 -0
  83. package/dist/agents/subagent-announce.js +251 -49
  84. package/dist/agents/subagent-lifecycle-events.js +19 -0
  85. package/dist/agents/subagent-registry-cleanup.js +31 -0
  86. package/dist/agents/subagent-registry-completion.js +68 -0
  87. package/dist/agents/subagent-registry-queries.js +117 -0
  88. package/dist/agents/subagent-registry-state.js +46 -0
  89. package/dist/agents/subagent-registry.js +252 -221
  90. package/dist/agents/subagent-registry.mocks.shared.js +12 -0
  91. package/dist/agents/subagent-registry.store.js +1 -0
  92. package/dist/agents/subagent-registry.types.js +1 -0
  93. package/dist/agents/subagent-spawn.js +195 -7
  94. package/dist/agents/system-prompt.js +22 -6
  95. package/dist/agents/test-helpers/assistant-message-fixtures.js +29 -0
  96. package/dist/agents/test-helpers/fast-coding-tools.js +1 -18
  97. package/dist/agents/test-helpers/fast-core-tools.js +1 -17
  98. package/dist/agents/test-helpers/pi-tools-sandbox-context.js +27 -0
  99. package/dist/agents/timeout.js +18 -6
  100. package/dist/agents/tool-call-id.js +1 -1
  101. package/dist/agents/tool-display-common.js +162 -29
  102. package/dist/agents/tool-images.js +82 -9
  103. package/dist/agents/tool-policy-shared.js +108 -0
  104. package/dist/agents/tool-policy.js +51 -26
  105. package/dist/agents/tools/browser-tool.js +160 -54
  106. package/dist/agents/tools/canvas-tool.js +27 -1
  107. package/dist/agents/tools/common.js +45 -0
  108. package/dist/agents/tools/cron-tool.test-helpers.js +12 -0
  109. package/dist/agents/tools/discord-actions-guild.js +4 -1
  110. package/dist/agents/tools/discord-actions-moderation-shared.js +27 -0
  111. package/dist/agents/tools/gateway-tool.js +3 -1
  112. package/dist/agents/tools/image-tool.js +214 -99
  113. package/dist/agents/tools/nodes-utils.js +1 -10
  114. package/dist/agents/tools/sessions-history-tool.js +140 -108
  115. package/dist/agents/tools/sessions-send-helpers.js +12 -6
  116. package/dist/agents/tools/sessions-spawn-tool.js +8 -2
  117. package/dist/agents/tools/subagents-tool.js +2 -1
  118. package/dist/agents/tools/whatsapp-actions.js +10 -2
  119. package/dist/agents/tools/whatsapp-target-auth.js +18 -0
  120. package/dist/agents/transcript-policy.js +22 -8
  121. package/dist/agents/venice-models.js +11 -3
  122. package/dist/agents/workspace.js +222 -46
  123. package/dist/auto-reply/commands-registry.data.js +51 -0
  124. package/dist/auto-reply/commands-registry.js +19 -21
  125. package/dist/auto-reply/fallback-state.js +114 -0
  126. package/dist/auto-reply/group-activation.js +10 -5
  127. package/dist/auto-reply/inbound-debounce.js +10 -5
  128. package/dist/auto-reply/model-runtime.js +68 -0
  129. package/dist/auto-reply/reply/abort.js +1 -1
  130. package/dist/auto-reply/reply/agent-runner-execution.js +40 -5
  131. package/dist/auto-reply/reply/agent-runner.js +165 -39
  132. package/dist/auto-reply/reply/bash-command.js +41 -39
  133. package/dist/auto-reply/reply/command-gates.js +25 -0
  134. package/dist/auto-reply/reply/commands-allowlist.js +111 -72
  135. package/dist/auto-reply/reply/commands-bash.js +6 -5
  136. package/dist/auto-reply/reply/commands-config.js +30 -28
  137. package/dist/auto-reply/reply/commands-core.js +2 -1
  138. package/dist/auto-reply/reply/commands-info.js +1 -0
  139. package/dist/auto-reply/reply/commands-models.js +65 -14
  140. package/dist/auto-reply/reply/commands-session.js +237 -82
  141. package/dist/auto-reply/reply/commands-setunset-standard.js +13 -0
  142. package/dist/auto-reply/reply/commands-setunset.js +45 -0
  143. package/dist/auto-reply/reply/commands-subagents/action-agents.js +44 -0
  144. package/dist/auto-reply/reply/commands-subagents/action-focus.js +64 -0
  145. package/dist/auto-reply/reply/commands-subagents/action-help.js +4 -0
  146. package/dist/auto-reply/reply/commands-subagents/action-info.js +45 -0
  147. package/dist/auto-reply/reply/commands-subagents/action-kill.js +60 -0
  148. package/dist/auto-reply/reply/commands-subagents/action-list.js +44 -0
  149. package/dist/auto-reply/reply/commands-subagents/action-log.js +29 -0
  150. package/dist/auto-reply/reply/commands-subagents/action-send.js +119 -0
  151. package/dist/auto-reply/reply/commands-subagents/action-spawn.js +52 -0
  152. package/dist/auto-reply/reply/commands-subagents/action-unfocus.js +30 -0
  153. package/dist/auto-reply/reply/commands-subagents/shared.js +303 -0
  154. package/dist/auto-reply/reply/commands-subagents.js +51 -587
  155. package/dist/auto-reply/reply/commands-tts.js +10 -5
  156. package/dist/auto-reply/reply/config-value.js +10 -5
  157. package/dist/auto-reply/reply/directive-handling.model-picker.js +12 -6
  158. package/dist/auto-reply/reply/directive-handling.persist.js +9 -21
  159. package/dist/auto-reply/reply/directive-handling.shared.js +24 -4
  160. package/dist/auto-reply/reply/followup-runner.js +1 -0
  161. package/dist/auto-reply/reply/get-reply-directives-utils.js +23 -14
  162. package/dist/auto-reply/reply/get-reply-directives.js +17 -28
  163. package/dist/auto-reply/reply/get-reply-inline-actions.js +1 -0
  164. package/dist/auto-reply/reply/get-reply.js +71 -12
  165. package/dist/auto-reply/reply/model-selection.js +80 -39
  166. package/dist/auto-reply/reply/queue/enqueue.js +10 -5
  167. package/dist/auto-reply/reply/queue/state.js +13 -12
  168. package/dist/auto-reply/reply/reply-payloads.js +67 -36
  169. package/dist/auto-reply/reply/reply-reference.js +9 -8
  170. package/dist/auto-reply/reply/route-reply.js +15 -8
  171. package/dist/auto-reply/reply/session-reset-prompt.js +1 -1
  172. package/dist/auto-reply/reply/session.js +22 -6
  173. package/dist/auto-reply/reply/strip-inbound-meta.js +147 -0
  174. package/dist/auto-reply/reply/subagents-utils.js +56 -30
  175. package/dist/auto-reply/reply/typing.js +46 -21
  176. package/dist/auto-reply/send-policy.js +14 -7
  177. package/dist/auto-reply/status.js +140 -16
  178. package/dist/auto-reply/templating.js +10 -5
  179. package/dist/auto-reply/thinking.js +7 -16
  180. package/dist/auto-reply/tokens.js +21 -5
  181. package/dist/browser/bridge-server.js +36 -20
  182. package/dist/browser/cdp.helpers.js +7 -14
  183. package/dist/browser/cdp.js +35 -15
  184. package/dist/browser/chrome.profile-decoration.js +7 -4
  185. package/dist/browser/config.js +30 -0
  186. package/dist/browser/extension-relay-auth.js +55 -0
  187. package/dist/browser/extension-relay.js +74 -29
  188. package/dist/browser/navigation-guard.js +39 -0
  189. package/dist/browser/paths.js +77 -0
  190. package/dist/browser/profiles.js +13 -8
  191. package/dist/browser/pw-ai-module.js +10 -5
  192. package/dist/browser/pw-session.js +76 -39
  193. package/dist/browser/pw-tools-core.interactions.js +14 -7
  194. package/dist/browser/pw-tools-core.state.js +12 -6
  195. package/dist/browser/routes/agent.act.js +431 -424
  196. package/dist/browser/routes/agent.shared.js +47 -3
  197. package/dist/browser/routes/agent.snapshot.js +122 -116
  198. package/dist/browser/routes/agent.storage.js +303 -297
  199. package/dist/browser/routes/tabs.js +154 -100
  200. package/dist/browser/server-context.js +7 -0
  201. package/dist/browser/server-lifecycle.js +37 -0
  202. package/dist/build-info.json +3 -3
  203. package/dist/channels/allow-from.js +26 -0
  204. package/dist/channels/allowlists/resolve-utils.js +43 -19
  205. package/dist/channels/channel-config.js +14 -7
  206. package/dist/channels/draft-stream-loop.js +7 -0
  207. package/dist/channels/model-overrides.js +82 -0
  208. package/dist/channels/plugins/account-action-gate.js +13 -0
  209. package/dist/channels/plugins/message-actions.js +10 -0
  210. package/dist/channels/plugins/normalize/imessage.js +14 -7
  211. package/dist/channels/plugins/normalize/slack.js +10 -5
  212. package/dist/channels/plugins/normalize/telegram.js +14 -7
  213. package/dist/channels/plugins/outbound/discord.js +80 -8
  214. package/dist/channels/plugins/outbound/signal.js +11 -11
  215. package/dist/channels/plugins/setup-helpers.js +10 -5
  216. package/dist/channels/sender-label.js +14 -7
  217. package/dist/channels/session.js +4 -2
  218. package/dist/channels/status-reactions.js +297 -0
  219. package/dist/channels/telegram/api.js +18 -0
  220. package/dist/cli/argv.js +84 -21
  221. package/dist/cli/banner.js +3 -2
  222. package/dist/cli/browser-cli-actions-input/register.files-downloads.js +65 -56
  223. package/dist/cli/cli-name.js +11 -11
  224. package/dist/cli/cli-utils.js +13 -3
  225. package/dist/cli/command-format.js +1 -1
  226. package/dist/cli/config-cli.js +1 -1
  227. package/dist/cli/daemon-cli/lifecycle-core.js +31 -19
  228. package/dist/cli/daemon-cli/lifecycle.js +64 -2
  229. package/dist/cli/daemon-cli/restart-health.js +126 -0
  230. package/dist/cli/daemon-cli/status.gather.js +9 -13
  231. package/dist/cli/daemon-cli/status.print.js +2 -10
  232. package/dist/cli/deps.js +27 -22
  233. package/dist/cli/exec-approvals-cli.js +92 -124
  234. package/dist/cli/gateway-cli/run-loop.js +23 -5
  235. package/dist/cli/memory-cli.js +158 -61
  236. package/dist/cli/node-cli/register.js +14 -5
  237. package/dist/cli/nodes-cli/register.push.js +63 -0
  238. package/dist/cli/nodes-media-utils.js +26 -0
  239. package/dist/cli/outbound-send-deps.js +2 -9
  240. package/dist/cli/outbound-send-mapping.js +11 -0
  241. package/dist/cli/pairing-cli.js +40 -14
  242. package/dist/cli/plugins-cli.js +250 -73
  243. package/dist/cli/ports.js +11 -10
  244. package/dist/cli/program/build-program.js +3 -1
  245. package/dist/cli/program/command-registry.js +214 -136
  246. package/dist/cli/program/command-tree.js +16 -0
  247. package/dist/cli/program/help.js +43 -12
  248. package/dist/cli/program/preaction.js +13 -9
  249. package/dist/cli/program/register.configure.js +3 -18
  250. package/dist/cli/program/register.maintenance.js +2 -2
  251. package/dist/cli/program/register.onboard.js +2 -0
  252. package/dist/cli/program/register.status-health-sessions.js +16 -17
  253. package/dist/cli/program/register.subclis.js +93 -52
  254. package/dist/cli/route.js +12 -8
  255. package/dist/cli/system-cli.js +36 -46
  256. package/dist/cli/test-runtime-capture.js +24 -0
  257. package/dist/cli/update-cli/shared.js +22 -9
  258. package/dist/cli/update-cli/update-command.js +89 -14
  259. package/dist/cli/update-cli/wizard.js +6 -12
  260. package/dist/commands/agent/run-context.js +18 -5
  261. package/dist/commands/agent/session-store.js +17 -4
  262. package/dist/commands/agent.js +185 -89
  263. package/dist/commands/agents.bindings.js +14 -7
  264. package/dist/commands/agents.commands.add.js +13 -9
  265. package/dist/commands/agents.commands.identity.js +12 -6
  266. package/dist/commands/agents.commands.list.js +11 -6
  267. package/dist/commands/agents.config.js +8 -10
  268. package/dist/commands/agents.providers.js +12 -6
  269. package/dist/commands/auth-choice-options.js +103 -75
  270. package/dist/commands/auth-choice.apply.byteplus.js +55 -0
  271. package/dist/commands/auth-choice.apply.js +4 -0
  272. package/dist/commands/auth-choice.apply.minimax.js +61 -13
  273. package/dist/commands/auth-choice.apply.openai.js +3 -1
  274. package/dist/commands/auth-choice.apply.volcengine.js +55 -0
  275. package/dist/commands/auth-choice.preferred-provider.js +2 -0
  276. package/dist/commands/channels/remove.js +13 -6
  277. package/dist/commands/channels/shared.js +4 -14
  278. package/dist/commands/channels.mock-harness.js +23 -0
  279. package/dist/commands/configure.commands.js +14 -0
  280. package/dist/commands/configure.gateway.js +2 -4
  281. package/dist/commands/configure.js +1 -1
  282. package/dist/commands/configure.shared.js +11 -0
  283. package/dist/commands/daemon-install-helpers.js +2 -2
  284. package/dist/commands/daemon-install-runtime-warning.js +11 -0
  285. package/dist/commands/dashboard.js +12 -10
  286. package/dist/commands/docs.js +14 -8
  287. package/dist/commands/doctor-config-flow.js +11 -9
  288. package/dist/commands/doctor-legacy-config.js +281 -0
  289. package/dist/commands/doctor-state-integrity.js +99 -23
  290. package/dist/commands/doctor-update.js +12 -9
  291. package/dist/commands/models/list.list-command.js +7 -5
  292. package/dist/commands/models/set-image.js +2 -21
  293. package/dist/commands/node-daemon-install-helpers.js +10 -8
  294. package/dist/commands/onboard-auth.config-minimax.js +54 -80
  295. package/dist/commands/onboard-auth.config-opencode.js +2 -18
  296. package/dist/commands/onboard-auth.credentials.js +90 -13
  297. package/dist/commands/onboard-auth.js +1 -1
  298. package/dist/commands/onboard-auth.models.js +6 -5
  299. package/dist/commands/onboard-hooks.js +1 -1
  300. package/dist/commands/onboard-non-interactive/api-keys.js +14 -7
  301. package/dist/commands/onboard-non-interactive/local/auth-choice.js +64 -49
  302. package/dist/commands/onboard-provider-auth-flags.js +14 -0
  303. package/dist/commands/onboard-remote.js +14 -7
  304. package/dist/commands/onboard.js +11 -13
  305. package/dist/commands/sandbox-display.js +6 -5
  306. package/dist/commands/sessions.test-helpers.js +61 -0
  307. package/dist/commands/status-all/diagnosis.js +14 -10
  308. package/dist/commands/status-all/format.js +1 -0
  309. package/dist/commands/status.gateway-probe.js +1 -16
  310. package/dist/commands/systemd-linger.js +12 -6
  311. package/dist/config/agent-limits.js +2 -0
  312. package/dist/config/commands.js +32 -15
  313. package/dist/config/config-paths.js +9 -11
  314. package/dist/config/config.js +1 -1
  315. package/dist/config/defaults.js +22 -2
  316. package/dist/config/discord-preview-streaming.js +104 -0
  317. package/dist/config/env-substitution.js +62 -34
  318. package/dist/config/env-vars.js +45 -7
  319. package/dist/config/includes.js +4 -0
  320. package/dist/config/io.js +656 -171
  321. package/dist/config/legacy.migrations.part-1.js +189 -78
  322. package/dist/config/legacy.shared.js +3 -1
  323. package/dist/config/merge-patch.js +54 -4
  324. package/dist/config/prototype-keys.js +4 -0
  325. package/dist/config/redact-snapshot.js +404 -76
  326. package/dist/config/schema.help.js +44 -7
  327. package/dist/config/schema.js +58 -570
  328. package/dist/config/schema.labels.js +38 -6
  329. package/dist/config/sessions/delivery-info.js +10 -3
  330. package/dist/config/sessions/main-session.js +10 -5
  331. package/dist/config/sessions/session-file.js +33 -0
  332. package/dist/config/sessions/session-key.js +10 -5
  333. package/dist/config/sessions/store.js +1 -1
  334. package/dist/config/sessions.js +1 -0
  335. package/dist/config/validation.js +140 -85
  336. package/dist/config/zod-schema.agent-runtime.js +11 -0
  337. package/dist/config/zod-schema.hooks.js +40 -11
  338. package/dist/config/zod-schema.installs.js +20 -0
  339. package/dist/config/zod-schema.js +156 -20
  340. package/dist/config/zod-schema.providers-core.js +78 -4
  341. package/dist/config/zod-schema.providers.js +6 -1
  342. package/dist/config/zod-schema.session.js +41 -2
  343. package/dist/cron/run-log.js +3 -0
  344. package/dist/cron/schedule.js +21 -10
  345. package/dist/cron/service/ops.js +35 -21
  346. package/dist/cron/service/timer.js +116 -16
  347. package/dist/cron/stagger.js +3 -1
  348. package/dist/daemon/cmd-argv.js +21 -0
  349. package/dist/daemon/cmd-set.js +58 -0
  350. package/dist/daemon/service-types.js +1 -0
  351. package/dist/discord/api.js +12 -6
  352. package/dist/discord/draft-chunking.js +22 -0
  353. package/dist/discord/draft-stream.js +124 -0
  354. package/dist/discord/monitor/agent-components.js +1 -1
  355. package/dist/discord/monitor/commands.js +5 -0
  356. package/dist/discord/monitor/exec-approvals.js +357 -162
  357. package/dist/discord/monitor/gateway-plugin.js +2 -1
  358. package/dist/discord/monitor/listeners.js +37 -27
  359. package/dist/discord/monitor/message-handler.js +4 -1
  360. package/dist/discord/monitor/message-handler.preflight.js +65 -8
  361. package/dist/discord/monitor/message-handler.process.js +246 -217
  362. package/dist/discord/monitor/message-utils.js +143 -6
  363. package/dist/discord/monitor/model-picker-preferences.js +143 -0
  364. package/dist/discord/monitor/model-picker.js +651 -0
  365. package/dist/discord/monitor/native-command.js +573 -16
  366. package/dist/discord/monitor/provider.allowlist.js +223 -0
  367. package/dist/discord/monitor/provider.js +275 -347
  368. package/dist/discord/monitor/provider.lifecycle.js +100 -0
  369. package/dist/discord/monitor/reply-delivery.js +123 -16
  370. package/dist/discord/monitor/thread-bindings.discord-api.js +215 -0
  371. package/dist/discord/monitor/thread-bindings.js +4 -0
  372. package/dist/discord/monitor/thread-bindings.lifecycle.js +177 -0
  373. package/dist/discord/monitor/thread-bindings.manager.js +423 -0
  374. package/dist/discord/monitor/thread-bindings.messages.js +55 -0
  375. package/dist/discord/monitor/thread-bindings.state.js +358 -0
  376. package/dist/discord/monitor/thread-bindings.types.js +6 -0
  377. package/dist/discord/resolve-users.js +33 -21
  378. package/dist/discord/send.channels.js +15 -0
  379. package/dist/discord/send.js +3 -2
  380. package/dist/discord/send.outbound.js +82 -26
  381. package/dist/discord/send.permissions.js +83 -30
  382. package/dist/discord/send.reactions.js +8 -4
  383. package/dist/discord/token.js +10 -5
  384. package/dist/discord/voice/command.js +263 -0
  385. package/dist/discord/voice/manager.js +531 -0
  386. package/dist/gateway/auth.js +72 -13
  387. package/dist/gateway/call.js +152 -83
  388. package/dist/gateway/canvas-capability.js +75 -0
  389. package/dist/gateway/client.js +28 -4
  390. package/dist/gateway/config-reload.js +3 -4
  391. package/dist/gateway/control-plane-audit.js +28 -0
  392. package/dist/gateway/control-plane-rate-limit.js +53 -0
  393. package/dist/gateway/control-ui.js +219 -96
  394. package/dist/gateway/events.js +1 -0
  395. package/dist/gateway/hooks-mapping.js +88 -38
  396. package/dist/gateway/hooks.js +109 -54
  397. package/dist/gateway/http-auth-helpers.js +3 -2
  398. package/dist/gateway/http-common.js +22 -0
  399. package/dist/gateway/http-endpoint-helpers.js +1 -0
  400. package/dist/gateway/method-scopes.js +169 -0
  401. package/dist/gateway/net.js +74 -9
  402. package/dist/gateway/node-invoke-system-run-approval.js +14 -35
  403. package/dist/gateway/node-registry.js +10 -5
  404. package/dist/gateway/openai-http.js +1 -0
  405. package/dist/gateway/openresponses-http.js +121 -110
  406. package/dist/gateway/origin-check.js +1 -18
  407. package/dist/gateway/probe-auth.js +2 -0
  408. package/dist/gateway/protocol/index.js +4 -2
  409. package/dist/gateway/protocol/schema/cron.js +1 -0
  410. package/dist/gateway/protocol/schema/devices.js +1 -0
  411. package/dist/gateway/protocol/schema/protocol-schemas.js +4 -1
  412. package/dist/gateway/protocol/schema/push.js +18 -0
  413. package/dist/gateway/protocol/schema/sessions.js +6 -0
  414. package/dist/gateway/protocol/schema.js +1 -0
  415. package/dist/gateway/role-policy.js +17 -0
  416. package/dist/gateway/server/ws-connection/connect-policy.js +37 -0
  417. package/dist/gateway/server/ws-connection/message-handler.js +175 -148
  418. package/dist/gateway/server-chat.js +83 -25
  419. package/dist/gateway/server-constants.js +10 -9
  420. package/dist/gateway/server-cron.js +1 -0
  421. package/dist/gateway/server-http.js +247 -54
  422. package/dist/gateway/server-maintenance.js +20 -5
  423. package/dist/gateway/server-methods/agent.js +162 -24
  424. package/dist/gateway/server-methods/chat.js +465 -130
  425. package/dist/gateway/server-methods/config.js +193 -152
  426. package/dist/gateway/server-methods/devices.js +17 -3
  427. package/dist/gateway/server-methods/models.js +11 -1
  428. package/dist/gateway/server-methods/nodes.helpers.js +12 -0
  429. package/dist/gateway/server-methods/nodes.js +251 -69
  430. package/dist/gateway/server-methods/push.js +53 -0
  431. package/dist/gateway/server-methods/sessions.js +64 -8
  432. package/dist/gateway/server-methods/usage.js +162 -75
  433. package/dist/gateway/server-node-events.js +29 -0
  434. package/dist/gateway/server-reload-handlers.js +2 -3
  435. package/dist/gateway/server-runtime-config.js +39 -13
  436. package/dist/gateway/server-runtime-state.js +2 -0
  437. package/dist/gateway/server-startup-memory.js +17 -11
  438. package/dist/gateway/server-ws-runtime.js +1 -0
  439. package/dist/gateway/server.impl.js +296 -139
  440. package/dist/gateway/session-preview.test-helpers.js +11 -0
  441. package/dist/gateway/session-utils.fs.js +32 -34
  442. package/dist/gateway/sessions-resolve.js +17 -5
  443. package/dist/gateway/startup-auth.js +126 -0
  444. package/dist/gateway/test-helpers.agent-results.js +15 -0
  445. package/dist/gateway/test-helpers.mocks.js +37 -14
  446. package/dist/gateway/test-helpers.openai-mock.js +14 -7
  447. package/dist/gateway/test-helpers.server.js +161 -77
  448. package/dist/gateway/tools-invoke-http.js +21 -10
  449. package/dist/hooks/bundled/bootstrap-extra-files/handler.js +3 -1
  450. package/dist/hooks/bundled/command-logger/handler.js +7 -2
  451. package/dist/hooks/bundled/session-memory/handler.js +170 -38
  452. package/dist/hooks/frontmatter.js +6 -6
  453. package/dist/hooks/gmail-watcher-lifecycle.js +23 -0
  454. package/dist/hooks/gmail-watcher.js +11 -6
  455. package/dist/hooks/internal-hooks.js +11 -1
  456. package/dist/hooks/llm-slug-generator.js +4 -1
  457. package/dist/hooks/workspace.js +47 -17
  458. package/dist/imessage/accounts.js +9 -20
  459. package/dist/imessage/monitor/inbound-processing.js +2 -1
  460. package/dist/infra/archive-path.js +49 -0
  461. package/dist/infra/archive.js +174 -73
  462. package/dist/infra/control-ui-assets.js +14 -6
  463. package/dist/infra/device-pairing.js +204 -144
  464. package/dist/infra/env.js +10 -5
  465. package/dist/infra/exec-approvals-allowlist.js +141 -70
  466. package/dist/infra/exec-approvals-analysis.js +78 -20
  467. package/dist/infra/exec-approvals.js +5 -17
  468. package/dist/infra/exec-safe-bin-policy.js +277 -0
  469. package/dist/infra/fixed-window-rate-limit.js +33 -0
  470. package/dist/infra/fs-safe.js +71 -39
  471. package/dist/infra/gateway-lock.js +6 -2
  472. package/dist/infra/git-root.js +61 -0
  473. package/dist/infra/heartbeat-active-hours.js +2 -2
  474. package/dist/infra/heartbeat-reason.js +40 -0
  475. package/dist/infra/heartbeat-runner.js +72 -32
  476. package/dist/infra/heartbeat-wake.js +6 -12
  477. package/dist/infra/host-env-security-policy.json +19 -0
  478. package/dist/infra/host-env-security.js +66 -0
  479. package/dist/infra/install-source-utils.js +91 -7
  480. package/dist/infra/net/ssrf.js +131 -38
  481. package/dist/infra/node-pairing.js +50 -105
  482. package/dist/infra/npm-integrity.js +45 -0
  483. package/dist/infra/npm-pack-install.js +40 -0
  484. package/dist/infra/outbound/bound-delivery-router.js +88 -0
  485. package/dist/infra/outbound/channel-adapters.js +20 -7
  486. package/dist/infra/outbound/channel-selection.js +12 -6
  487. package/dist/infra/outbound/envelope.js +1 -1
  488. package/dist/infra/outbound/format.js +12 -6
  489. package/dist/infra/outbound/message-action-runner.js +107 -327
  490. package/dist/infra/outbound/message.js +59 -36
  491. package/dist/infra/outbound/outbound-policy.js +52 -25
  492. package/dist/infra/outbound/outbound-send-service.js +58 -71
  493. package/dist/infra/outbound/payloads.js +14 -7
  494. package/dist/infra/outbound/session-binding-service.js +123 -0
  495. package/dist/infra/pairing-files.js +10 -0
  496. package/dist/infra/path-guards.js +25 -0
  497. package/dist/infra/plain-object.js +9 -0
  498. package/dist/infra/provider-usage.fetch.codex.js +7 -15
  499. package/dist/infra/provider-usage.fetch.gemini.js +14 -11
  500. package/dist/infra/provider-usage.fetch.shared.js +30 -1
  501. package/dist/infra/provider-usage.fetch.zai.js +10 -9
  502. package/dist/infra/push-apns.js +365 -0
  503. package/dist/infra/restart-sentinel.js +16 -1
  504. package/dist/infra/restart.js +229 -26
  505. package/dist/infra/retry-policy.js +4 -2
  506. package/dist/infra/retry.js +9 -5
  507. package/dist/infra/scp-host.js +54 -0
  508. package/dist/infra/session-cost-usage.js +107 -59
  509. package/dist/infra/session-maintenance-warning.js +3 -1
  510. package/dist/infra/shell-env.js +98 -34
  511. package/dist/infra/ssh-config.js +12 -6
  512. package/dist/infra/system-run-command.js +49 -4
  513. package/dist/infra/update-channels.js +10 -5
  514. package/dist/infra/update-startup.js +86 -9
  515. package/dist/line/accounts.js +5 -7
  516. package/dist/line/bot-access.js +8 -20
  517. package/dist/line/bot-handlers.js +3 -1
  518. package/dist/link-understanding/detect.js +15 -7
  519. package/dist/media/constants.js +15 -6
  520. package/dist/media/image-ops.js +7 -0
  521. package/dist/media/inbound-path-policy.js +114 -0
  522. package/dist/media/input-files.js +16 -0
  523. package/dist/media/local-roots.js +3 -2
  524. package/dist/media-understanding/apply.js +4 -1
  525. package/dist/media-understanding/concurrency.js +8 -20
  526. package/dist/memory/backend-config.js +45 -6
  527. package/dist/memory/embeddings.js +10 -4
  528. package/dist/memory/fs-utils.js +23 -0
  529. package/dist/memory/manager-search.js +12 -6
  530. package/dist/memory/manager-sync-ops.js +12 -2
  531. package/dist/memory/qmd-manager.js +466 -53
  532. package/dist/memory/query-expansion.js +167 -3
  533. package/dist/memory/status-format.js +10 -5
  534. package/dist/memory/sync-memory-files.js +1 -1
  535. package/dist/memory/test-manager.js +8 -0
  536. package/dist/node-host/invoke-system-run.js +281 -0
  537. package/dist/node-host/invoke.js +55 -337
  538. package/dist/pairing/pairing-store.js +22 -0
  539. package/dist/plugin-sdk/allow-from.js +1 -1
  540. package/dist/plugin-sdk/command-auth.js +3 -1
  541. package/dist/plugin-sdk/index.js +6 -3
  542. package/dist/plugin-sdk/temp-path.js +47 -0
  543. package/dist/plugin-sdk/webhook-targets.js +32 -0
  544. package/dist/plugins/bundled-dir.js +9 -6
  545. package/dist/plugins/discovery.js +217 -23
  546. package/dist/plugins/hook-runner-global.js +16 -0
  547. package/dist/plugins/hooks.js +50 -0
  548. package/dist/plugins/install.js +28 -16
  549. package/dist/plugins/loader.js +192 -26
  550. package/dist/plugins/logger.js +8 -0
  551. package/dist/plugins/manifest-registry.js +3 -0
  552. package/dist/plugins/path-safety.js +34 -0
  553. package/dist/plugins/registry.js +5 -2
  554. package/dist/plugins/runtime/index.js +271 -206
  555. package/dist/plugins/runtime.js +3 -17
  556. package/dist/plugins/update.js +78 -12
  557. package/dist/process/spawn-utils.js +14 -7
  558. package/dist/providers/github-copilot-models.js +4 -1
  559. package/dist/providers/github-copilot-token.js +11 -6
  560. package/dist/providers/qwen-portal-oauth.js +14 -6
  561. package/dist/routing/account-id.js +30 -0
  562. package/dist/routing/resolve-route.js +3 -7
  563. package/dist/routing/session-key.js +2 -16
  564. package/dist/security/audit-channel.js +100 -20
  565. package/dist/security/audit-extra.async.js +505 -179
  566. package/dist/security/audit-extra.js +12 -2
  567. package/dist/security/audit-extra.sync.js +421 -35
  568. package/dist/security/audit-fs.js +31 -13
  569. package/dist/security/audit.js +180 -370
  570. package/dist/security/dm-policy-shared.js +68 -0
  571. package/dist/security/external-content.js +46 -14
  572. package/dist/security/fix.js +49 -85
  573. package/dist/security/scan-paths.js +20 -0
  574. package/dist/security/secret-equal.js +3 -7
  575. package/dist/security/windows-acl.js +30 -15
  576. package/dist/shared/entry-status.js +6 -0
  577. package/dist/shared/frontmatter.js +5 -5
  578. package/dist/shared/node-list-parse.js +13 -0
  579. package/dist/shared/node-match.js +11 -4
  580. package/dist/shared/operator-scope-compat.js +42 -0
  581. package/dist/shared/text-chunking.js +29 -0
  582. package/dist/signal/accounts.js +7 -20
  583. package/dist/signal/monitor/event-handler.js +3 -1
  584. package/dist/slack/accounts.js +6 -19
  585. package/dist/slack/actions.js +11 -3
  586. package/dist/slack/blocks.test-helpers.js +31 -0
  587. package/dist/slack/monitor/auth.js +1 -1
  588. package/dist/slack/monitor/message-handler/dispatch.js +50 -29
  589. package/dist/slack/monitor/mrkdwn.js +8 -0
  590. package/dist/slack/monitor/replies.js +15 -7
  591. package/dist/slack/monitor/slash.js +22 -13
  592. package/dist/slack/resolve-channels.js +10 -5
  593. package/dist/slack/send.js +102 -12
  594. package/dist/slack/stream-mode.js +10 -0
  595. package/dist/slack/streaming.js +4 -2
  596. package/dist/telegram/accounts.js +19 -14
  597. package/dist/telegram/bot/helpers.js +3 -5
  598. package/dist/telegram/bot-access.js +35 -36
  599. package/dist/telegram/bot-handlers.js +120 -148
  600. package/dist/telegram/bot-message-context.js +68 -9
  601. package/dist/telegram/bot-message-dispatch.js +477 -210
  602. package/dist/telegram/bot-native-commands.js +16 -0
  603. package/dist/telegram/draft-stream.js +44 -8
  604. package/dist/telegram/inline-buttons.js +5 -15
  605. package/dist/telegram/monitor.js +11 -7
  606. package/dist/telegram/network-config.js +19 -7
  607. package/dist/telegram/reasoning-lane-coordinator.js +128 -0
  608. package/dist/telegram/send.js +3 -2
  609. package/dist/telegram/sent-message-cache.js +5 -6
  610. package/dist/telegram/status-reaction-variants.js +208 -0
  611. package/dist/telegram/sticker-cache.js +11 -9
  612. package/dist/terminal/prompt-select-styled.js +9 -0
  613. package/dist/terminal/theme.js +12 -12
  614. package/dist/test-utils/command-runner.js +6 -0
  615. package/dist/test-utils/internal-hook-event-payload.js +10 -0
  616. package/dist/test-utils/model-auth-mock.js +12 -0
  617. package/dist/test-utils/provider-usage-fetch.js +14 -0
  618. package/dist/test-utils/temp-home.js +33 -0
  619. package/dist/tts/tts.js +80 -567
  620. package/dist/tui/components/chat-log.js +50 -8
  621. package/dist/tui/theme/theme.js +10 -12
  622. package/dist/tui/tui-command-handlers.js +36 -27
  623. package/dist/tui/tui-event-handlers.js +122 -32
  624. package/dist/tui/tui-local-shell.js +16 -6
  625. package/dist/tui/tui.js +236 -48
  626. package/dist/utils/account-id.js +2 -4
  627. package/dist/utils/boolean.js +10 -5
  628. package/dist/utils/directive-tags.js +11 -0
  629. package/dist/utils/mask-api-key.js +10 -0
  630. package/dist/utils/queue-helpers.js +67 -12
  631. package/dist/utils/run-with-concurrency.js +39 -0
  632. package/dist/web/auto-reply/deliver-reply.js +8 -4
  633. package/dist/web/auto-reply/mentions.js +10 -5
  634. package/dist/web/auto-reply/monitor/group-members.js +14 -7
  635. package/dist/web/auto-reply/monitor/process-message.js +45 -24
  636. package/dist/web/inbound/access-control.js +5 -2
  637. package/dist/web/login-qr.js +12 -6
  638. package/dist/web/media.js +126 -15
  639. package/docs/tools/slash-commands.md +5 -1
  640. package/extensions/bluebubbles/src/monitor-processing.ts +580 -139
  641. package/extensions/bluebubbles/src/monitor.ts +208 -1950
  642. package/extensions/feishu/src/external-keys.ts +19 -0
  643. package/extensions/lobster/src/windows-spawn.ts +193 -0
  644. package/extensions/matrix/src/matrix/actions/limits.ts +6 -0
  645. package/extensions/mattermost/src/mattermost/reactions.test-helpers.ts +83 -0
  646. package/package.json +1 -1
@@ -1,46 +1,30 @@
1
- import { RequestClient } from "@buape/carbon";
2
1
  import { ChannelType, PermissionFlagsBits, Routes } from "discord-api-types/v10";
3
- import { loadConfig } from "../config/config.js";
4
- import { resolveDiscordAccount } from "./accounts.js";
5
- import { normalizeDiscordToken } from "./token.js";
2
+ import { resolveDiscordRest } from "./client.js";
6
3
  const PERMISSION_ENTRIES = Object.entries(PermissionFlagsBits).filter(([, value]) => typeof value === "bigint");
7
- function resolveToken(params) {
8
- const explicit = normalizeDiscordToken(params.explicit);
9
- if (explicit)
10
- return explicit;
11
- const fallback = normalizeDiscordToken(params.fallbackToken);
12
- if (!fallback) {
13
- throw new Error(`Discord bot token missing for account "${params.accountId}" (set discord.accounts.${params.accountId}.token or DISCORD_BOT_TOKEN for default).`);
14
- }
15
- return fallback;
16
- }
17
- function resolveRest(token, rest) {
18
- return rest ?? new RequestClient(token);
19
- }
20
- function resolveDiscordRest(opts) {
21
- const cfg = loadConfig();
22
- const account = resolveDiscordAccount({ cfg, accountId: opts.accountId });
23
- const token = resolveToken({
24
- explicit: opts.token,
25
- accountId: account.accountId,
26
- fallbackToken: account.token,
27
- });
28
- return resolveRest(token, opts.rest);
29
- }
4
+ const ALL_PERMISSIONS = PERMISSION_ENTRIES.reduce((acc, [, value]) => acc | value, 0n);
5
+ const ADMINISTRATOR_BIT = PermissionFlagsBits.Administrator;
30
6
  function addPermissionBits(base, add) {
31
- if (!add)
7
+ if (!add) {
32
8
  return base;
9
+ }
33
10
  return base | BigInt(add);
34
11
  }
35
12
  function removePermissionBits(base, deny) {
36
- if (!deny)
13
+ if (!deny) {
37
14
  return base;
15
+ }
38
16
  return base & ~BigInt(deny);
39
17
  }
40
18
  function bitfieldToPermissions(bitfield) {
41
19
  return PERMISSION_ENTRIES.filter(([, value]) => (bitfield & value) === value)
42
20
  .map(([name]) => name)
43
- .sort();
21
+ .toSorted();
22
+ }
23
+ function hasAdministrator(bitfield) {
24
+ return (bitfield & ADMINISTRATOR_BIT) === ADMINISTRATOR_BIT;
25
+ }
26
+ function hasPermissionBit(bitfield, permission) {
27
+ return (bitfield & permission) === permission;
44
28
  }
45
29
  export function isThreadChannelType(channelType) {
46
30
  return (channelType === ChannelType.GuildNewsThread ||
@@ -54,6 +38,65 @@ async function fetchBotUserId(rest) {
54
38
  }
55
39
  return me.id;
56
40
  }
41
+ /**
42
+ * Fetch guild-level permissions for a user. This does not include channel-specific overwrites.
43
+ */
44
+ export async function fetchMemberGuildPermissionsDiscord(guildId, userId, opts = {}) {
45
+ const rest = resolveDiscordRest(opts);
46
+ try {
47
+ const [guild, member] = await Promise.all([
48
+ rest.get(Routes.guild(guildId)),
49
+ rest.get(Routes.guildMember(guildId, userId)),
50
+ ]);
51
+ const rolesById = new Map((guild.roles ?? []).map((role) => [role.id, role]));
52
+ const everyoneRole = rolesById.get(guildId);
53
+ let permissions = 0n;
54
+ if (everyoneRole?.permissions) {
55
+ permissions = addPermissionBits(permissions, everyoneRole.permissions);
56
+ }
57
+ for (const roleId of member.roles ?? []) {
58
+ const role = rolesById.get(roleId);
59
+ if (role?.permissions) {
60
+ permissions = addPermissionBits(permissions, role.permissions);
61
+ }
62
+ }
63
+ return permissions;
64
+ }
65
+ catch {
66
+ // Not a guild member, guild not found, or API failure.
67
+ return null;
68
+ }
69
+ }
70
+ /**
71
+ * Returns true when the user has ADMINISTRATOR or any required permission bit.
72
+ */
73
+ export async function hasAnyGuildPermissionDiscord(guildId, userId, requiredPermissions, opts = {}) {
74
+ const permissions = await fetchMemberGuildPermissionsDiscord(guildId, userId, opts);
75
+ if (permissions === null) {
76
+ return false;
77
+ }
78
+ if (hasAdministrator(permissions)) {
79
+ return true;
80
+ }
81
+ return requiredPermissions.some((permission) => hasPermissionBit(permissions, permission));
82
+ }
83
+ /**
84
+ * Returns true when the user has ADMINISTRATOR or all required permission bits.
85
+ */
86
+ export async function hasAllGuildPermissionsDiscord(guildId, userId, requiredPermissions, opts = {}) {
87
+ const permissions = await fetchMemberGuildPermissionsDiscord(guildId, userId, opts);
88
+ if (permissions === null) {
89
+ return false;
90
+ }
91
+ if (hasAdministrator(permissions)) {
92
+ return true;
93
+ }
94
+ return requiredPermissions.every((permission) => hasPermissionBit(permissions, permission));
95
+ }
96
+ /**
97
+ * @deprecated Prefer hasAnyGuildPermissionDiscord or hasAllGuildPermissionsDiscord for clarity.
98
+ */
99
+ export const hasGuildPermissionDiscord = hasAnyGuildPermissionDiscord;
57
100
  export async function fetchChannelPermissionsDiscord(channelId, opts = {}) {
58
101
  const rest = resolveDiscordRest(opts);
59
102
  const channel = (await rest.get(Routes.channel(channelId)));
@@ -85,6 +128,16 @@ export async function fetchChannelPermissionsDiscord(channelId, opts = {}) {
85
128
  base = addPermissionBits(base, role.permissions);
86
129
  }
87
130
  }
131
+ if (hasAdministrator(base)) {
132
+ return {
133
+ channelId,
134
+ guildId,
135
+ permissions: bitfieldToPermissions(ALL_PERMISSIONS),
136
+ raw: ALL_PERMISSIONS.toString(),
137
+ isDm: false,
138
+ channelType,
139
+ };
140
+ }
88
141
  let permissions = base;
89
142
  const overwrites = "permission_overwrites" in channel ? (channel.permission_overwrites ?? []) : [];
90
143
  for (const overwrite of overwrites) {
@@ -20,11 +20,13 @@ export async function removeOwnReactionsDiscord(channelId, messageId, opts = {})
20
20
  const identifiers = new Set();
21
21
  for (const reaction of message.reactions ?? []) {
22
22
  const identifier = buildReactionIdentifier(reaction.emoji);
23
- if (identifier)
23
+ if (identifier) {
24
24
  identifiers.add(identifier);
25
+ }
25
26
  }
26
- if (identifiers.size === 0)
27
+ if (identifiers.size === 0) {
27
28
  return { ok: true, removed: [] };
29
+ }
28
30
  const removed = [];
29
31
  await Promise.allSettled(Array.from(identifiers, (identifier) => {
30
32
  removed.push(identifier);
@@ -36,16 +38,18 @@ export async function fetchReactionsDiscord(channelId, messageId, opts = {}) {
36
38
  const rest = resolveDiscordRest(opts);
37
39
  const message = (await rest.get(Routes.channelMessage(channelId, messageId)));
38
40
  const reactions = message.reactions ?? [];
39
- if (reactions.length === 0)
41
+ if (reactions.length === 0) {
40
42
  return [];
43
+ }
41
44
  const limit = typeof opts.limit === "number" && Number.isFinite(opts.limit)
42
45
  ? Math.min(Math.max(Math.floor(opts.limit), 1), 100)
43
46
  : 100;
44
47
  const summaries = [];
45
48
  for (const reaction of reactions) {
46
49
  const identifier = buildReactionIdentifier(reaction.emoji);
47
- if (!identifier)
50
+ if (!identifier) {
48
51
  continue;
52
+ }
49
53
  const encoded = encodeURIComponent(identifier);
50
54
  const users = (await rest.get(Routes.channelMessageReaction(channelId, messageId, encoded), {
51
55
  limit,
@@ -1,10 +1,12 @@
1
1
  import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../routing/session-key.js";
2
2
  export function normalizeDiscordToken(raw) {
3
- if (!raw)
3
+ if (!raw) {
4
4
  return undefined;
5
+ }
5
6
  const trimmed = raw.trim();
6
- if (!trimmed)
7
+ if (!trimmed) {
7
8
  return undefined;
9
+ }
8
10
  return trimmed.replace(/^Bot\s+/i, "");
9
11
  }
10
12
  export function resolveDiscordToken(cfg, opts = {}) {
@@ -14,16 +16,19 @@ export function resolveDiscordToken(cfg, opts = {}) {
14
16
  ? discordCfg?.accounts?.[accountId]
15
17
  : discordCfg?.accounts?.[DEFAULT_ACCOUNT_ID];
16
18
  const accountToken = normalizeDiscordToken(accountCfg?.token ?? undefined);
17
- if (accountToken)
19
+ if (accountToken) {
18
20
  return { token: accountToken, source: "config" };
21
+ }
19
22
  const allowEnv = accountId === DEFAULT_ACCOUNT_ID;
20
23
  const configToken = allowEnv ? normalizeDiscordToken(discordCfg?.token ?? undefined) : undefined;
21
- if (configToken)
24
+ if (configToken) {
22
25
  return { token: configToken, source: "config" };
26
+ }
23
27
  const envToken = allowEnv
24
28
  ? normalizeDiscordToken(opts.envToken ?? process.env.DISCORD_BOT_TOKEN)
25
29
  : undefined;
26
- if (envToken)
30
+ if (envToken) {
27
31
  return { token: envToken, source: "env" };
32
+ }
28
33
  return { token: "", source: "none" };
29
34
  }
@@ -0,0 +1,263 @@
1
+ import { ChannelType as CarbonChannelType, Command, CommandWithSubcommands, } from "@buape/carbon";
2
+ import { ApplicationCommandOptionType, ChannelType as DiscordChannelType, } from "discord-api-types/v10";
3
+ import { resolveCommandAuthorizedFromAuthorizers } from "../../channels/command-gating.js";
4
+ import { allowListMatches, isDiscordGroupAllowedByPolicy, normalizeDiscordAllowList, normalizeDiscordSlug, resolveDiscordChannelConfigWithFallback, resolveDiscordGuildEntry, resolveDiscordMemberAccessState, } from "../monitor/allow-list.js";
5
+ import { resolveDiscordChannelInfo } from "../monitor/message-utils.js";
6
+ import { resolveDiscordSenderIdentity } from "../monitor/sender-identity.js";
7
+ import { resolveDiscordThreadParentInfo } from "../monitor/threading.js";
8
+ const VOICE_CHANNEL_TYPES = [
9
+ DiscordChannelType.GuildVoice,
10
+ DiscordChannelType.GuildStageVoice,
11
+ ];
12
+ async function authorizeVoiceCommand(interaction, params, options) {
13
+ const channelOverride = options?.channelOverride;
14
+ const channel = channelOverride ? undefined : interaction.channel;
15
+ if (!interaction.guild) {
16
+ return { ok: false, message: "Voice commands are only available in guilds." };
17
+ }
18
+ const user = interaction.user;
19
+ if (!user) {
20
+ return { ok: false, message: "Unable to resolve command user." };
21
+ }
22
+ const channelId = channelOverride?.id ?? channel?.id ?? "";
23
+ const rawChannelName = channelOverride?.name ?? (channel && "name" in channel ? channel.name : undefined);
24
+ const rawParentId = channelOverride?.parentId ??
25
+ ("parentId" in (channel ?? {})
26
+ ? (channel.parentId ?? undefined)
27
+ : undefined);
28
+ const channelInfo = channelId
29
+ ? await resolveDiscordChannelInfo(interaction.client, channelId)
30
+ : null;
31
+ const channelName = rawChannelName ?? channelInfo?.name;
32
+ const channelSlug = channelName ? normalizeDiscordSlug(channelName) : "";
33
+ const isThreadChannel = channelInfo?.type === CarbonChannelType.PublicThread ||
34
+ channelInfo?.type === CarbonChannelType.PrivateThread ||
35
+ channelInfo?.type === CarbonChannelType.AnnouncementThread;
36
+ let parentId;
37
+ let parentName;
38
+ let parentSlug;
39
+ if (isThreadChannel && channelId) {
40
+ const parentInfo = await resolveDiscordThreadParentInfo({
41
+ client: interaction.client,
42
+ threadChannel: {
43
+ id: channelId,
44
+ name: channelName,
45
+ parentId: rawParentId ?? channelInfo?.parentId,
46
+ parent: undefined,
47
+ },
48
+ channelInfo,
49
+ });
50
+ parentId = parentInfo.id;
51
+ parentName = parentInfo.name;
52
+ parentSlug = parentName ? normalizeDiscordSlug(parentName) : undefined;
53
+ }
54
+ const guildInfo = resolveDiscordGuildEntry({
55
+ guild: interaction.guild ?? undefined,
56
+ guildEntries: params.discordConfig.guilds,
57
+ });
58
+ const channelConfig = channelId
59
+ ? resolveDiscordChannelConfigWithFallback({
60
+ guildInfo,
61
+ channelId,
62
+ channelName,
63
+ channelSlug,
64
+ parentId,
65
+ parentName,
66
+ parentSlug,
67
+ scope: isThreadChannel ? "thread" : "channel",
68
+ })
69
+ : null;
70
+ if (channelConfig?.enabled === false) {
71
+ return { ok: false, message: "This channel is disabled." };
72
+ }
73
+ const channelAllowlistConfigured = Boolean(guildInfo?.channels) && Object.keys(guildInfo?.channels ?? {}).length > 0;
74
+ const channelAllowed = channelConfig?.allowed !== false;
75
+ if (!isDiscordGroupAllowedByPolicy({
76
+ groupPolicy: params.groupPolicy,
77
+ guildAllowlisted: Boolean(guildInfo),
78
+ channelAllowlistConfigured,
79
+ channelAllowed,
80
+ }) ||
81
+ channelConfig?.allowed === false) {
82
+ const channelId = channelOverride?.id ?? channel?.id;
83
+ const channelLabel = channelId ? `<#${channelId}>` : "This channel";
84
+ return {
85
+ ok: false,
86
+ message: `${channelLabel} is not allowlisted for voice commands.`,
87
+ };
88
+ }
89
+ const memberRoleIds = Array.isArray(interaction.rawData.member?.roles)
90
+ ? interaction.rawData.member.roles.map((roleId) => String(roleId))
91
+ : [];
92
+ const sender = resolveDiscordSenderIdentity({ author: user, member: interaction.rawData.member });
93
+ const { hasAccessRestrictions, memberAllowed } = resolveDiscordMemberAccessState({
94
+ channelConfig,
95
+ guildInfo,
96
+ memberRoleIds,
97
+ sender,
98
+ });
99
+ const ownerAllowList = normalizeDiscordAllowList(params.discordConfig.allowFrom ?? params.discordConfig.dm?.allowFrom ?? [], ["discord:", "user:", "pk:"]);
100
+ const ownerOk = ownerAllowList
101
+ ? allowListMatches(ownerAllowList, {
102
+ id: sender.id,
103
+ name: sender.name,
104
+ tag: sender.tag,
105
+ })
106
+ : false;
107
+ const authorizers = params.useAccessGroups
108
+ ? [
109
+ { configured: ownerAllowList != null, allowed: ownerOk },
110
+ { configured: hasAccessRestrictions, allowed: memberAllowed },
111
+ ]
112
+ : [{ configured: hasAccessRestrictions, allowed: memberAllowed }];
113
+ const commandAuthorized = resolveCommandAuthorizedFromAuthorizers({
114
+ useAccessGroups: params.useAccessGroups,
115
+ authorizers,
116
+ modeWhenAccessGroupsOff: "configured",
117
+ });
118
+ if (!commandAuthorized) {
119
+ return { ok: false, message: "You are not authorized to use this command." };
120
+ }
121
+ return { ok: true, guildId: interaction.guild.id };
122
+ }
123
+ export function createDiscordVoiceCommand(params) {
124
+ const resolveSessionChannelId = (manager, guildId) => manager.status().find((entry) => entry.guildId === guildId)?.channelId;
125
+ class JoinCommand extends Command {
126
+ name = "join";
127
+ description = "Join a voice channel";
128
+ defer = true;
129
+ ephemeral = params.ephemeralDefault;
130
+ options = [
131
+ {
132
+ name: "channel",
133
+ description: "Voice channel to join",
134
+ type: ApplicationCommandOptionType.Channel,
135
+ required: true,
136
+ channel_types: VOICE_CHANNEL_TYPES,
137
+ },
138
+ ];
139
+ async run(interaction) {
140
+ const channel = await interaction.options.getChannel("channel", true);
141
+ if (!channel || !("id" in channel)) {
142
+ await interaction.reply({ content: "Voice channel not found.", ephemeral: true });
143
+ return;
144
+ }
145
+ const access = await authorizeVoiceCommand(interaction, params, {
146
+ channelOverride: {
147
+ id: channel.id,
148
+ name: "name" in channel ? channel.name : undefined,
149
+ parentId: "parentId" in channel
150
+ ? (channel.parentId ?? undefined)
151
+ : undefined,
152
+ },
153
+ });
154
+ if (!access.ok) {
155
+ await interaction.reply({ content: access.message ?? "Not authorized.", ephemeral: true });
156
+ return;
157
+ }
158
+ if (!isVoiceChannelType(channel.type)) {
159
+ await interaction.reply({ content: "That is not a voice channel.", ephemeral: true });
160
+ return;
161
+ }
162
+ const guildId = access.guildId ?? ("guildId" in channel ? channel.guildId : undefined);
163
+ if (!guildId) {
164
+ await interaction.reply({
165
+ content: "Unable to resolve guild for this voice channel.",
166
+ ephemeral: true,
167
+ });
168
+ return;
169
+ }
170
+ const manager = params.getManager();
171
+ if (!manager) {
172
+ await interaction.reply({
173
+ content: "Voice manager is not available yet.",
174
+ ephemeral: true,
175
+ });
176
+ return;
177
+ }
178
+ const result = await manager.join({ guildId, channelId: channel.id });
179
+ await interaction.reply({ content: result.message, ephemeral: true });
180
+ }
181
+ }
182
+ class LeaveCommand extends Command {
183
+ name = "leave";
184
+ description = "Leave the current voice channel";
185
+ defer = true;
186
+ ephemeral = params.ephemeralDefault;
187
+ async run(interaction) {
188
+ const guildId = interaction.guild?.id;
189
+ if (!guildId) {
190
+ await interaction.reply({
191
+ content: "Unable to resolve guild for this command.",
192
+ ephemeral: true,
193
+ });
194
+ return;
195
+ }
196
+ const manager = params.getManager();
197
+ if (!manager) {
198
+ await interaction.reply({
199
+ content: "Voice manager is not available yet.",
200
+ ephemeral: true,
201
+ });
202
+ return;
203
+ }
204
+ const sessionChannelId = resolveSessionChannelId(manager, guildId);
205
+ const access = await authorizeVoiceCommand(interaction, params, {
206
+ channelOverride: sessionChannelId ? { id: sessionChannelId } : undefined,
207
+ });
208
+ if (!access.ok) {
209
+ await interaction.reply({ content: access.message ?? "Not authorized.", ephemeral: true });
210
+ return;
211
+ }
212
+ const result = await manager.leave({ guildId });
213
+ await interaction.reply({ content: result.message, ephemeral: true });
214
+ }
215
+ }
216
+ class StatusCommand extends Command {
217
+ name = "status";
218
+ description = "Show active voice sessions";
219
+ defer = true;
220
+ ephemeral = params.ephemeralDefault;
221
+ async run(interaction) {
222
+ const guildId = interaction.guild?.id;
223
+ if (!guildId) {
224
+ await interaction.reply({
225
+ content: "Unable to resolve guild for this command.",
226
+ ephemeral: true,
227
+ });
228
+ return;
229
+ }
230
+ const manager = params.getManager();
231
+ if (!manager) {
232
+ await interaction.reply({
233
+ content: "Voice manager is not available yet.",
234
+ ephemeral: true,
235
+ });
236
+ return;
237
+ }
238
+ const sessions = manager.status().filter((entry) => entry.guildId === guildId);
239
+ const sessionChannelId = sessions[0]?.channelId;
240
+ const access = await authorizeVoiceCommand(interaction, params, {
241
+ channelOverride: sessionChannelId ? { id: sessionChannelId } : undefined,
242
+ });
243
+ if (!access.ok) {
244
+ await interaction.reply({ content: access.message ?? "Not authorized.", ephemeral: true });
245
+ return;
246
+ }
247
+ if (sessions.length === 0) {
248
+ await interaction.reply({ content: "No active voice sessions.", ephemeral: true });
249
+ return;
250
+ }
251
+ const lines = sessions.map((entry) => `\u2022 <#${entry.channelId}> (guild ${entry.guildId})`);
252
+ await interaction.reply({ content: lines.join("\n"), ephemeral: true });
253
+ }
254
+ }
255
+ return new (class extends CommandWithSubcommands {
256
+ name = "vc";
257
+ description = "Voice channel controls";
258
+ subcommands = [new JoinCommand(), new LeaveCommand(), new StatusCommand()];
259
+ })();
260
+ }
261
+ function isVoiceChannelType(type) {
262
+ return type === CarbonChannelType.GuildVoice || type === CarbonChannelType.GuildStageVoice;
263
+ }