@gakr-gakr/discord 0.1.0

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 (353) hide show
  1. package/account-inspect-api.ts +6 -0
  2. package/action-runtime-api.ts +1 -0
  3. package/api.ts +130 -0
  4. package/autobot.plugin.json +15 -0
  5. package/channel-config-api.ts +1 -0
  6. package/channel-plugin-api.ts +3 -0
  7. package/config-api.ts +4 -0
  8. package/configured-state.ts +6 -0
  9. package/contract-api.ts +21 -0
  10. package/directory-contract-api.ts +4 -0
  11. package/doctor-contract-api.ts +1 -0
  12. package/index.ts +24 -0
  13. package/package.json +79 -0
  14. package/runtime-api.actions.ts +15 -0
  15. package/runtime-api.lookup.ts +22 -0
  16. package/runtime-api.monitor.ts +50 -0
  17. package/runtime-api.send.ts +79 -0
  18. package/runtime-api.threads.ts +31 -0
  19. package/runtime-api.ts +181 -0
  20. package/runtime-setter-api.ts +3 -0
  21. package/secret-contract-api.ts +4 -0
  22. package/security-audit-contract-api.ts +1 -0
  23. package/security-contract-api.ts +4 -0
  24. package/session-key-api.ts +1 -0
  25. package/setup-entry.ts +9 -0
  26. package/setup-plugin-api.ts +3 -0
  27. package/src/account-inspect.ts +131 -0
  28. package/src/accounts.ts +205 -0
  29. package/src/actions/handle-action.guild-admin.ts +421 -0
  30. package/src/actions/handle-action.ts +402 -0
  31. package/src/actions/runtime.guild.ts +446 -0
  32. package/src/actions/runtime.messaging.messages.ts +226 -0
  33. package/src/actions/runtime.messaging.reactions.ts +67 -0
  34. package/src/actions/runtime.messaging.runtime.ts +73 -0
  35. package/src/actions/runtime.messaging.send.ts +336 -0
  36. package/src/actions/runtime.messaging.shared.ts +97 -0
  37. package/src/actions/runtime.messaging.ts +37 -0
  38. package/src/actions/runtime.moderation-shared.ts +48 -0
  39. package/src/actions/runtime.moderation.ts +116 -0
  40. package/src/actions/runtime.presence.ts +117 -0
  41. package/src/actions/runtime.shared.ts +86 -0
  42. package/src/actions/runtime.ts +87 -0
  43. package/src/api.ts +219 -0
  44. package/src/approval-handler.runtime.ts +636 -0
  45. package/src/approval-native.ts +219 -0
  46. package/src/approval-runtime.ts +14 -0
  47. package/src/approval-shared.ts +56 -0
  48. package/src/audit-core.ts +178 -0
  49. package/src/audit.ts +32 -0
  50. package/src/channel-actions.runtime.ts +1 -0
  51. package/src/channel-actions.ts +254 -0
  52. package/src/channel-api.ts +29 -0
  53. package/src/channel.conversation.ts +159 -0
  54. package/src/channel.loaders.ts +50 -0
  55. package/src/channel.runtime.ts +1 -0
  56. package/src/channel.setup.ts +12 -0
  57. package/src/channel.ts +728 -0
  58. package/src/chunk.ts +321 -0
  59. package/src/client.ts +143 -0
  60. package/src/component-custom-id.ts +72 -0
  61. package/src/components-registry.ts +356 -0
  62. package/src/components.builders.ts +410 -0
  63. package/src/components.modal.ts +124 -0
  64. package/src/components.parse.ts +407 -0
  65. package/src/components.ts +54 -0
  66. package/src/components.types.ts +187 -0
  67. package/src/config-schema.ts +6 -0
  68. package/src/config-ui-hints.ts +354 -0
  69. package/src/conversation-identity.ts +58 -0
  70. package/src/delivery-retry.ts +56 -0
  71. package/src/directory-cache.ts +116 -0
  72. package/src/directory-config.ts +58 -0
  73. package/src/directory-live.ts +135 -0
  74. package/src/doctor-contract.ts +477 -0
  75. package/src/doctor-shared.ts +5 -0
  76. package/src/doctor.ts +340 -0
  77. package/src/draft-chunking.ts +43 -0
  78. package/src/draft-stream.ts +162 -0
  79. package/src/error-body.ts +38 -0
  80. package/src/exec-approvals.ts +110 -0
  81. package/src/gateway-logging.ts +67 -0
  82. package/src/group-policy.ts +113 -0
  83. package/src/guilds.ts +29 -0
  84. package/src/inbound-event-delivery.ts +135 -0
  85. package/src/interactive-dispatch.ts +104 -0
  86. package/src/internal/api.commands.ts +51 -0
  87. package/src/internal/api.guild.ts +164 -0
  88. package/src/internal/api.interactions.ts +53 -0
  89. package/src/internal/api.messages.ts +113 -0
  90. package/src/internal/api.reactions.ts +38 -0
  91. package/src/internal/api.ts +61 -0
  92. package/src/internal/api.users.ts +19 -0
  93. package/src/internal/api.webhooks.ts +13 -0
  94. package/src/internal/client.ts +310 -0
  95. package/src/internal/command-deploy.ts +352 -0
  96. package/src/internal/commands.ts +188 -0
  97. package/src/internal/components.base.ts +65 -0
  98. package/src/internal/components.message.ts +279 -0
  99. package/src/internal/components.modal.ts +95 -0
  100. package/src/internal/components.ts +31 -0
  101. package/src/internal/discord.ts +11 -0
  102. package/src/internal/embeds.ts +35 -0
  103. package/src/internal/entity-cache.ts +98 -0
  104. package/src/internal/event-queue.ts +185 -0
  105. package/src/internal/gateway-close-codes.ts +25 -0
  106. package/src/internal/gateway-dispatch.ts +96 -0
  107. package/src/internal/gateway-identify-limiter.ts +26 -0
  108. package/src/internal/gateway-lifecycle.ts +75 -0
  109. package/src/internal/gateway-rate-limit.ts +104 -0
  110. package/src/internal/gateway.ts +479 -0
  111. package/src/internal/interaction-dispatch.ts +162 -0
  112. package/src/internal/interaction-options.ts +98 -0
  113. package/src/internal/interaction-response.ts +53 -0
  114. package/src/internal/interactions.ts +378 -0
  115. package/src/internal/listeners.ts +91 -0
  116. package/src/internal/modal-fields.ts +95 -0
  117. package/src/internal/payload.ts +69 -0
  118. package/src/internal/rest-body.ts +115 -0
  119. package/src/internal/rest-errors.ts +88 -0
  120. package/src/internal/rest-routes.ts +50 -0
  121. package/src/internal/rest-scheduler.ts +557 -0
  122. package/src/internal/rest.ts +322 -0
  123. package/src/internal/schemas.ts +36 -0
  124. package/src/internal/structures.ts +280 -0
  125. package/src/internal/test-builders.test-support.ts +167 -0
  126. package/src/internal/voice.ts +49 -0
  127. package/src/media-detection.ts +28 -0
  128. package/src/mentions.ts +147 -0
  129. package/src/monitor/ack-reactions.ts +70 -0
  130. package/src/monitor/agent-components-auth.ts +7 -0
  131. package/src/monitor/agent-components-context.ts +154 -0
  132. package/src/monitor/agent-components-data.ts +224 -0
  133. package/src/monitor/agent-components-dm-auth.ts +177 -0
  134. package/src/monitor/agent-components-guild-auth.ts +322 -0
  135. package/src/monitor/agent-components-helpers.runtime.ts +3 -0
  136. package/src/monitor/agent-components-helpers.ts +34 -0
  137. package/src/monitor/agent-components-reply.ts +10 -0
  138. package/src/monitor/agent-components.deps.runtime.ts +2 -0
  139. package/src/monitor/agent-components.dispatch.ts +359 -0
  140. package/src/monitor/agent-components.handlers.ts +303 -0
  141. package/src/monitor/agent-components.modal.ts +160 -0
  142. package/src/monitor/agent-components.plugin-interactive.ts +187 -0
  143. package/src/monitor/agent-components.runtime.ts +14 -0
  144. package/src/monitor/agent-components.system-controls.ts +215 -0
  145. package/src/monitor/agent-components.ts +70 -0
  146. package/src/monitor/agent-components.types.ts +58 -0
  147. package/src/monitor/agent-components.wildcard-controls.ts +171 -0
  148. package/src/monitor/allow-list.ts +631 -0
  149. package/src/monitor/auto-presence.ts +356 -0
  150. package/src/monitor/channel-access.ts +102 -0
  151. package/src/monitor/commands.ts +9 -0
  152. package/src/monitor/dm-command-auth.ts +259 -0
  153. package/src/monitor/dm-command-decision.ts +49 -0
  154. package/src/monitor/exec-approvals.ts +161 -0
  155. package/src/monitor/format.ts +45 -0
  156. package/src/monitor/gateway-handle.ts +34 -0
  157. package/src/monitor/gateway-metadata.ts +298 -0
  158. package/src/monitor/gateway-plugin.ts +302 -0
  159. package/src/monitor/gateway-registry.ts +37 -0
  160. package/src/monitor/gateway-supervisor.ts +206 -0
  161. package/src/monitor/inbound-context.ts +95 -0
  162. package/src/monitor/inbound-dedupe.ts +79 -0
  163. package/src/monitor/inbound-job.ts +118 -0
  164. package/src/monitor/listeners.queue.ts +91 -0
  165. package/src/monitor/listeners.reactions.ts +594 -0
  166. package/src/monitor/listeners.ts +150 -0
  167. package/src/monitor/message-channel-info.ts +96 -0
  168. package/src/monitor/message-forwarded.ts +114 -0
  169. package/src/monitor/message-handler.batch-gate.ts +19 -0
  170. package/src/monitor/message-handler.context.ts +492 -0
  171. package/src/monitor/message-handler.dm-preflight.ts +119 -0
  172. package/src/monitor/message-handler.draft-preview.ts +436 -0
  173. package/src/monitor/message-handler.hydration.ts +198 -0
  174. package/src/monitor/message-handler.module-test-helpers.ts +31 -0
  175. package/src/monitor/message-handler.preflight-channel-access.ts +86 -0
  176. package/src/monitor/message-handler.preflight-channel-context.ts +58 -0
  177. package/src/monitor/message-handler.preflight-context.ts +54 -0
  178. package/src/monitor/message-handler.preflight-helpers.ts +164 -0
  179. package/src/monitor/message-handler.preflight-history.ts +23 -0
  180. package/src/monitor/message-handler.preflight-logging.ts +36 -0
  181. package/src/monitor/message-handler.preflight-pluralkit.ts +28 -0
  182. package/src/monitor/message-handler.preflight-runtime.ts +28 -0
  183. package/src/monitor/message-handler.preflight-thread.ts +49 -0
  184. package/src/monitor/message-handler.preflight.ts +822 -0
  185. package/src/monitor/message-handler.preflight.types.ts +115 -0
  186. package/src/monitor/message-handler.process.ts +1033 -0
  187. package/src/monitor/message-handler.routing-preflight.ts +112 -0
  188. package/src/monitor/message-handler.ts +309 -0
  189. package/src/monitor/message-media.ts +536 -0
  190. package/src/monitor/message-run-queue.ts +101 -0
  191. package/src/monitor/message-text.ts +171 -0
  192. package/src/monitor/message-utils.ts +34 -0
  193. package/src/monitor/model-picker-preferences.ts +184 -0
  194. package/src/monitor/model-picker.state.ts +364 -0
  195. package/src/monitor/model-picker.test-utils.ts +26 -0
  196. package/src/monitor/model-picker.ts +38 -0
  197. package/src/monitor/model-picker.view.ts +722 -0
  198. package/src/monitor/native-command-agent-reply.ts +125 -0
  199. package/src/monitor/native-command-arg-ui.ts +233 -0
  200. package/src/monitor/native-command-auth.ts +309 -0
  201. package/src/monitor/native-command-bypass.ts +13 -0
  202. package/src/monitor/native-command-context.ts +109 -0
  203. package/src/monitor/native-command-dispatch.ts +35 -0
  204. package/src/monitor/native-command-model-picker-apply.ts +209 -0
  205. package/src/monitor/native-command-model-picker-interaction.ts +516 -0
  206. package/src/monitor/native-command-model-picker-ui.ts +357 -0
  207. package/src/monitor/native-command-reply.ts +185 -0
  208. package/src/monitor/native-command-route.ts +91 -0
  209. package/src/monitor/native-command-status.ts +76 -0
  210. package/src/monitor/native-command-ui.ts +26 -0
  211. package/src/monitor/native-command-ui.types.ts +20 -0
  212. package/src/monitor/native-command.args.ts +45 -0
  213. package/src/monitor/native-command.options.ts +153 -0
  214. package/src/monitor/native-command.runtime.ts +51 -0
  215. package/src/monitor/native-command.ts +747 -0
  216. package/src/monitor/native-command.types.ts +9 -0
  217. package/src/monitor/native-interaction-channel-context.ts +50 -0
  218. package/src/monitor/preflight-audio.runtime.ts +9 -0
  219. package/src/monitor/preflight-audio.ts +130 -0
  220. package/src/monitor/presence-cache.ts +61 -0
  221. package/src/monitor/presence.ts +50 -0
  222. package/src/monitor/provider-session.runtime.ts +12 -0
  223. package/src/monitor/provider.acp.ts +89 -0
  224. package/src/monitor/provider.allowlist.ts +398 -0
  225. package/src/monitor/provider.cleanup.ts +41 -0
  226. package/src/monitor/provider.commands.ts +129 -0
  227. package/src/monitor/provider.config-log.ts +45 -0
  228. package/src/monitor/provider.deploy-errors.ts +362 -0
  229. package/src/monitor/provider.deploy.ts +221 -0
  230. package/src/monitor/provider.interactions.ts +160 -0
  231. package/src/monitor/provider.lifecycle.ts +562 -0
  232. package/src/monitor/provider.runtime.ts +1 -0
  233. package/src/monitor/provider.startup-log.ts +32 -0
  234. package/src/monitor/provider.startup.ts +323 -0
  235. package/src/monitor/provider.ts +688 -0
  236. package/src/monitor/reply-context.ts +64 -0
  237. package/src/monitor/reply-delivery.ts +216 -0
  238. package/src/monitor/reply-safety.ts +96 -0
  239. package/src/monitor/rest-fetch.ts +97 -0
  240. package/src/monitor/route-resolution.ts +140 -0
  241. package/src/monitor/sender-identity.ts +81 -0
  242. package/src/monitor/startup-status.ts +10 -0
  243. package/src/monitor/status.ts +22 -0
  244. package/src/monitor/system-events.ts +55 -0
  245. package/src/monitor/thread-bindings.config.ts +35 -0
  246. package/src/monitor/thread-bindings.discord-api.ts +310 -0
  247. package/src/monitor/thread-bindings.lifecycle.ts +354 -0
  248. package/src/monitor/thread-bindings.manager.ts +554 -0
  249. package/src/monitor/thread-bindings.messages.ts +6 -0
  250. package/src/monitor/thread-bindings.persona.ts +25 -0
  251. package/src/monitor/thread-bindings.session-adapter.ts +229 -0
  252. package/src/monitor/thread-bindings.session-shared.ts +59 -0
  253. package/src/monitor/thread-bindings.session-updates.ts +35 -0
  254. package/src/monitor/thread-bindings.state.ts +540 -0
  255. package/src/monitor/thread-bindings.ts +48 -0
  256. package/src/monitor/thread-bindings.types.ts +83 -0
  257. package/src/monitor/thread-channel-context.ts +112 -0
  258. package/src/monitor/thread-session-close.ts +63 -0
  259. package/src/monitor/thread-title.ts +181 -0
  260. package/src/monitor/threading.auto-thread.ts +287 -0
  261. package/src/monitor/threading.cache.ts +45 -0
  262. package/src/monitor/threading.starter.ts +288 -0
  263. package/src/monitor/threading.ts +20 -0
  264. package/src/monitor/threading.types.ts +102 -0
  265. package/src/monitor/timeouts.ts +84 -0
  266. package/src/monitor/typing.ts +17 -0
  267. package/src/monitor.gateway.ts +75 -0
  268. package/src/monitor.ts +28 -0
  269. package/src/network-config.ts +79 -0
  270. package/src/normalize.ts +86 -0
  271. package/src/outbound-adapter.ts +327 -0
  272. package/src/outbound-approval.ts +29 -0
  273. package/src/outbound-components.ts +86 -0
  274. package/src/outbound-payload.ts +208 -0
  275. package/src/outbound-send-context.ts +92 -0
  276. package/src/outbound-session-route.ts +72 -0
  277. package/src/pluralkit.ts +58 -0
  278. package/src/preview-streaming.ts +18 -0
  279. package/src/probe.runtime.ts +1 -0
  280. package/src/probe.ts +237 -0
  281. package/src/proxy-fetch.ts +92 -0
  282. package/src/proxy-request-client.ts +21 -0
  283. package/src/recipient-resolution.ts +39 -0
  284. package/src/resolve-allowlist-common.ts +39 -0
  285. package/src/resolve-channels.ts +369 -0
  286. package/src/resolve-users.ts +184 -0
  287. package/src/retry.ts +98 -0
  288. package/src/runtime-api.ts +64 -0
  289. package/src/runtime-config.ts +16 -0
  290. package/src/runtime.ts +23 -0
  291. package/src/secret-config-contract.ts +140 -0
  292. package/src/security-audit.runtime.ts +1 -0
  293. package/src/security-audit.ts +208 -0
  294. package/src/security-contract.ts +47 -0
  295. package/src/security-doctor.ts +20 -0
  296. package/src/security.ts +60 -0
  297. package/src/send-target-parsing.ts +14 -0
  298. package/src/send.channels.ts +139 -0
  299. package/src/send.components.ts +391 -0
  300. package/src/send.emojis-stickers.ts +57 -0
  301. package/src/send.guild.ts +170 -0
  302. package/src/send.message-request.ts +112 -0
  303. package/src/send.messages.ts +229 -0
  304. package/src/send.outbound.ts +459 -0
  305. package/src/send.permissions.ts +283 -0
  306. package/src/send.reactions.ts +155 -0
  307. package/src/send.receipt.ts +69 -0
  308. package/src/send.shared.ts +469 -0
  309. package/src/send.ts +82 -0
  310. package/src/send.types.ts +191 -0
  311. package/src/send.typing.ts +9 -0
  312. package/src/send.voice.ts +140 -0
  313. package/src/send.webhook.ts +137 -0
  314. package/src/session-contract.ts +3 -0
  315. package/src/session-key-normalization.ts +47 -0
  316. package/src/setup-account-state.ts +144 -0
  317. package/src/setup-adapter.ts +14 -0
  318. package/src/setup-core.ts +215 -0
  319. package/src/setup-runtime-helpers.ts +10 -0
  320. package/src/setup-surface.ts +132 -0
  321. package/src/shared-interactive.ts +167 -0
  322. package/src/shared.ts +197 -0
  323. package/src/status-issues.ts +201 -0
  324. package/src/subagent-hooks.ts +232 -0
  325. package/src/target-parsing.ts +70 -0
  326. package/src/target-resolver.ts +129 -0
  327. package/src/targets.ts +12 -0
  328. package/src/token.ts +107 -0
  329. package/src/ui-colors.ts +27 -0
  330. package/src/ui.ts +20 -0
  331. package/src/voice/access.ts +126 -0
  332. package/src/voice/audio.ts +249 -0
  333. package/src/voice/capture-state.ts +120 -0
  334. package/src/voice/command.ts +284 -0
  335. package/src/voice/config.ts +8 -0
  336. package/src/voice/ingress.ts +164 -0
  337. package/src/voice/manager.runtime.ts +14 -0
  338. package/src/voice/manager.ts +1155 -0
  339. package/src/voice/prompt.ts +22 -0
  340. package/src/voice/realtime.ts +1370 -0
  341. package/src/voice/receive-recovery.ts +159 -0
  342. package/src/voice/sanitize.ts +29 -0
  343. package/src/voice/sdk-runtime.ts +14 -0
  344. package/src/voice/segment.ts +160 -0
  345. package/src/voice/session.ts +81 -0
  346. package/src/voice/speaker-context.ts +127 -0
  347. package/src/voice/tts.ts +151 -0
  348. package/src/voice-message.ts +474 -0
  349. package/subagent-hooks-api.ts +27 -0
  350. package/test-api.ts +4 -0
  351. package/thread-binding-api.ts +1 -0
  352. package/timeouts.ts +6 -0
  353. package/tsconfig.json +16 -0
