@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,86 @@
1
+ import { logDebug } from "autobot/plugin-sdk/logging-core";
2
+ import { logVerbose } from "autobot/plugin-sdk/runtime-env";
3
+ import {
4
+ isDiscordGroupAllowedByPolicy,
5
+ resolveGroupDmAllow,
6
+ type DiscordChannelConfigResolved,
7
+ type DiscordGuildEntryResolved,
8
+ } from "./allow-list.js";
9
+
10
+ export function resolveDiscordPreflightChannelAccess(params: {
11
+ isGuildMessage: boolean;
12
+ isGroupDm: boolean;
13
+ groupPolicy: "open" | "disabled" | "allowlist";
14
+ groupDmChannels?: string[];
15
+ messageChannelId: string;
16
+ displayChannelName?: string;
17
+ displayChannelSlug: string;
18
+ guildInfo: DiscordGuildEntryResolved | null;
19
+ channelConfig: DiscordChannelConfigResolved | null;
20
+ channelMatchMeta: string;
21
+ }): { allowed: boolean; channelAllowlistConfigured: boolean; channelAllowed: boolean } {
22
+ if (params.isGuildMessage && params.channelConfig?.enabled === false) {
23
+ logDebug(`[discord-preflight] drop: channel disabled`);
24
+ logVerbose(
25
+ `Blocked discord channel ${params.messageChannelId} (channel disabled, ${params.channelMatchMeta})`,
26
+ );
27
+ return { allowed: false, channelAllowlistConfigured: false, channelAllowed: false };
28
+ }
29
+
30
+ const groupDmAllowed =
31
+ params.isGroupDm &&
32
+ resolveGroupDmAllow({
33
+ channels: params.groupDmChannels,
34
+ channelId: params.messageChannelId,
35
+ channelName: params.displayChannelName,
36
+ channelSlug: params.displayChannelSlug,
37
+ });
38
+ if (params.isGroupDm && !groupDmAllowed) {
39
+ return { allowed: false, channelAllowlistConfigured: false, channelAllowed: false };
40
+ }
41
+
42
+ const channelAllowlistConfigured =
43
+ Boolean(params.guildInfo?.channels) && Object.keys(params.guildInfo?.channels ?? {}).length > 0;
44
+ const channelAllowed = params.channelConfig?.allowed !== false;
45
+ if (
46
+ params.isGuildMessage &&
47
+ !isDiscordGroupAllowedByPolicy({
48
+ groupPolicy: params.groupPolicy,
49
+ guildAllowlisted: Boolean(params.guildInfo),
50
+ channelAllowlistConfigured,
51
+ channelAllowed,
52
+ })
53
+ ) {
54
+ if (params.groupPolicy === "disabled") {
55
+ logDebug(`[discord-preflight] drop: groupPolicy disabled`);
56
+ logVerbose(`discord: drop guild message (groupPolicy: disabled, ${params.channelMatchMeta})`);
57
+ } else if (!channelAllowlistConfigured) {
58
+ logDebug(`[discord-preflight] drop: groupPolicy allowlist, no channel allowlist configured`);
59
+ logVerbose(
60
+ `discord: drop guild message (groupPolicy: allowlist, no channel allowlist, ${params.channelMatchMeta})`,
61
+ );
62
+ } else {
63
+ logDebug(
64
+ `[discord] Ignored message from channel ${params.messageChannelId} (not in guild allowlist). Add to guilds.<guildId>.channels to enable.`,
65
+ );
66
+ logVerbose(
67
+ `Blocked discord channel ${params.messageChannelId} not in guild channel allowlist (groupPolicy: allowlist, ${params.channelMatchMeta})`,
68
+ );
69
+ }
70
+ return { allowed: false, channelAllowlistConfigured, channelAllowed };
71
+ }
72
+
73
+ if (params.isGuildMessage && params.channelConfig?.allowed === false) {
74
+ logDebug(`[discord-preflight] drop: channelConfig.allowed===false`);
75
+ logVerbose(
76
+ `Blocked discord channel ${params.messageChannelId} not in guild channel allowlist (${params.channelMatchMeta})`,
77
+ );
78
+ return { allowed: false, channelAllowlistConfigured, channelAllowed };
79
+ }
80
+ if (params.isGuildMessage) {
81
+ logDebug(`[discord-preflight] pass: channel allowed`);
82
+ logVerbose(`discord: allow channel ${params.messageChannelId} (${params.channelMatchMeta})`);
83
+ }
84
+
85
+ return { allowed: true, channelAllowlistConfigured, channelAllowed };
86
+ }
@@ -0,0 +1,58 @@
1
+ import {
2
+ normalizeDiscordDisplaySlug,
3
+ normalizeDiscordSlug,
4
+ resolveDiscordChannelConfigWithFallback,
5
+ type DiscordGuildEntryResolved,
6
+ } from "./allow-list.js";
7
+ import type { DiscordMessagePreflightContext } from "./message-handler.preflight.types.js";
8
+
9
+ export function resolveDiscordPreflightChannelContext(params: {
10
+ isGuildMessage: boolean;
11
+ messageChannelId: string;
12
+ channelName?: string;
13
+ guildName?: string;
14
+ guildInfo: DiscordGuildEntryResolved | null;
15
+ threadChannel: DiscordMessagePreflightContext["threadChannel"];
16
+ threadParentId?: string;
17
+ threadParentName?: string;
18
+ }) {
19
+ const threadName = params.threadChannel?.name;
20
+ const configChannelName = params.threadParentName ?? params.channelName;
21
+ const configChannelSlug = configChannelName ? normalizeDiscordSlug(configChannelName) : "";
22
+ const displayChannelName = threadName ?? params.channelName;
23
+ const displayChannelSlug = displayChannelName
24
+ ? normalizeDiscordDisplaySlug(displayChannelName)
25
+ : "";
26
+ const guildSlug =
27
+ params.guildInfo?.slug || (params.guildName ? normalizeDiscordSlug(params.guildName) : "");
28
+
29
+ const threadChannelSlug = params.channelName ? normalizeDiscordSlug(params.channelName) : "";
30
+ const threadParentSlug = params.threadParentName
31
+ ? normalizeDiscordSlug(params.threadParentName)
32
+ : "";
33
+
34
+ const channelConfig = params.isGuildMessage
35
+ ? resolveDiscordChannelConfigWithFallback({
36
+ guildInfo: params.guildInfo,
37
+ channelId: params.messageChannelId,
38
+ channelName: params.channelName,
39
+ channelSlug: threadChannelSlug,
40
+ parentId: params.threadParentId,
41
+ parentName: params.threadParentName,
42
+ parentSlug: threadParentSlug,
43
+ scope: params.threadChannel ? "thread" : "channel",
44
+ })
45
+ : null;
46
+
47
+ return {
48
+ threadName,
49
+ configChannelName,
50
+ configChannelSlug,
51
+ displayChannelName,
52
+ displayChannelSlug,
53
+ guildSlug,
54
+ threadChannelSlug,
55
+ threadParentSlug,
56
+ channelConfig,
57
+ };
58
+ }
@@ -0,0 +1,54 @@
1
+ import type {
2
+ DiscordMessagePreflightContext,
3
+ DiscordMessagePreflightParams,
4
+ } from "./message-handler.preflight.types.js";
5
+
6
+ type SharedPreflightFields =
7
+ | "cfg"
8
+ | "discordConfig"
9
+ | "accountId"
10
+ | "token"
11
+ | "runtime"
12
+ | "botUserId"
13
+ | "abortSignal"
14
+ | "guildHistories"
15
+ | "historyLimit"
16
+ | "mediaMaxBytes"
17
+ | "textLimit"
18
+ | "replyToMode"
19
+ | "ackReactionScope"
20
+ | "groupPolicy"
21
+ | "threadBindings"
22
+ | "discordRestFetch";
23
+
24
+ type BuildDiscordMessagePreflightContextParams = Omit<
25
+ DiscordMessagePreflightContext,
26
+ SharedPreflightFields
27
+ > & {
28
+ preflightParams: DiscordMessagePreflightParams;
29
+ };
30
+
31
+ export function buildDiscordMessagePreflightContext({
32
+ preflightParams,
33
+ ...fields
34
+ }: BuildDiscordMessagePreflightContextParams): DiscordMessagePreflightContext {
35
+ return {
36
+ cfg: preflightParams.cfg,
37
+ discordConfig: preflightParams.discordConfig,
38
+ accountId: preflightParams.accountId,
39
+ token: preflightParams.token,
40
+ runtime: preflightParams.runtime,
41
+ botUserId: preflightParams.botUserId,
42
+ abortSignal: preflightParams.abortSignal,
43
+ guildHistories: preflightParams.guildHistories,
44
+ historyLimit: preflightParams.historyLimit,
45
+ mediaMaxBytes: preflightParams.mediaMaxBytes,
46
+ textLimit: preflightParams.textLimit,
47
+ replyToMode: preflightParams.replyToMode,
48
+ ackReactionScope: preflightParams.ackReactionScope,
49
+ groupPolicy: preflightParams.groupPolicy,
50
+ ...fields,
51
+ threadBindings: preflightParams.threadBindings,
52
+ discordRestFetch: preflightParams.discordRestFetch,
53
+ };
54
+ }
@@ -0,0 +1,164 @@
1
+ import {
2
+ implicitMentionKindWhen,
3
+ matchesMentionWithExplicit,
4
+ } from "autobot/plugin-sdk/channel-inbound";
5
+ import { normalizeOptionalString } from "autobot/plugin-sdk/string-coerce-runtime";
6
+ import { ChannelType, type Message } from "../internal/discord.js";
7
+ import type { DiscordMessagePreflightParams } from "./message-handler.preflight.types.js";
8
+ import type { DiscordChannelInfo } from "./message-utils.js";
9
+ import { isRecentlyUnboundThreadWebhookMessage } from "./thread-bindings.js";
10
+
11
+ const DISCORD_BOUND_THREAD_SYSTEM_PREFIXES = ["⚙️", "🤖", "🧰"];
12
+
13
+ export function isBoundThreadBotSystemMessage(params: {
14
+ isBoundThreadSession: boolean;
15
+ isBotAuthor: boolean;
16
+ text?: string;
17
+ }): boolean {
18
+ if (!params.isBoundThreadSession || !params.isBotAuthor) {
19
+ return false;
20
+ }
21
+ const text = params.text?.trim();
22
+ if (!text) {
23
+ return false;
24
+ }
25
+ return DISCORD_BOUND_THREAD_SYSTEM_PREFIXES.some((prefix) => text.startsWith(prefix));
26
+ }
27
+
28
+ type BoundThreadLookupRecordLike = {
29
+ webhookId?: string | null;
30
+ metadata?: {
31
+ webhookId?: string | null;
32
+ };
33
+ };
34
+
35
+ function isDiscordThreadChannelType(type: ChannelType | undefined): boolean {
36
+ return (
37
+ type === ChannelType.PublicThread ||
38
+ type === ChannelType.PrivateThread ||
39
+ type === ChannelType.AnnouncementThread
40
+ );
41
+ }
42
+
43
+ export function isDiscordThreadChannelMessage(params: {
44
+ isGuildMessage: boolean;
45
+ message: Message;
46
+ channelInfo: DiscordChannelInfo | null;
47
+ }): boolean {
48
+ if (!params.isGuildMessage) {
49
+ return false;
50
+ }
51
+ const channel =
52
+ "channel" in params.message ? (params.message as { channel?: unknown }).channel : undefined;
53
+ return Boolean(
54
+ (channel &&
55
+ typeof channel === "object" &&
56
+ "isThread" in channel &&
57
+ typeof (channel as { isThread?: unknown }).isThread === "function" &&
58
+ (channel as { isThread: () => boolean }).isThread()) ||
59
+ isDiscordThreadChannelType(params.channelInfo?.type),
60
+ );
61
+ }
62
+
63
+ export function resolveInjectedBoundThreadLookupRecord(params: {
64
+ threadBindings: DiscordMessagePreflightParams["threadBindings"];
65
+ threadId: string;
66
+ }): BoundThreadLookupRecordLike | undefined {
67
+ const getByThreadId = (params.threadBindings as { getByThreadId?: (threadId: string) => unknown })
68
+ .getByThreadId;
69
+ if (typeof getByThreadId !== "function") {
70
+ return undefined;
71
+ }
72
+ const binding = getByThreadId(params.threadId);
73
+ return binding && typeof binding === "object"
74
+ ? (binding as BoundThreadLookupRecordLike)
75
+ : undefined;
76
+ }
77
+
78
+ export function resolveDiscordMentionState(params: {
79
+ authorIsBot: boolean;
80
+ botId?: string;
81
+ hasAnyMention: boolean;
82
+ isDirectMessage: boolean;
83
+ isExplicitlyMentioned: boolean;
84
+ mentionRegexes: RegExp[];
85
+ mentionText: string;
86
+ mentionedEveryone: boolean;
87
+ referencedAuthorId?: string;
88
+ senderIsPluralKit: boolean;
89
+ transcript?: string;
90
+ }) {
91
+ if (params.isDirectMessage) {
92
+ return {
93
+ implicitMentionKinds: [],
94
+ wasMentioned: false,
95
+ };
96
+ }
97
+
98
+ const everyoneMentioned =
99
+ params.mentionedEveryone && (!params.authorIsBot || params.senderIsPluralKit);
100
+ const wasMentioned =
101
+ everyoneMentioned ||
102
+ matchesMentionWithExplicit({
103
+ text: params.mentionText,
104
+ mentionRegexes: params.mentionRegexes,
105
+ explicit: {
106
+ hasAnyMention: params.hasAnyMention,
107
+ isExplicitlyMentioned: params.isExplicitlyMentioned,
108
+ canResolveExplicit: Boolean(params.botId),
109
+ },
110
+ transcript: params.transcript,
111
+ });
112
+ const implicitMentionKinds = implicitMentionKindWhen(
113
+ "reply_to_bot",
114
+ Boolean(params.botId) &&
115
+ Boolean(params.referencedAuthorId) &&
116
+ params.referencedAuthorId === params.botId,
117
+ );
118
+
119
+ return {
120
+ implicitMentionKinds,
121
+ wasMentioned,
122
+ };
123
+ }
124
+
125
+ export function resolvePreflightMentionRequirement(params: {
126
+ shouldRequireMention: boolean;
127
+ bypassMentionRequirement: boolean;
128
+ }): boolean {
129
+ if (!params.shouldRequireMention) {
130
+ return false;
131
+ }
132
+ return !params.bypassMentionRequirement;
133
+ }
134
+
135
+ export function shouldIgnoreBoundThreadWebhookMessage(params: {
136
+ accountId?: string;
137
+ threadId?: string;
138
+ webhookId?: string | null;
139
+ threadBinding?: BoundThreadLookupRecordLike;
140
+ }): boolean {
141
+ const webhookId = normalizeOptionalString(params.webhookId) ?? "";
142
+ if (!webhookId) {
143
+ return false;
144
+ }
145
+ const boundWebhookId =
146
+ normalizeOptionalString(params.threadBinding?.webhookId) ??
147
+ normalizeOptionalString(params.threadBinding?.metadata?.webhookId) ??
148
+ "";
149
+ if (boundWebhookId && webhookId === boundWebhookId) {
150
+ return true;
151
+ }
152
+ const threadId = normalizeOptionalString(params.threadId) ?? "";
153
+ if (!threadId) {
154
+ return false;
155
+ }
156
+ if (params.threadBinding) {
157
+ return true;
158
+ }
159
+ return isRecentlyUnboundThreadWebhookMessage({
160
+ accountId: params.accountId,
161
+ threadId,
162
+ webhookId,
163
+ });
164
+ }
@@ -0,0 +1,23 @@
1
+ import type { HistoryEntry } from "autobot/plugin-sdk/reply-history";
2
+ import { resolveTimestampMs } from "./format.js";
3
+ import type { DiscordMessagePreflightContext } from "./message-handler.preflight.types.js";
4
+ import { resolveDiscordMessageText } from "./message-utils.js";
5
+
6
+ export function buildDiscordPreflightHistoryEntry(params: {
7
+ isGuildMessage: boolean;
8
+ historyLimit: number;
9
+ message: DiscordMessagePreflightContext["message"];
10
+ senderLabel: string;
11
+ }): HistoryEntry | undefined {
12
+ const textForHistory = resolveDiscordMessageText(params.message, {
13
+ includeForwarded: true,
14
+ });
15
+ return params.isGuildMessage && params.historyLimit > 0 && textForHistory
16
+ ? {
17
+ sender: params.senderLabel,
18
+ body: textForHistory,
19
+ timestamp: resolveTimestampMs(params.message.timestamp),
20
+ messageId: params.message.id,
21
+ }
22
+ : undefined;
23
+ }
@@ -0,0 +1,36 @@
1
+ import { logDebug } from "autobot/plugin-sdk/logging-core";
2
+ import { logVerbose, shouldLogVerbose } from "autobot/plugin-sdk/runtime-env";
3
+ import type { DiscordChannelConfigResolved } from "./allow-list.js";
4
+
5
+ export function logDiscordPreflightChannelConfig(params: {
6
+ channelConfig: DiscordChannelConfigResolved | null;
7
+ channelMatchMeta: string;
8
+ channelId: string;
9
+ }) {
10
+ if (!shouldLogVerbose()) {
11
+ return;
12
+ }
13
+ const channelConfigSummary = params.channelConfig
14
+ ? `allowed=${params.channelConfig.allowed} enabled=${params.channelConfig.enabled ?? "unset"} requireMention=${params.channelConfig.requireMention ?? "unset"} ignoreOtherMentions=${params.channelConfig.ignoreOtherMentions ?? "unset"} matchKey=${params.channelConfig.matchKey ?? "none"} matchSource=${params.channelConfig.matchSource ?? "none"} users=${params.channelConfig.users?.length ?? 0} roles=${params.channelConfig.roles?.length ?? 0} skills=${params.channelConfig.skills?.length ?? 0}`
15
+ : "none";
16
+ logDebug(
17
+ `[discord-preflight] channelConfig=${channelConfigSummary} channelMatchMeta=${params.channelMatchMeta} channelId=${params.channelId}`,
18
+ );
19
+ }
20
+
21
+ export function logDiscordPreflightInboundSummary(params: {
22
+ messageId: string;
23
+ guildId?: string;
24
+ channelId: string;
25
+ wasMentioned: boolean;
26
+ isDirectMessage: boolean;
27
+ isGroupDm: boolean;
28
+ hasContent: boolean;
29
+ }) {
30
+ if (!shouldLogVerbose()) {
31
+ return;
32
+ }
33
+ logVerbose(
34
+ `discord: inbound id=${params.messageId} guild=${params.guildId ?? "dm"} channel=${params.channelId} mention=${params.wasMentioned ? "yes" : "no"} type=${params.isDirectMessage ? "dm" : params.isGroupDm ? "group-dm" : "guild"} content=${params.hasContent ? "yes" : "no"}`,
35
+ );
36
+ }
@@ -0,0 +1,28 @@
1
+ import { logVerbose } from "autobot/plugin-sdk/runtime-env";
2
+ import { isPreflightAborted, loadPluralKitRuntime } from "./message-handler.preflight-runtime.js";
3
+ import type { DiscordMessageEvent } from "./message-handler.preflight.types.js";
4
+
5
+ export async function resolveDiscordPreflightPluralKitInfo(params: {
6
+ message: DiscordMessageEvent["message"];
7
+ config?: NonNullable<
8
+ NonNullable<
9
+ import("autobot/plugin-sdk/config-contracts").AutoBotConfig["channels"]
10
+ >["discord"]
11
+ >["pluralkit"];
12
+ abortSignal?: AbortSignal;
13
+ }): Promise<Awaited<ReturnType<typeof import("../pluralkit.js").fetchPluralKitMessageInfo>>> {
14
+ if (!params.config?.enabled) {
15
+ return null;
16
+ }
17
+ try {
18
+ const { fetchPluralKitMessageInfo } = await loadPluralKitRuntime();
19
+ const info = await fetchPluralKitMessageInfo({
20
+ messageId: params.message.id,
21
+ config: params.config,
22
+ });
23
+ return isPreflightAborted(params.abortSignal) ? null : info;
24
+ } catch (err) {
25
+ logVerbose(`discord: pluralkit lookup failed for ${params.message.id}: ${String(err)}`);
26
+ return null;
27
+ }
28
+ }
@@ -0,0 +1,28 @@
1
+ let pluralkitRuntimePromise: Promise<typeof import("../pluralkit.js")> | undefined;
2
+ let preflightAudioRuntimePromise: Promise<typeof import("./preflight-audio.js")> | undefined;
3
+ let systemEventsRuntimePromise: Promise<typeof import("./system-events.js")> | undefined;
4
+ let discordThreadingRuntimePromise: Promise<typeof import("./threading.js")> | undefined;
5
+
6
+ export async function loadPluralKitRuntime() {
7
+ pluralkitRuntimePromise ??= import("../pluralkit.js");
8
+ return await pluralkitRuntimePromise;
9
+ }
10
+
11
+ export async function loadPreflightAudioRuntime() {
12
+ preflightAudioRuntimePromise ??= import("./preflight-audio.js");
13
+ return await preflightAudioRuntimePromise;
14
+ }
15
+
16
+ export async function loadSystemEventsRuntime() {
17
+ systemEventsRuntimePromise ??= import("./system-events.js");
18
+ return await systemEventsRuntimePromise;
19
+ }
20
+
21
+ export async function loadDiscordThreadingRuntime() {
22
+ discordThreadingRuntimePromise ??= import("./threading.js");
23
+ return await discordThreadingRuntimePromise;
24
+ }
25
+
26
+ export function isPreflightAborted(abortSignal?: AbortSignal): boolean {
27
+ return Boolean(abortSignal?.aborted);
28
+ }
@@ -0,0 +1,49 @@
1
+ import type { ChannelType } from "../internal/discord.js";
2
+ import {
3
+ isPreflightAborted,
4
+ loadDiscordThreadingRuntime,
5
+ } from "./message-handler.preflight-runtime.js";
6
+ import type { DiscordMessagePreflightContext } from "./message-handler.preflight.types.js";
7
+ import type { DiscordChannelInfo } from "./message-utils.js";
8
+
9
+ type DiscordPreflightThreadContext = {
10
+ earlyThreadChannel: DiscordMessagePreflightContext["threadChannel"];
11
+ earlyThreadParentId?: string;
12
+ earlyThreadParentName?: string;
13
+ earlyThreadParentType?: ChannelType;
14
+ };
15
+
16
+ export async function resolveDiscordPreflightThreadContext(params: {
17
+ client: DiscordMessagePreflightContext["client"];
18
+ isGuildMessage: boolean;
19
+ message: DiscordMessagePreflightContext["message"];
20
+ channelInfo: DiscordChannelInfo | null;
21
+ messageChannelId: string;
22
+ abortSignal?: AbortSignal;
23
+ }): Promise<DiscordPreflightThreadContext | null> {
24
+ const { resolveDiscordThreadChannel, resolveDiscordThreadParentInfo } =
25
+ await loadDiscordThreadingRuntime();
26
+ const earlyThreadChannel = resolveDiscordThreadChannel({
27
+ isGuildMessage: params.isGuildMessage,
28
+ message: params.message,
29
+ channelInfo: params.channelInfo,
30
+ messageChannelId: params.messageChannelId,
31
+ });
32
+ if (!earlyThreadChannel) {
33
+ return { earlyThreadChannel: null };
34
+ }
35
+ const parentInfo = await resolveDiscordThreadParentInfo({
36
+ client: params.client,
37
+ threadChannel: earlyThreadChannel,
38
+ channelInfo: params.channelInfo,
39
+ });
40
+ if (isPreflightAborted(params.abortSignal)) {
41
+ return null;
42
+ }
43
+ return {
44
+ earlyThreadChannel,
45
+ earlyThreadParentId: parentInfo.id,
46
+ earlyThreadParentName: parentInfo.name,
47
+ earlyThreadParentType: parentInfo.type,
48
+ };
49
+ }