@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,356 @@
1
+ import { resolveGlobalMap } from "autobot/plugin-sdk/global-singleton";
2
+ import type { DiscordComponentEntry, DiscordModalEntry } from "./components.js";
3
+ import { getOptionalDiscordRuntime } from "./runtime.js";
4
+
5
+ const DEFAULT_COMPONENT_TTL_MS = 30 * 60 * 1000;
6
+ const PERSISTENT_COMPONENT_NAMESPACE = "discord.components";
7
+ const PERSISTENT_MODAL_NAMESPACE = "discord.modals";
8
+ const PERSISTENT_COMPONENT_MAX_ENTRIES = 500;
9
+ const PERSISTENT_MODAL_MAX_ENTRIES = 500;
10
+ const DISCORD_COMPONENT_ENTRIES_KEY = Symbol.for("autobot.discord.componentEntries");
11
+ const DISCORD_MODAL_ENTRIES_KEY = Symbol.for("autobot.discord.modalEntries");
12
+
13
+ type PersistedDiscordRegistryEntry<T extends { id: string }> = {
14
+ version: 1;
15
+ entry: T;
16
+ };
17
+
18
+ type DiscordPersistentStore<T> = {
19
+ register(key: string, value: T, opts?: { ttlMs?: number }): Promise<void>;
20
+ lookup(key: string): Promise<T | undefined>;
21
+ consume(key: string): Promise<T | undefined>;
22
+ delete(key: string): Promise<boolean>;
23
+ };
24
+
25
+ type DiscordRegistryStore<T extends { id: string }> = DiscordPersistentStore<
26
+ PersistedDiscordRegistryEntry<T>
27
+ >;
28
+
29
+ let componentEntries: Map<string, DiscordComponentEntry> | undefined;
30
+ let modalEntries: Map<string, DiscordModalEntry> | undefined;
31
+ let persistentComponentStore: DiscordRegistryStore<DiscordComponentEntry> | undefined;
32
+ let persistentModalStore: DiscordRegistryStore<DiscordModalEntry> | undefined;
33
+ let persistentRegistryDisabled = false;
34
+
35
+ function getComponentEntries(): Map<string, DiscordComponentEntry> {
36
+ componentEntries ??= resolveGlobalMap<string, DiscordComponentEntry>(
37
+ DISCORD_COMPONENT_ENTRIES_KEY,
38
+ );
39
+ return componentEntries;
40
+ }
41
+
42
+ function getModalEntries(): Map<string, DiscordModalEntry> {
43
+ modalEntries ??= resolveGlobalMap<string, DiscordModalEntry>(DISCORD_MODAL_ENTRIES_KEY);
44
+ return modalEntries;
45
+ }
46
+
47
+ function reportPersistentComponentRegistryError(error: unknown): void {
48
+ try {
49
+ getOptionalDiscordRuntime()
50
+ ?.logging.getChildLogger({ plugin: "discord", feature: "component-registry-state" })
51
+ .warn("Discord persistent component registry state failed", { error: String(error) });
52
+ } catch {
53
+ // Best effort only: persistent state must never break Discord interactions.
54
+ }
55
+ }
56
+
57
+ function disablePersistentComponentRegistry(error: unknown): void {
58
+ persistentRegistryDisabled = true;
59
+ persistentComponentStore = undefined;
60
+ persistentModalStore = undefined;
61
+ reportPersistentComponentRegistryError(error);
62
+ }
63
+
64
+ function getPersistentComponentStore(): DiscordRegistryStore<DiscordComponentEntry> | undefined {
65
+ if (persistentRegistryDisabled) {
66
+ return undefined;
67
+ }
68
+ if (persistentComponentStore) {
69
+ return persistentComponentStore;
70
+ }
71
+ const runtime = getOptionalDiscordRuntime();
72
+ if (!runtime) {
73
+ return undefined;
74
+ }
75
+ try {
76
+ persistentComponentStore = runtime.state.openKeyedStore<
77
+ PersistedDiscordRegistryEntry<DiscordComponentEntry>
78
+ >({
79
+ namespace: PERSISTENT_COMPONENT_NAMESPACE,
80
+ maxEntries: PERSISTENT_COMPONENT_MAX_ENTRIES,
81
+ defaultTtlMs: DEFAULT_COMPONENT_TTL_MS,
82
+ });
83
+ return persistentComponentStore;
84
+ } catch (error) {
85
+ disablePersistentComponentRegistry(error);
86
+ return undefined;
87
+ }
88
+ }
89
+
90
+ function getPersistentModalStore(): DiscordRegistryStore<DiscordModalEntry> | undefined {
91
+ if (persistentRegistryDisabled) {
92
+ return undefined;
93
+ }
94
+ if (persistentModalStore) {
95
+ return persistentModalStore;
96
+ }
97
+ const runtime = getOptionalDiscordRuntime();
98
+ if (!runtime) {
99
+ return undefined;
100
+ }
101
+ try {
102
+ persistentModalStore = runtime.state.openKeyedStore<
103
+ PersistedDiscordRegistryEntry<DiscordModalEntry>
104
+ >({
105
+ namespace: PERSISTENT_MODAL_NAMESPACE,
106
+ maxEntries: PERSISTENT_MODAL_MAX_ENTRIES,
107
+ defaultTtlMs: DEFAULT_COMPONENT_TTL_MS,
108
+ });
109
+ return persistentModalStore;
110
+ } catch (error) {
111
+ disablePersistentComponentRegistry(error);
112
+ return undefined;
113
+ }
114
+ }
115
+
116
+ function isExpired(entry: { expiresAt?: number }, now: number) {
117
+ return typeof entry.expiresAt === "number" && entry.expiresAt <= now;
118
+ }
119
+
120
+ function normalizeEntryTimestamps<T extends { createdAt?: number; expiresAt?: number }>(
121
+ entry: T,
122
+ now: number,
123
+ ttlMs: number,
124
+ ): T {
125
+ const createdAt = entry.createdAt ?? now;
126
+ const expiresAt = entry.expiresAt ?? createdAt + ttlMs;
127
+ return { ...entry, createdAt, expiresAt };
128
+ }
129
+
130
+ function registerEntries<
131
+ T extends { id: string; messageId?: string; createdAt?: number; expiresAt?: number },
132
+ >(
133
+ entries: T[],
134
+ store: Map<string, T>,
135
+ params: { now: number; ttlMs: number; messageId?: string },
136
+ ): T[] {
137
+ const normalizedEntries: T[] = [];
138
+ for (const entry of entries) {
139
+ const normalized = normalizeEntryTimestamps(
140
+ { ...entry, messageId: params.messageId ?? entry.messageId },
141
+ params.now,
142
+ params.ttlMs,
143
+ );
144
+ store.set(entry.id, normalized);
145
+ normalizedEntries.push(normalized);
146
+ }
147
+ return normalizedEntries;
148
+ }
149
+
150
+ function resolveEntry<T extends { expiresAt?: number }>(
151
+ store: Map<string, T>,
152
+ params: { id: string; consume?: boolean },
153
+ ): T | null {
154
+ const entry = store.get(params.id);
155
+ if (!entry) {
156
+ return null;
157
+ }
158
+ const now = Date.now();
159
+ if (isExpired(entry, now)) {
160
+ store.delete(params.id);
161
+ return null;
162
+ }
163
+ if (params.consume !== false) {
164
+ store.delete(params.id);
165
+ }
166
+ return entry;
167
+ }
168
+
169
+ function readPersistedRegistryEntry<T extends { id: string }>(
170
+ persisted: PersistedDiscordRegistryEntry<T> | undefined,
171
+ ): T | null {
172
+ if (persisted?.version !== 1 || typeof persisted.entry?.id !== "string") {
173
+ return null;
174
+ }
175
+ return persisted.entry;
176
+ }
177
+
178
+ function registerPersistentRegistryEntries<T extends { id: string }>(params: {
179
+ entries: T[];
180
+ ttlMs: number;
181
+ openStore: () => DiscordRegistryStore<T> | undefined;
182
+ }): void {
183
+ if (params.entries.length === 0) {
184
+ return;
185
+ }
186
+ const store = params.openStore();
187
+ if (!store) {
188
+ return;
189
+ }
190
+ for (const entry of params.entries) {
191
+ void store
192
+ .register(entry.id, { version: 1, entry }, { ttlMs: params.ttlMs })
193
+ .catch(disablePersistentComponentRegistry);
194
+ }
195
+ }
196
+
197
+ function registerPersistentEntries(params: {
198
+ entries: DiscordComponentEntry[];
199
+ modals: DiscordModalEntry[];
200
+ ttlMs: number;
201
+ }): void {
202
+ registerPersistentRegistryEntries({
203
+ entries: params.entries,
204
+ ttlMs: params.ttlMs,
205
+ openStore: getPersistentComponentStore,
206
+ });
207
+ registerPersistentRegistryEntries({
208
+ entries: params.modals,
209
+ ttlMs: params.ttlMs,
210
+ openStore: getPersistentModalStore,
211
+ });
212
+ }
213
+
214
+ function deletePersistentEntry<T extends { id: string }>(params: {
215
+ id: string;
216
+ openStore: () => DiscordRegistryStore<T> | undefined;
217
+ }): void {
218
+ const store = params.openStore();
219
+ if (!store) {
220
+ return;
221
+ }
222
+ void store.delete(params.id).catch(disablePersistentComponentRegistry);
223
+ }
224
+
225
+ function resolveComponentConsumptionIds(entry: DiscordComponentEntry): string[] {
226
+ if (!entry.consumptionGroupId) {
227
+ return [entry.id];
228
+ }
229
+ const ids = entry.consumptionGroupEntryIds?.filter((id) => typeof id === "string" && id) ?? [];
230
+ return ids.length > 0 ? Array.from(new Set(ids)) : [entry.id];
231
+ }
232
+
233
+ function deleteComponentConsumptionGroup(entry: DiscordComponentEntry): void {
234
+ const store = getComponentEntries();
235
+ for (const id of resolveComponentConsumptionIds(entry)) {
236
+ store.delete(id);
237
+ }
238
+ }
239
+
240
+ function deletePersistentComponentConsumptionGroup(entry: DiscordComponentEntry): void {
241
+ const store = getPersistentComponentStore();
242
+ if (!store) {
243
+ return;
244
+ }
245
+ for (const id of resolveComponentConsumptionIds(entry)) {
246
+ void store.delete(id).catch(disablePersistentComponentRegistry);
247
+ }
248
+ }
249
+
250
+ async function resolvePersistentRegistryEntry<T extends { id: string }>(params: {
251
+ id: string;
252
+ consume?: boolean;
253
+ openStore: () => DiscordRegistryStore<T> | undefined;
254
+ }): Promise<T | null> {
255
+ const store = params.openStore();
256
+ if (!store) {
257
+ return null;
258
+ }
259
+ try {
260
+ const value =
261
+ params.consume === false ? await store.lookup(params.id) : await store.consume(params.id);
262
+ return readPersistedRegistryEntry(value);
263
+ } catch (error) {
264
+ disablePersistentComponentRegistry(error);
265
+ return null;
266
+ }
267
+ }
268
+
269
+ export function registerDiscordComponentEntries(params: {
270
+ entries: DiscordComponentEntry[];
271
+ modals: DiscordModalEntry[];
272
+ ttlMs?: number;
273
+ messageId?: string;
274
+ }): void {
275
+ const now = Date.now();
276
+ const ttlMs = params.ttlMs ?? DEFAULT_COMPONENT_TTL_MS;
277
+ const normalizedEntries = registerEntries(params.entries, getComponentEntries(), {
278
+ now,
279
+ ttlMs,
280
+ messageId: params.messageId,
281
+ });
282
+ const normalizedModals = registerEntries(params.modals, getModalEntries(), {
283
+ now,
284
+ ttlMs,
285
+ messageId: params.messageId,
286
+ });
287
+ registerPersistentEntries({
288
+ entries: normalizedEntries,
289
+ modals: normalizedModals,
290
+ ttlMs,
291
+ });
292
+ }
293
+
294
+ export function resolveDiscordComponentEntry(params: {
295
+ id: string;
296
+ consume?: boolean;
297
+ }): DiscordComponentEntry | null {
298
+ const entry = resolveEntry(getComponentEntries(), params);
299
+ if (entry && params.consume !== false) {
300
+ deleteComponentConsumptionGroup(entry);
301
+ }
302
+ return entry;
303
+ }
304
+
305
+ export async function resolveDiscordComponentEntryWithPersistence(params: {
306
+ id: string;
307
+ consume?: boolean;
308
+ }): Promise<DiscordComponentEntry | null> {
309
+ const inMemory = resolveDiscordComponentEntry(params);
310
+ if (inMemory) {
311
+ if (params.consume !== false) {
312
+ deletePersistentComponentConsumptionGroup(inMemory);
313
+ }
314
+ return inMemory;
315
+ }
316
+ const persisted = await resolvePersistentRegistryEntry({
317
+ ...params,
318
+ openStore: getPersistentComponentStore,
319
+ });
320
+ if (persisted && params.consume !== false) {
321
+ deletePersistentComponentConsumptionGroup(persisted);
322
+ }
323
+ return persisted;
324
+ }
325
+
326
+ export function resolveDiscordModalEntry(params: {
327
+ id: string;
328
+ consume?: boolean;
329
+ }): DiscordModalEntry | null {
330
+ return resolveEntry(getModalEntries(), params);
331
+ }
332
+
333
+ export async function resolveDiscordModalEntryWithPersistence(params: {
334
+ id: string;
335
+ consume?: boolean;
336
+ }): Promise<DiscordModalEntry | null> {
337
+ const inMemory = resolveDiscordModalEntry(params);
338
+ if (inMemory) {
339
+ if (params.consume !== false) {
340
+ deletePersistentEntry({ ...params, openStore: getPersistentModalStore });
341
+ }
342
+ return inMemory;
343
+ }
344
+ return await resolvePersistentRegistryEntry({
345
+ ...params,
346
+ openStore: getPersistentModalStore,
347
+ });
348
+ }
349
+
350
+ export function clearDiscordComponentEntries(): void {
351
+ getComponentEntries().clear();
352
+ getModalEntries().clear();
353
+ persistentComponentStore = undefined;
354
+ persistentModalStore = undefined;
355
+ persistentRegistryDisabled = false;
356
+ }