@@ -0,0 +1,125 @@
1
+ import { resolveHumanDelayConfig } from "autobot/plugin-sdk/agent-runtime";
2
+ import { createChannelMessageReplyPipeline } from "autobot/plugin-sdk/channel-message";
3
+ import { resolveChannelStreamingBlockEnabled } from "autobot/plugin-sdk/channel-streaming";
4
+ import type { AutoBotConfig } from "autobot/plugin-sdk/config-contracts";
5
+ import { getAgentScopedMediaLocalRoots } from "autobot/plugin-sdk/media-runtime";
6
+ import { resolveChunkMode, resolveTextChunkLimit } from "autobot/plugin-sdk/reply-chunking";
7
+ import type { createSubsystemLogger } from "autobot/plugin-sdk/runtime-env";
8
+ import { logVerbose } from "autobot/plugin-sdk/runtime-env";
9
+ import { resolveDiscordMaxLinesPerMessage } from "../accounts.js";
10
+ import type {
11
+ ButtonInteraction,
12
+ CommandInteraction,
13
+ StringSelectMenuInteraction,
14
+ } from "../internal/discord.js";
15
+ import type { DiscordChannelConfigResolved } from "./allow-list.js";
16
+ import type { buildDiscordNativeCommandContext } from "./native-command-context.js";
17
+ import {
18
+ DISCORD_EMPTY_VISIBLE_REPLY_WARNING,
19
+ deliverDiscordInteractionReply,
20
+ isDiscordUnknownInteraction,
21
+ safeDiscordInteractionCall,
22
+ } from "./native-command-reply.js";
23
+ import { nativeCommandRuntime } from "./native-command.runtime.js";
24
+ import type { DiscordConfig } from "./native-command.types.js";
25
+
26
+ type NativeCommandEffectiveRoute = {
27
+ accountId: string;
28
+ agentId: string;
29
+ };
30
+
31
+ export async function dispatchDiscordNativeAgentReply(params: {
32
+ cfg: AutoBotConfig;
33
+ discordConfig: DiscordConfig;
34
+ accountId: string;
35
+ interaction: CommandInteraction | ButtonInteraction | StringSelectMenuInteraction;
36
+ ctxPayload: ReturnType<typeof buildDiscordNativeCommandContext>;
37
+ effectiveRoute: NativeCommandEffectiveRoute;
38
+ channelConfig: DiscordChannelConfigResolved | null;
39
+ mediaLocalRoots: ReturnType<typeof getAgentScopedMediaLocalRoots>;
40
+ preferFollowUp: boolean;
41
+ responseEphemeral?: boolean;
42
+ suppressReplies?: boolean;
43
+ log: ReturnType<typeof createSubsystemLogger>;
44
+ }): Promise<void> {
45
+ const { onModelSelected, ...replyPipeline } = createChannelMessageReplyPipeline({
46
+ cfg: params.cfg,
47
+ agentId: params.effectiveRoute.agentId,
48
+ channel: "discord",
49
+ accountId: params.effectiveRoute.accountId,
50
+ });
51
+ const blockStreamingEnabled = resolveChannelStreamingBlockEnabled(params.discordConfig);
52
+
53
+ let didReply = false;
54
+ const dispatchResult = await nativeCommandRuntime.dispatchReplyWithDispatcher({
55
+ ctx: params.ctxPayload,
56
+ cfg: params.cfg,
57
+ dispatcherOptions: {
58
+ ...replyPipeline,
59
+ humanDelay: resolveHumanDelayConfig(params.cfg, params.effectiveRoute.agentId),
60
+ deliver: async (payload) => {
61
+ if (params.suppressReplies) {
62
+ return;
63
+ }
64
+ try {
65
+ await deliverDiscordInteractionReply({
66
+ interaction: params.interaction,
67
+ payload,
68
+ mediaLocalRoots: params.mediaLocalRoots,
69
+ textLimit: resolveTextChunkLimit(params.cfg, "discord", params.accountId, {
70
+ fallbackLimit: 2000,
71
+ }),
72
+ maxLinesPerMessage: resolveDiscordMaxLinesPerMessage({
73
+ cfg: params.cfg,
74
+ discordConfig: params.discordConfig,
75
+ accountId: params.accountId,
76
+ }),
77
+ preferFollowUp: params.preferFollowUp || didReply,
78
+ responseEphemeral: params.responseEphemeral,
79
+ chunkMode: resolveChunkMode(params.cfg, "discord", params.accountId),
80
+ });
81
+ } catch (error) {
82
+ if (isDiscordUnknownInteraction(error)) {
83
+ logVerbose("discord: interaction reply skipped (interaction expired)");
84
+ return;
85
+ }
86
+ throw error;
87
+ }
88
+ didReply = true;
89
+ },
90
+ onError: (err, info) => {
91
+ const message = err instanceof Error ? (err.stack ?? err.message) : String(err);
92
+ params.log.error(`discord slash ${info.kind} reply failed: ${message}`);
93
+ },
94
+ },
95
+ replyOptions: {
96
+ skillFilter: params.channelConfig?.skills,
97
+ disableBlockStreaming:
98
+ typeof blockStreamingEnabled === "boolean" ? !blockStreamingEnabled : undefined,
99
+ onModelSelected,
100
+ },
101
+ });
102
+
103
+ if (
104
+ params.suppressReplies ||
105
+ didReply ||
106
+ dispatchResult.queuedFinal ||
107
+ dispatchResult.counts.final !== 0 ||
108
+ dispatchResult.counts.block !== 0 ||
109
+ dispatchResult.counts.tool !== 0
110
+ ) {
111
+ return;
112
+ }
113
+
114
+ await safeDiscordInteractionCall("interaction empty fallback", async () => {
115
+ const payload = {
116
+ content: DISCORD_EMPTY_VISIBLE_REPLY_WARNING,
117
+ ephemeral: true,
118
+ };
119
+ if (params.preferFollowUp) {
120
+ await params.interaction.followUp(payload);
121
+ return;
122
+ }
123
+ await params.interaction.reply(payload);
124
+ });
125
+ }
@@ -0,0 +1,233 @@
1
+ import { ButtonStyle } from "discord-api-types/v10";
2
+ import {
3
+ buildCommandTextFromArgs,
4
+ findCommandByNativeName,
5
+ formatCommandArgMenuTitle,
6
+ listChatCommands,
7
+ serializeCommandArgs,
8
+ type ChatCommandDefinition,
9
+ type CommandArgDefinition,
10
+ type CommandArgValues,
11
+ type CommandArgs,
12
+ } from "autobot/plugin-sdk/command-auth-native";
13
+ import { chunkItems } from "autobot/plugin-sdk/text-chunking";
14
+ import {
15
+ Button,
16
+ Row,
17
+ type ButtonInteraction,
18
+ type CommandInteraction,
19
+ type ComponentData,
20
+ } from "../internal/discord.js";
21
+ import { resolveDiscordSlashCommandConfig } from "./commands.js";
22
+ import type { DispatchDiscordCommandInteraction } from "./native-command-dispatch.js";
23
+ import type {
24
+ DiscordCommandArgContext,
25
+ SafeDiscordInteractionCall,
26
+ } from "./native-command-ui.types.js";
27
+
28
+ const DISCORD_COMMAND_ARG_CUSTOM_ID_KEY = "cmdarg";
29
+
30
+ function createCommandArgsWithValue(params: { argName: string; value: string }): CommandArgs {
31
+ const values: CommandArgValues = { [params.argName]: params.value };
32
+ return { values };
33
+ }
34
+
35
+ function encodeDiscordCommandArgValue(value: string): string {
36
+ return encodeURIComponent(value);
37
+ }
38
+
39
+ function decodeDiscordCommandArgValue(value: string): string {
40
+ try {
41
+ return decodeURIComponent(value);
42
+ } catch {
43
+ return value;
44
+ }
45
+ }
46
+
47
+ export function buildDiscordCommandArgCustomId(params: {
48
+ command: string;
49
+ arg: string;
50
+ value: string;
51
+ userId: string;
52
+ }): string {
53
+ return [
54
+ `${DISCORD_COMMAND_ARG_CUSTOM_ID_KEY}:command=${encodeDiscordCommandArgValue(params.command)}`,
55
+ `arg=${encodeDiscordCommandArgValue(params.arg)}`,
56
+ `value=${encodeDiscordCommandArgValue(params.value)}`,
57
+ `user=${encodeDiscordCommandArgValue(params.userId)}`,
58
+ ].join(";");
59
+ }
60
+
61
+ function parseDiscordCommandArgData(
62
+ data: ComponentData,
63
+ ): { command: string; arg: string; value: string; userId: string } | null {
64
+ if (!data || typeof data !== "object") {
65
+ return null;
66
+ }
67
+ const coerce = (value: unknown) =>
68
+ typeof value === "string" || typeof value === "number" ? String(value) : "";
69
+ const rawCommand = coerce(data.command);
70
+ const rawArg = coerce(data.arg);
71
+ const rawValue = coerce(data.value);
72
+ const rawUser = coerce(data.user);
73
+ if (!rawCommand || !rawArg || !rawValue || !rawUser) {
74
+ return null;
75
+ }
76
+ return {
77
+ command: decodeDiscordCommandArgValue(rawCommand),
78
+ arg: decodeDiscordCommandArgValue(rawArg),
79
+ value: decodeDiscordCommandArgValue(rawValue),
80
+ userId: decodeDiscordCommandArgValue(rawUser),
81
+ };
82
+ }
83
+
84
+ export async function handleDiscordCommandArgInteraction(params: {
85
+ interaction: ButtonInteraction;
86
+ data: ComponentData;
87
+ ctx: DiscordCommandArgContext;
88
+ safeInteractionCall: SafeDiscordInteractionCall;
89
+ dispatchCommandInteraction: DispatchDiscordCommandInteraction;
90
+ }) {
91
+ const { interaction, data, ctx } = params;
92
+ const clearWithMessage = async (content: string) =>
93
+ await params.safeInteractionCall("command arg update", () =>
94
+ interaction.update({ content, components: [] }),
95
+ );
96
+ const parsed = parseDiscordCommandArgData(data);
97
+ if (!parsed) {
98
+ await clearWithMessage("Sorry, that selection is no longer available.");
99
+ return;
100
+ }
101
+ if (interaction.user?.id && interaction.user.id !== parsed.userId) {
102
+ await params.safeInteractionCall("command arg ack", () => interaction.acknowledge());
103
+ return;
104
+ }
105
+ const commandDefinition =
106
+ findCommandByNativeName(parsed.command, "discord") ??
107
+ listChatCommands().find((entry) => entry.key === parsed.command);
108
+ if (!commandDefinition) {
109
+ await clearWithMessage("Sorry, that command is no longer available.");
110
+ return;
111
+ }
112
+ const argUpdateResult = await clearWithMessage(`✅ Selected ${parsed.value}.`);
113
+ if (argUpdateResult === null) {
114
+ return;
115
+ }
116
+ const commandArgs = createCommandArgsWithValue({
117
+ argName: parsed.arg,
118
+ value: parsed.value,
119
+ });
120
+ const commandArgsWithRaw: CommandArgs = {
121
+ ...commandArgs,
122
+ raw: serializeCommandArgs(commandDefinition, commandArgs),
123
+ };
124
+ const prompt = buildCommandTextFromArgs(commandDefinition, commandArgsWithRaw);
125
+ await params.dispatchCommandInteraction({
126
+ interaction,
127
+ prompt,
128
+ command: commandDefinition,
129
+ commandArgs: commandArgsWithRaw,
130
+ cfg: ctx.cfg,
131
+ discordConfig: ctx.discordConfig,
132
+ accountId: ctx.accountId,
133
+ sessionPrefix: ctx.sessionPrefix,
134
+ preferFollowUp: true,
135
+ threadBindings: ctx.threadBindings,
136
+ responseEphemeral: resolveDiscordSlashCommandConfig(ctx.discordConfig?.slashCommand).ephemeral,
137
+ });
138
+ }
139
+
140
+ type DiscordCommandArgButtonParams = {
141
+ ctx: DiscordCommandArgContext;
142
+ safeInteractionCall: SafeDiscordInteractionCall;
143
+ dispatchCommandInteraction: DispatchDiscordCommandInteraction;
144
+ };
145
+
146
+ async function runDiscordCommandArgButton(
147
+ params: DiscordCommandArgButtonParams & {
148
+ interaction: ButtonInteraction;
149
+ data: ComponentData;
150
+ },
151
+ ) {
152
+ await handleDiscordCommandArgInteraction(params);
153
+ }
154
+
155
+ class DiscordCommandArgButton extends Button {
156
+ label: string;
157
+ customId: string;
158
+ override style = ButtonStyle.Secondary;
159
+
160
+ constructor(
161
+ params: {
162
+ label: string;
163
+ customId: string;
164
+ } & DiscordCommandArgButtonParams,
165
+ ) {
166
+ super();
167
+ this.label = params.label;
168
+ this.customId = params.customId;
169
+ this.params = params;
170
+ }
171
+
172
+ private params: DiscordCommandArgButtonParams;
173
+
174
+ override async run(interaction: ButtonInteraction, data: ComponentData) {
175
+ await runDiscordCommandArgButton({ ...this.params, interaction, data });
176
+ }
177
+ }
178
+
179
+ export function buildDiscordCommandArgMenu(params: {
180
+ command: ChatCommandDefinition;
181
+ menu: {
182
+ arg: CommandArgDefinition;
183
+ choices: Array<{ value: string; label: string }>;
184
+ title?: string;
185
+ };
186
+ interaction: CommandInteraction;
187
+ ctx: DiscordCommandArgContext;
188
+ safeInteractionCall: SafeDiscordInteractionCall;
189
+ dispatchCommandInteraction: DispatchDiscordCommandInteraction;
190
+ }): { content: string; components: Row<Button>[] } {
191
+ const { command, menu, interaction } = params;
192
+ const commandLabel = command.nativeName ?? command.key;
193
+ const userId = interaction.user?.id ?? "";
194
+ const rows = chunkItems(menu.choices, 4).map((choices) => {
195
+ const buttons = choices.map(
196
+ (choice) =>
197
+ new DiscordCommandArgButton({
198
+ label: choice.label,
199
+ customId: buildDiscordCommandArgCustomId({
200
+ command: commandLabel,
201
+ arg: menu.arg.name,
202
+ value: choice.value,
203
+ userId,
204
+ }),
205
+ ctx: params.ctx,
206
+ safeInteractionCall: params.safeInteractionCall,
207
+ dispatchCommandInteraction: params.dispatchCommandInteraction,
208
+ }),
209
+ );
210
+ return new Row(buttons);
211
+ });
212
+ const content = formatCommandArgMenuTitle({ command, menu });
213
+ return { content, components: rows };
214
+ }
215
+
216
+ class DiscordCommandArgFallbackButton extends Button {
217
+ label = "cmdarg";
218
+ customId = "cmdarg:seed=1";
219
+
220
+ constructor(private readonly params: DiscordCommandArgButtonParams) {
221
+ super();
222
+ }
223
+
224
+ override async run(interaction: ButtonInteraction, data: ComponentData) {
225
+ await runDiscordCommandArgButton({ ...this.params, interaction, data });
226
+ }
227
+ }
228
+
229
+ export function createDiscordCommandArgFallbackButton(
230
+ params: DiscordCommandArgButtonParams,
231
+ ): Button {
232
+ return new DiscordCommandArgFallbackButton(params);
233
+ }
@@ -0,0 +1,309 @@
1
+ import { resolveCommandAuthorizedFromAuthorizers } from "autobot/plugin-sdk/command-auth-native";
2
+ import type { AutoBotConfig } from "autobot/plugin-sdk/config-contracts";
3
+ import { isDangerousNameMatchingEnabled } from "autobot/plugin-sdk/dangerous-name-runtime";
4
+ import { resolveOpenProviderRuntimeGroupPolicy } from "autobot/plugin-sdk/runtime-group-policy";
5
+ import { normalizeOptionalString } from "autobot/plugin-sdk/string-coerce-runtime";
6
+ import { resolveDiscordAccountAllowFrom, resolveDiscordAccountDmPolicy } from "../accounts.js";
7
+ import type { AutocompleteInteraction } from "../internal/discord.js";
8
+ import {
9
+ normalizeDiscordAllowList,
10
+ resolveDiscordAllowListMatch,
11
+ resolveDiscordChannelConfigWithFallback,
12
+ resolveDiscordChannelPolicyCommandAuthorizer,
13
+ resolveDiscordGuildEntry,
14
+ resolveDiscordMemberAccessState,
15
+ resolveDiscordOwnerAccess,
16
+ resolveGroupDmAllow,
17
+ } from "./allow-list.js";
18
+ import { resolveDiscordDmCommandAccess } from "./dm-command-auth.js";
19
+ import type { DiscordConfig } from "./native-command.types.js";
20
+ import { resolveDiscordNativeInteractionChannelContext } from "./native-interaction-channel-context.js";
21
+ import { resolveDiscordSenderIdentity } from "./sender-identity.js";
22
+
23
+ export function resolveDiscordNativeCommandAllowlistAccess(params: {
24
+ cfg: AutoBotConfig;
25
+ accountId?: string | null;
26
+ sender: { id: string; name?: string; tag?: string };
27
+ chatType: "direct" | "group" | "thread" | "channel";
28
+ conversationId?: string;
29
+ guildId?: string | null;
30
+ }) {
31
+ const commandsAllowFrom = params.cfg.commands?.allowFrom;
32
+ if (!commandsAllowFrom || typeof commandsAllowFrom !== "object") {
33
+ return { configured: false, allowed: false } as const;
34
+ }
35
+ const rawAllowList = Array.isArray(commandsAllowFrom.discord)
36
+ ? commandsAllowFrom.discord
37
+ : commandsAllowFrom["*"];
38
+ if (!Array.isArray(rawAllowList)) {
39
+ return { configured: false, allowed: false } as const;
40
+ }
41
+ const guildId = normalizeOptionalString(params.guildId);
42
+ if (guildId) {
43
+ for (const entry of rawAllowList) {
44
+ const text = normalizeOptionalString(String(entry)) ?? "";
45
+ if (text.startsWith("guild:") && text.slice("guild:".length) === guildId) {
46
+ return { configured: true, allowed: true } as const;
47
+ }
48
+ }
49
+ }
50
+ const allowList = normalizeDiscordAllowList(rawAllowList.map(String), [
51
+ "discord:",
52
+ "user:",
53
+ "pk:",
54
+ ]);
55
+ if (!allowList) {
56
+ return { configured: true, allowed: false } as const;
57
+ }
58
+ const match = resolveDiscordAllowListMatch({
59
+ allowList,
60
+ candidate: params.sender,
61
+ allowNameMatching: false,
62
+ });
63
+ return { configured: true, allowed: match.allowed } as const;
64
+ }
65
+
66
+ export async function resolveDiscordGuildNativeCommandAuthorized(params: {
67
+ cfg: AutoBotConfig;
68
+ accountId: string;
69
+ discordConfig: DiscordConfig;
70
+ useAccessGroups: boolean;
71
+ commandsAllowFromAccess: ReturnType<typeof resolveDiscordNativeCommandAllowlistAccess>;
72
+ guildInfo?: ReturnType<typeof resolveDiscordGuildEntry> | null;
73
+ channelConfig?: ReturnType<typeof resolveDiscordChannelConfigWithFallback> | null;
74
+ memberRoleIds: string[];
75
+ sender: { id: string; name?: string; tag?: string };
76
+ allowNameMatching: boolean;
77
+ ownerAllowListConfigured: boolean;
78
+ ownerAllowed: boolean;
79
+ }) {
80
+ const { groupPolicy } = resolveOpenProviderRuntimeGroupPolicy({
81
+ providerConfigPresent: params.cfg.channels?.discord !== undefined,
82
+ groupPolicy: params.discordConfig?.groupPolicy,
83
+ defaultGroupPolicy: params.cfg.channels?.defaults?.groupPolicy,
84
+ });
85
+ const policyAuthorizer = resolveDiscordChannelPolicyCommandAuthorizer({
86
+ groupPolicy,
87
+ guildInfo: params.guildInfo,
88
+ channelConfig: params.channelConfig,
89
+ });
90
+ if (!policyAuthorizer.allowed) {
91
+ return false;
92
+ }
93
+ const { hasAccessRestrictions, memberAllowed } = resolveDiscordMemberAccessState({
94
+ channelConfig: params.channelConfig,
95
+ guildInfo: params.guildInfo,
96
+ memberRoleIds: params.memberRoleIds,
97
+ sender: params.sender,
98
+ allowNameMatching: params.allowNameMatching,
99
+ });
100
+ const commandAllowlistAuthorizer = {
101
+ configured: params.commandsAllowFromAccess.configured,
102
+ allowed: params.commandsAllowFromAccess.allowed,
103
+ };
104
+ const ownerAuthorizer = {
105
+ configured: params.ownerAllowListConfigured,
106
+ allowed: params.ownerAllowed,
107
+ };
108
+ const memberAuthorizer = {
109
+ configured: hasAccessRestrictions,
110
+ allowed: memberAllowed,
111
+ };
112
+ const hasStricterAccessRestrictions = ownerAuthorizer.configured || memberAuthorizer.configured;
113
+ const policyFallbackAuthorizer = {
114
+ configured: policyAuthorizer.configured && !hasStricterAccessRestrictions,
115
+ allowed: policyAuthorizer.allowed,
116
+ };
117
+ const fallbackAuthorizers = [policyFallbackAuthorizer, ownerAuthorizer, memberAuthorizer];
118
+ const authorizers = params.commandsAllowFromAccess.configured
119
+ ? [commandAllowlistAuthorizer]
120
+ : fallbackAuthorizers;
121
+ return resolveCommandAuthorizedFromAuthorizers({
122
+ useAccessGroups: params.useAccessGroups,
123
+ authorizers,
124
+ modeWhenAccessGroupsOff: "configured",
125
+ });
126
+ }
127
+
128
+ export function resolveDiscordNativeGroupDmAccess(params: {
129
+ isGroupDm: boolean;
130
+ groupEnabled?: boolean;
131
+ groupChannels?: string[];
132
+ channelId: string;
133
+ channelName?: string;
134
+ channelSlug: string;
135
+ }): { allowed: true } | { allowed: false; reason: "disabled" | "not-allowlisted" } {
136
+ if (!params.isGroupDm) {
137
+ return { allowed: true };
138
+ }
139
+ if (params.groupEnabled === false) {
140
+ return { allowed: false, reason: "disabled" };
141
+ }
142
+ if (
143
+ !resolveGroupDmAllow({
144
+ channels: params.groupChannels,
145
+ channelId: params.channelId,
146
+ channelName: params.channelName,
147
+ channelSlug: params.channelSlug,
148
+ })
149
+ ) {
150
+ return { allowed: false, reason: "not-allowlisted" };
151
+ }
152
+ return { allowed: true };
153
+ }
154
+
155
+ export async function resolveDiscordNativeAutocompleteAuthorized(params: {
156
+ interaction: AutocompleteInteraction;
157
+ cfg: AutoBotConfig;
158
+ discordConfig: DiscordConfig;
159
+ accountId: string;
160
+ }): Promise<boolean> {
161
+ const { interaction, cfg, discordConfig, accountId } = params;
162
+ const user = interaction.user;
163
+ if (!user) {
164
+ return false;
165
+ }
166
+ const sender = resolveDiscordSenderIdentity({ author: user, pluralkitInfo: null });
167
+ const {
168
+ isDirectMessage,
169
+ isGroupDm,
170
+ isThreadChannel,
171
+ channelName,
172
+ channelSlug,
173
+ rawChannelId,
174
+ threadParentId,
175
+ threadParentName,
176
+ threadParentSlug,
177
+ } = await resolveDiscordNativeInteractionChannelContext({
178
+ channel: interaction.channel,
179
+ client: interaction.client,
180
+ hasGuild: Boolean(interaction.guild),
181
+ channelIdFallback: "",
182
+ });
183
+ const memberRoleIds = Array.isArray(interaction.rawData.member?.roles)
184
+ ? interaction.rawData.member.roles.map((roleId: string) => roleId)
185
+ : [];
186
+ const allowNameMatching = isDangerousNameMatchingEnabled(discordConfig);
187
+ const useAccessGroups = cfg.commands?.useAccessGroups !== false;
188
+ const configuredDmAllowFrom =
189
+ resolveDiscordAccountAllowFrom({
190
+ cfg,
191
+ accountId,
192
+ }) ?? [];
193
+ const { ownerAllowList, ownerAllowed: ownerOk } = resolveDiscordOwnerAccess({
194
+ allowFrom: configuredDmAllowFrom,
195
+ sender: {
196
+ id: sender.id,
197
+ name: sender.name,
198
+ tag: sender.tag,
199
+ },
200
+ allowNameMatching,
201
+ });
202
+ const commandsAllowFromAccess = resolveDiscordNativeCommandAllowlistAccess({
203
+ cfg,
204
+ accountId,
205
+ sender: {
206
+ id: sender.id,
207
+ name: sender.name,
208
+ tag: sender.tag,
209
+ },
210
+ chatType: isDirectMessage
211
+ ? "direct"
212
+ : isThreadChannel
213
+ ? "thread"
214
+ : interaction.guild
215
+ ? "channel"
216
+ : "group",
217
+ conversationId: rawChannelId || undefined,
218
+ guildId: interaction.guild?.id,
219
+ });
220
+ const guildInfo = resolveDiscordGuildEntry({
221
+ guild: interaction.guild ?? undefined,
222
+ guildId: interaction.guild?.id ?? undefined,
223
+ guildEntries: discordConfig?.guilds,
224
+ });
225
+ const channelConfig = interaction.guild
226
+ ? resolveDiscordChannelConfigWithFallback({
227
+ guildInfo,
228
+ channelId: rawChannelId,
229
+ channelName,
230
+ channelSlug,
231
+ parentId: threadParentId,
232
+ parentName: threadParentName,
233
+ parentSlug: threadParentSlug,
234
+ scope: isThreadChannel ? "thread" : "channel",
235
+ })
236
+ : null;
237
+ if (channelConfig?.enabled === false) {
238
+ return false;
239
+ }
240
+ if (interaction.guild && channelConfig?.allowed === false) {
241
+ return false;
242
+ }
243
+ if (useAccessGroups && interaction.guild) {
244
+ const { groupPolicy } = resolveOpenProviderRuntimeGroupPolicy({
245
+ providerConfigPresent: cfg.channels?.discord !== undefined,
246
+ groupPolicy: discordConfig?.groupPolicy,
247
+ defaultGroupPolicy: cfg.channels?.defaults?.groupPolicy,
248
+ });
249
+ const policyAuthorizer = resolveDiscordChannelPolicyCommandAuthorizer({
250
+ groupPolicy,
251
+ guildInfo,
252
+ channelConfig,
253
+ });
254
+ if (!policyAuthorizer.allowed) {
255
+ return false;
256
+ }
257
+ }
258
+ const dmEnabled = discordConfig?.dm?.enabled ?? true;
259
+ const dmPolicy = resolveDiscordAccountDmPolicy({ cfg, accountId }) ?? "pairing";
260
+ if (isDirectMessage) {
261
+ if (!dmEnabled || dmPolicy === "disabled") {
262
+ return false;
263
+ }
264
+ const dmAccess = await resolveDiscordDmCommandAccess({
265
+ accountId,
266
+ dmPolicy,
267
+ configuredAllowFrom: configuredDmAllowFrom,
268
+ sender: {
269
+ id: sender.id,
270
+ name: sender.name,
271
+ tag: sender.tag,
272
+ },
273
+ allowNameMatching,
274
+ cfg,
275
+ rest: interaction.client.rest,
276
+ });
277
+ if (dmAccess.senderAccess.decision !== "allow") {
278
+ return false;
279
+ }
280
+ }
281
+ const groupDmAccess = resolveDiscordNativeGroupDmAccess({
282
+ isGroupDm,
283
+ groupEnabled: discordConfig?.dm?.groupEnabled,
284
+ groupChannels: discordConfig?.dm?.groupChannels,
285
+ channelId: rawChannelId,
286
+ channelName,
287
+ channelSlug,
288
+ });
289
+ if (!groupDmAccess.allowed) {
290
+ return false;
291
+ }
292
+ if (!isDirectMessage) {
293
+ return resolveDiscordGuildNativeCommandAuthorized({
294
+ cfg,
295
+ accountId,
296
+ discordConfig,
297
+ useAccessGroups,
298
+ commandsAllowFromAccess,
299
+ guildInfo,
300
+ channelConfig,
301
+ memberRoleIds,
302
+ sender,
303
+ allowNameMatching,
304
+ ownerAllowListConfigured: ownerAllowList != null,
305
+ ownerAllowed: ownerOk,
306
+ });
307
+ }
308
+ return true;
309
+ }
@@ -0,0 +1,13 @@
1
+ import { normalizeLowercaseStringOrEmpty } from "autobot/plugin-sdk/string-coerce-runtime";
2
+
3
+ export function shouldBypassConfiguredAcpEnsure(commandName: string): boolean {
4
+ const normalized = normalizeLowercaseStringOrEmpty(commandName);
5
+ // Recovery slash commands still need configured ACP readiness so stale dead
6
+ // bindings are recreated before /new or /reset dispatches through them.
7
+ return normalized === "acp";
8
+ }
9
+
10
+ export function shouldBypassConfiguredAcpGuildGuards(commandName: string): boolean {
11
+ const normalized = normalizeLowercaseStringOrEmpty(commandName);
12
+ return normalized === "new" || normalized === "reset";
13
+ }