@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,67 @@
1
+ import {
2
+ jsonResult,
3
+ readNumberParam,
4
+ readReactionParams,
5
+ readStringParam,
6
+ } from "../runtime-api.js";
7
+ import { discordMessagingActionRuntime } from "./runtime.messaging.runtime.js";
8
+ import type { DiscordMessagingActionContext } from "./runtime.messaging.shared.js";
9
+
10
+ export async function handleDiscordReactionMessagingAction(ctx: DiscordMessagingActionContext) {
11
+ switch (ctx.action) {
12
+ case "react": {
13
+ if (!ctx.isActionEnabled("reactions")) {
14
+ throw new Error("Discord reactions are disabled.");
15
+ }
16
+ const channelId = await ctx.resolveReactionChannelId();
17
+ const messageId = readStringParam(ctx.params, "messageId", {
18
+ required: true,
19
+ });
20
+ const { emoji, remove, isEmpty } = readReactionParams(ctx.params, {
21
+ removeErrorMessage: "Emoji is required to remove a Discord reaction.",
22
+ });
23
+ if (remove) {
24
+ await discordMessagingActionRuntime.removeReactionDiscord(
25
+ channelId,
26
+ messageId,
27
+ emoji,
28
+ ctx.withReactionRuntimeOptions(),
29
+ );
30
+ return jsonResult({ ok: true, removed: emoji });
31
+ }
32
+ if (isEmpty) {
33
+ const removed = await discordMessagingActionRuntime.removeOwnReactionsDiscord(
34
+ channelId,
35
+ messageId,
36
+ ctx.withReactionRuntimeOptions(),
37
+ );
38
+ return jsonResult({ ok: true, removed: removed.removed });
39
+ }
40
+ await discordMessagingActionRuntime.reactMessageDiscord(
41
+ channelId,
42
+ messageId,
43
+ emoji,
44
+ ctx.withReactionRuntimeOptions(),
45
+ );
46
+ return jsonResult({ ok: true, added: emoji });
47
+ }
48
+ case "reactions": {
49
+ if (!ctx.isActionEnabled("reactions")) {
50
+ throw new Error("Discord reactions are disabled.");
51
+ }
52
+ const channelId = await ctx.resolveReactionChannelId();
53
+ const messageId = readStringParam(ctx.params, "messageId", {
54
+ required: true,
55
+ });
56
+ const limit = readNumberParam(ctx.params, "limit");
57
+ const reactions = await discordMessagingActionRuntime.fetchReactionsDiscord(
58
+ channelId,
59
+ messageId,
60
+ ctx.withReactionRuntimeOptions({ limit }),
61
+ );
62
+ return jsonResult({ ok: true, reactions });
63
+ }
64
+ default:
65
+ return undefined;
66
+ }
67
+ }
@@ -0,0 +1,73 @@
1
+ import { readDiscordComponentSpec } from "../components.js";
2
+ import type { AutoBotConfig } from "../runtime-api.js";
3
+ import { sendDiscordComponentMessage } from "../send.components.js";
4
+ import {
5
+ createThreadDiscord,
6
+ deleteMessageDiscord,
7
+ editMessageDiscord,
8
+ editChannelDiscord,
9
+ fetchChannelInfoDiscord,
10
+ fetchChannelPermissionsDiscord,
11
+ fetchMessageDiscord,
12
+ fetchReactionsDiscord,
13
+ listPinsDiscord,
14
+ listThreadsDiscord,
15
+ pinMessageDiscord,
16
+ reactMessageDiscord,
17
+ readMessagesDiscord,
18
+ removeOwnReactionsDiscord,
19
+ removeReactionDiscord,
20
+ searchMessagesDiscord,
21
+ sendMessageDiscord,
22
+ sendPollDiscord,
23
+ sendStickerDiscord,
24
+ sendVoiceMessageDiscord,
25
+ unpinMessageDiscord,
26
+ } from "../send.js";
27
+ import { resolveDiscordTargetChannelId } from "../send.shared.js";
28
+ import { resolveDiscordChannelId } from "../targets.js";
29
+
30
+ export const discordMessagingActionRuntime = {
31
+ createThreadDiscord,
32
+ deleteMessageDiscord,
33
+ editChannelDiscord,
34
+ editMessageDiscord,
35
+ fetchChannelInfoDiscord,
36
+ fetchChannelPermissionsDiscord,
37
+ fetchMessageDiscord,
38
+ fetchReactionsDiscord,
39
+ listPinsDiscord,
40
+ listThreadsDiscord,
41
+ pinMessageDiscord,
42
+ reactMessageDiscord,
43
+ readDiscordComponentSpec,
44
+ readMessagesDiscord,
45
+ removeOwnReactionsDiscord,
46
+ removeReactionDiscord,
47
+ resolveDiscordReactionTargetChannelId,
48
+ resolveDiscordChannelId,
49
+ searchMessagesDiscord,
50
+ sendDiscordComponentMessage,
51
+ sendMessageDiscord,
52
+ sendPollDiscord,
53
+ sendStickerDiscord,
54
+ sendVoiceMessageDiscord,
55
+ unpinMessageDiscord,
56
+ };
57
+
58
+ async function resolveDiscordReactionTargetChannelId(params: {
59
+ target: string;
60
+ cfg: AutoBotConfig;
61
+ accountId?: string;
62
+ }): Promise<string> {
63
+ try {
64
+ return resolveDiscordChannelId(params.target);
65
+ } catch {
66
+ return (
67
+ await resolveDiscordTargetChannelId(params.target, {
68
+ cfg: params.cfg,
69
+ accountId: params.accountId,
70
+ })
71
+ ).channelId;
72
+ }
73
+ }
@@ -0,0 +1,336 @@
1
+ import { formatErrorMessage } from "autobot/plugin-sdk/error-runtime";
2
+ import {
3
+ assertMediaNotDataUrl,
4
+ jsonResult,
5
+ readBooleanParam,
6
+ readNumberParam,
7
+ readStringArrayParam,
8
+ readStringParam,
9
+ resolvePollMaxSelections,
10
+ } from "../runtime-api.js";
11
+ import { DiscordThreadInitialMessageError } from "../send.js";
12
+ import { isThreadChannelType } from "../send.permissions.js";
13
+ import type { DiscordSendComponents, DiscordSendEmbeds } from "../send.shared.js";
14
+ import { discordMessagingActionRuntime } from "./runtime.messaging.runtime.js";
15
+ import type { DiscordMessagingActionContext } from "./runtime.messaging.shared.js";
16
+
17
+ function hasDiscordComponentObjectKeys(value: unknown): value is Record<string, unknown> {
18
+ return Boolean(
19
+ value &&
20
+ typeof value === "object" &&
21
+ !Array.isArray(value) &&
22
+ Object.keys(value as Record<string, unknown>).length > 0,
23
+ );
24
+ }
25
+
26
+ async function appendDiscordThreadRenameResult(
27
+ ctx: DiscordMessagingActionContext,
28
+ params: {
29
+ payload: Record<string, unknown>;
30
+ target: string;
31
+ threadName?: string;
32
+ },
33
+ ) {
34
+ const threadName = params.threadName?.trim();
35
+ if (!threadName) {
36
+ return params.payload;
37
+ }
38
+ if (!ctx.isActionEnabled("channels")) {
39
+ return {
40
+ ...params.payload,
41
+ warning: "Discord threadName was ignored because Discord channel management is disabled.",
42
+ };
43
+ }
44
+
45
+ let channelId: string;
46
+ try {
47
+ channelId = discordMessagingActionRuntime.resolveDiscordChannelId(params.target);
48
+ } catch {
49
+ return {
50
+ ...params.payload,
51
+ warning: "Discord threadName was ignored because the send target is not a channel/thread.",
52
+ };
53
+ }
54
+
55
+ try {
56
+ const channel = await discordMessagingActionRuntime.fetchChannelInfoDiscord(
57
+ channelId,
58
+ ctx.withOpts(),
59
+ );
60
+ if (!isThreadChannelType(channel.type)) {
61
+ return {
62
+ ...params.payload,
63
+ warning: "Discord threadName was ignored because the send target is not a thread.",
64
+ };
65
+ }
66
+ const renamed = await discordMessagingActionRuntime.editChannelDiscord(
67
+ {
68
+ channelId,
69
+ name: threadName,
70
+ },
71
+ ctx.withOpts(),
72
+ );
73
+ return {
74
+ ...params.payload,
75
+ threadRename: {
76
+ ok: true,
77
+ channelId,
78
+ name: renamed.name ?? threadName,
79
+ },
80
+ };
81
+ } catch (error) {
82
+ return {
83
+ ...params.payload,
84
+ warning: `Discord message was sent, but thread rename failed: ${formatErrorMessage(error)}`,
85
+ };
86
+ }
87
+ }
88
+
89
+ export async function handleDiscordMessageSendAction(ctx: DiscordMessagingActionContext) {
90
+ switch (ctx.action) {
91
+ case "sticker": {
92
+ if (!ctx.isActionEnabled("stickers")) {
93
+ throw new Error("Discord stickers are disabled.");
94
+ }
95
+ const to = readStringParam(ctx.params, "to", { required: true });
96
+ const content = readStringParam(ctx.params, "content");
97
+ const stickerIds = readStringArrayParam(ctx.params, "stickerIds", {
98
+ required: true,
99
+ label: "stickerIds",
100
+ });
101
+ await discordMessagingActionRuntime.sendStickerDiscord(
102
+ to,
103
+ stickerIds,
104
+ ctx.withOpts({ content }),
105
+ );
106
+ return jsonResult({ ok: true });
107
+ }
108
+ case "poll": {
109
+ if (!ctx.isActionEnabled("polls")) {
110
+ throw new Error("Discord polls are disabled.");
111
+ }
112
+ const to = readStringParam(ctx.params, "to", { required: true });
113
+ const content = readStringParam(ctx.params, "content");
114
+ const question = readStringParam(ctx.params, "question", {
115
+ required: true,
116
+ });
117
+ const answers = readStringArrayParam(ctx.params, "answers", {
118
+ required: true,
119
+ label: "answers",
120
+ });
121
+ const allowMultiselect = readBooleanParam(ctx.params, "allowMultiselect");
122
+ const durationHours = readNumberParam(ctx.params, "durationHours");
123
+ const maxSelections = resolvePollMaxSelections(answers.length, allowMultiselect);
124
+ await discordMessagingActionRuntime.sendPollDiscord(
125
+ to,
126
+ { question, options: answers, maxSelections, durationHours },
127
+ ctx.withOpts({ content }),
128
+ );
129
+ return jsonResult({ ok: true });
130
+ }
131
+ case "sendMessage": {
132
+ if (!ctx.isActionEnabled("messages")) {
133
+ throw new Error("Discord message sends are disabled.");
134
+ }
135
+ const to = readStringParam(ctx.params, "to", { required: true });
136
+ const asVoice = ctx.params.asVoice === true;
137
+ const silent = ctx.params.silent === true;
138
+ const suppressEmbeds =
139
+ ctx.params.suppressEmbeds === undefined ? undefined : ctx.params.suppressEmbeds === true;
140
+ const rawComponents = ctx.params.components;
141
+ const componentSpec = hasDiscordComponentObjectKeys(rawComponents)
142
+ ? discordMessagingActionRuntime.readDiscordComponentSpec(rawComponents)
143
+ : null;
144
+ const components: DiscordSendComponents | undefined =
145
+ Array.isArray(rawComponents) || typeof rawComponents === "function"
146
+ ? (rawComponents as DiscordSendComponents)
147
+ : undefined;
148
+ const mediaUrl =
149
+ readStringParam(ctx.params, "mediaUrl", { trim: false }) ??
150
+ readStringParam(ctx.params, "path", { trim: false }) ??
151
+ readStringParam(ctx.params, "filePath", { trim: false });
152
+ const content = readStringParam(ctx.params, "content", {
153
+ required: !asVoice && !componentSpec && !components && !mediaUrl,
154
+ allowEmpty: true,
155
+ });
156
+ const filename = readStringParam(ctx.params, "filename");
157
+ const replyTo = readStringParam(ctx.params, "replyTo");
158
+ const threadName = readStringParam(ctx.params, "threadName");
159
+ const rawEmbeds = ctx.params.embeds;
160
+ const embeds: DiscordSendEmbeds | undefined = Array.isArray(rawEmbeds)
161
+ ? (rawEmbeds as DiscordSendEmbeds)
162
+ : undefined;
163
+ const sessionKey = readStringParam(ctx.params, "__sessionKey");
164
+ const agentId = readStringParam(ctx.params, "__agentId");
165
+
166
+ if (componentSpec) {
167
+ if (asVoice) {
168
+ throw new Error("Discord components cannot be sent as voice messages.");
169
+ }
170
+ if (embeds?.length) {
171
+ throw new Error("Discord components cannot include embeds.");
172
+ }
173
+ const normalizedContent = content?.trim() ? content : undefined;
174
+ const payload = componentSpec.text
175
+ ? componentSpec
176
+ : { ...componentSpec, text: normalizedContent };
177
+ const result = await discordMessagingActionRuntime.sendDiscordComponentMessage(
178
+ to,
179
+ payload,
180
+ {
181
+ ...ctx.withOpts(),
182
+ silent,
183
+ replyTo: replyTo ?? undefined,
184
+ sessionKey: sessionKey ?? undefined,
185
+ agentId: agentId ?? undefined,
186
+ mediaUrl: mediaUrl ?? undefined,
187
+ filename: filename ?? undefined,
188
+ mediaAccess: ctx.options?.mediaAccess,
189
+ mediaLocalRoots: ctx.options?.mediaLocalRoots,
190
+ mediaReadFile: ctx.options?.mediaReadFile,
191
+ ...(suppressEmbeds === undefined ? {} : { suppressEmbeds }),
192
+ },
193
+ );
194
+ return jsonResult(
195
+ await appendDiscordThreadRenameResult(ctx, {
196
+ payload: { ok: true, result, components: true },
197
+ target: to,
198
+ threadName,
199
+ }),
200
+ );
201
+ }
202
+
203
+ if (asVoice) {
204
+ if (!mediaUrl) {
205
+ throw new Error(
206
+ "Voice messages require a media file reference (mediaUrl, path, or filePath).",
207
+ );
208
+ }
209
+ if (content && content.trim()) {
210
+ throw new Error(
211
+ "Voice messages cannot include text content (Discord limitation). Remove the content parameter.",
212
+ );
213
+ }
214
+ assertMediaNotDataUrl(mediaUrl);
215
+ const result = await discordMessagingActionRuntime.sendVoiceMessageDiscord(to, mediaUrl, {
216
+ ...ctx.withOpts(),
217
+ replyTo,
218
+ silent,
219
+ });
220
+ return jsonResult(
221
+ await appendDiscordThreadRenameResult(ctx, {
222
+ payload: { ok: true, result, voiceMessage: true },
223
+ target: to,
224
+ threadName,
225
+ }),
226
+ );
227
+ }
228
+
229
+ const result = await discordMessagingActionRuntime.sendMessageDiscord(to, content ?? "", {
230
+ ...ctx.withOpts(),
231
+ mediaAccess: ctx.options?.mediaAccess,
232
+ mediaUrl,
233
+ filename: filename ?? undefined,
234
+ mediaLocalRoots: ctx.options?.mediaLocalRoots,
235
+ mediaReadFile: ctx.options?.mediaReadFile,
236
+ replyTo,
237
+ components,
238
+ embeds,
239
+ silent,
240
+ ...(suppressEmbeds === undefined ? {} : { suppressEmbeds }),
241
+ });
242
+ return jsonResult(
243
+ await appendDiscordThreadRenameResult(ctx, {
244
+ payload: { ok: true, result },
245
+ target: to,
246
+ threadName,
247
+ }),
248
+ );
249
+ }
250
+ case "threadCreate": {
251
+ if (!ctx.isActionEnabled("threads")) {
252
+ throw new Error("Discord threads are disabled.");
253
+ }
254
+ const channelId = ctx.resolveChannelId();
255
+ const name = readStringParam(ctx.params, "name", { required: true });
256
+ const messageId = readStringParam(ctx.params, "messageId");
257
+ const content = readStringParam(ctx.params, "content");
258
+ const autoArchiveMinutes = readNumberParam(ctx.params, "autoArchiveMinutes");
259
+ const appliedTags = readStringArrayParam(ctx.params, "appliedTags");
260
+ const payload = {
261
+ name,
262
+ messageId,
263
+ autoArchiveMinutes,
264
+ content,
265
+ appliedTags: appliedTags ?? undefined,
266
+ };
267
+ try {
268
+ const thread = await discordMessagingActionRuntime.createThreadDiscord(
269
+ channelId,
270
+ payload,
271
+ ctx.withOpts(),
272
+ );
273
+ return jsonResult({ ok: true, thread });
274
+ } catch (error) {
275
+ if (error instanceof DiscordThreadInitialMessageError) {
276
+ return jsonResult({
277
+ ok: true,
278
+ partial: true,
279
+ thread: error.thread,
280
+ warning: "Discord thread was created, but sending the initial message failed.",
281
+ initialMessageError: error.initialMessageError,
282
+ });
283
+ }
284
+ throw error;
285
+ }
286
+ }
287
+ case "threadList": {
288
+ if (!ctx.isActionEnabled("threads")) {
289
+ throw new Error("Discord threads are disabled.");
290
+ }
291
+ const guildId = readStringParam(ctx.params, "guildId", {
292
+ required: true,
293
+ });
294
+ const channelId = readStringParam(ctx.params, "channelId");
295
+ const includeArchived = readBooleanParam(ctx.params, "includeArchived");
296
+ const before = readStringParam(ctx.params, "before");
297
+ const limit = readNumberParam(ctx.params, "limit");
298
+ const threads = await discordMessagingActionRuntime.listThreadsDiscord(
299
+ {
300
+ guildId,
301
+ channelId,
302
+ includeArchived,
303
+ before,
304
+ limit,
305
+ },
306
+ ctx.withOpts(),
307
+ );
308
+ return jsonResult({ ok: true, threads });
309
+ }
310
+ case "threadReply": {
311
+ if (!ctx.isActionEnabled("threads")) {
312
+ throw new Error("Discord threads are disabled.");
313
+ }
314
+ const channelId = ctx.resolveChannelId();
315
+ const content = readStringParam(ctx.params, "content", {
316
+ required: true,
317
+ });
318
+ const mediaUrl = readStringParam(ctx.params, "mediaUrl");
319
+ const replyTo = readStringParam(ctx.params, "replyTo");
320
+ const result = await discordMessagingActionRuntime.sendMessageDiscord(
321
+ `channel:${channelId}`,
322
+ content,
323
+ {
324
+ ...ctx.withOpts(),
325
+ mediaUrl,
326
+ mediaLocalRoots: ctx.options?.mediaLocalRoots,
327
+ mediaReadFile: ctx.options?.mediaReadFile,
328
+ replyTo,
329
+ },
330
+ );
331
+ return jsonResult({ ok: true, result });
332
+ }
333
+ default:
334
+ return undefined;
335
+ }
336
+ }
@@ -0,0 +1,97 @@
1
+ import { resolveDefaultDiscordAccountId } from "../accounts.js";
2
+ import { createDiscordRuntimeAccountContext } from "../client.js";
3
+ import {
4
+ type ActionGate,
5
+ readStringParam,
6
+ type DiscordActionConfig,
7
+ type AutoBotConfig,
8
+ withNormalizedTimestamp,
9
+ } from "../runtime-api.js";
10
+ import type { DiscordReactOpts } from "../send.types.js";
11
+ import { discordMessagingActionRuntime } from "./runtime.messaging.runtime.js";
12
+ import { createDiscordActionOptions } from "./runtime.shared.js";
13
+
14
+ export type DiscordMessagingActionOptions = {
15
+ mediaAccess?: {
16
+ localRoots?: readonly string[];
17
+ readFile?: (filePath: string) => Promise<Buffer>;
18
+ workspaceDir?: string;
19
+ };
20
+ mediaLocalRoots?: readonly string[];
21
+ mediaReadFile?: (filePath: string) => Promise<Buffer>;
22
+ };
23
+
24
+ export type DiscordMessagingActionContext = {
25
+ action: string;
26
+ params: Record<string, unknown>;
27
+ isActionEnabled: ActionGate<DiscordActionConfig>;
28
+ cfg: AutoBotConfig;
29
+ options?: DiscordMessagingActionOptions;
30
+ accountId?: string;
31
+ resolveChannelId: () => string;
32
+ resolveReactionChannelId: () => Promise<string>;
33
+ withOpts: (extra?: Record<string, unknown>) => { cfg: AutoBotConfig; accountId?: string };
34
+ withReactionRuntimeOptions: <T extends Record<string, unknown> = Record<string, never>>(
35
+ extra?: T,
36
+ ) => DiscordReactOpts & T;
37
+ normalizeMessage: (message: unknown) => unknown;
38
+ };
39
+
40
+ export function createDiscordMessagingActionContext(params: {
41
+ action: string;
42
+ input: Record<string, unknown>;
43
+ isActionEnabled: ActionGate<DiscordActionConfig>;
44
+ cfg: AutoBotConfig;
45
+ options?: DiscordMessagingActionOptions;
46
+ }): DiscordMessagingActionContext {
47
+ const accountId = readStringParam(params.input, "accountId");
48
+ const cfgOptions = { cfg: params.cfg };
49
+ const withOpts = (extra?: Record<string, unknown>) =>
50
+ createDiscordActionOptions({ cfg: params.cfg, accountId, extra });
51
+ const resolvedReactionAccountId = accountId ?? resolveDefaultDiscordAccountId(params.cfg);
52
+ const reactionRuntimeOptions = resolvedReactionAccountId
53
+ ? createDiscordRuntimeAccountContext({
54
+ cfg: params.cfg,
55
+ accountId: resolvedReactionAccountId,
56
+ })
57
+ : cfgOptions;
58
+ return {
59
+ action: params.action,
60
+ params: params.input,
61
+ isActionEnabled: params.isActionEnabled,
62
+ cfg: params.cfg,
63
+ options: params.options,
64
+ accountId,
65
+ resolveChannelId: () =>
66
+ discordMessagingActionRuntime.resolveDiscordChannelId(
67
+ readStringParam(params.input, "channelId", {
68
+ required: true,
69
+ }),
70
+ ),
71
+ resolveReactionChannelId: async () => {
72
+ const target =
73
+ readStringParam(params.input, "channelId") ??
74
+ readStringParam(params.input, "to", { required: true });
75
+ return await discordMessagingActionRuntime.resolveDiscordReactionTargetChannelId({
76
+ target,
77
+ cfg: params.cfg,
78
+ accountId: resolvedReactionAccountId,
79
+ });
80
+ },
81
+ withOpts,
82
+ withReactionRuntimeOptions: (extra) =>
83
+ ({
84
+ ...(reactionRuntimeOptions ?? cfgOptions),
85
+ ...extra,
86
+ }) as DiscordReactOpts & NonNullable<typeof extra>,
87
+ normalizeMessage: (message: unknown) => {
88
+ if (!message || typeof message !== "object") {
89
+ return message;
90
+ }
91
+ return withNormalizedTimestamp(
92
+ message as Record<string, unknown>,
93
+ (message as { timestamp?: unknown }).timestamp,
94
+ );
95
+ },
96
+ };
97
+ }
@@ -0,0 +1,37 @@
1
+ import type { AgentToolResult } from "@earendil-works/pi-agent-core";
2
+ import type { ActionGate, DiscordActionConfig, AutoBotConfig } from "../runtime-api.js";
3
+ import { handleDiscordMessageManagementAction } from "./runtime.messaging.messages.js";
4
+ import { handleDiscordReactionMessagingAction } from "./runtime.messaging.reactions.js";
5
+ import { handleDiscordMessageSendAction } from "./runtime.messaging.send.js";
6
+ import {
7
+ createDiscordMessagingActionContext,
8
+ type DiscordMessagingActionOptions,
9
+ } from "./runtime.messaging.shared.js";
10
+ export { discordMessagingActionRuntime } from "./runtime.messaging.runtime.js";
11
+
12
+ export async function handleDiscordMessagingAction(
13
+ action: string,
14
+ params: Record<string, unknown>,
15
+ isActionEnabled: ActionGate<DiscordActionConfig>,
16
+ cfg: AutoBotConfig,
17
+ options?: DiscordMessagingActionOptions,
18
+ ): Promise<AgentToolResult<unknown>> {
19
+ if (!cfg) {
20
+ throw new Error("Discord messaging actions require a resolved runtime config.");
21
+ }
22
+ const ctx = createDiscordMessagingActionContext({
23
+ action,
24
+ input: params,
25
+ isActionEnabled,
26
+ cfg,
27
+ options,
28
+ });
29
+ return (
30
+ (await handleDiscordReactionMessagingAction(ctx)) ??
31
+ (await handleDiscordMessageSendAction(ctx)) ??
32
+ (await handleDiscordMessageManagementAction(ctx)) ??
33
+ (() => {
34
+ throw new Error(`Unknown action: ${action}`);
35
+ })()
36
+ );
37
+ }
@@ -0,0 +1,48 @@
1
+ import { PermissionFlagsBits } from "discord-api-types/v10";
2
+ import { readNumberParam, readStringParam } from "../runtime-api.js";
3
+
4
+ export type DiscordModerationAction = "timeout" | "kick" | "ban";
5
+
6
+ export type DiscordModerationCommand = {
7
+ action: DiscordModerationAction;
8
+ guildId: string;
9
+ userId: string;
10
+ durationMinutes?: number;
11
+ until?: string;
12
+ reason?: string;
13
+ deleteMessageDays?: number;
14
+ };
15
+
16
+ const moderationPermissions: Record<DiscordModerationAction, bigint> = {
17
+ timeout: PermissionFlagsBits.ModerateMembers,
18
+ kick: PermissionFlagsBits.KickMembers,
19
+ ban: PermissionFlagsBits.BanMembers,
20
+ };
21
+
22
+ export function isDiscordModerationAction(action: string): action is DiscordModerationAction {
23
+ return action === "timeout" || action === "kick" || action === "ban";
24
+ }
25
+
26
+ export function requiredGuildPermissionForModerationAction(
27
+ action: DiscordModerationAction,
28
+ ): bigint {
29
+ return moderationPermissions[action];
30
+ }
31
+
32
+ export function readDiscordModerationCommand(
33
+ action: string,
34
+ params: Record<string, unknown>,
35
+ ): DiscordModerationCommand {
36
+ if (!isDiscordModerationAction(action)) {
37
+ throw new Error(`Unsupported Discord moderation action: ${action}`);
38
+ }
39
+ return {
40
+ action,
41
+ guildId: readStringParam(params, "guildId", { required: true }),
42
+ userId: readStringParam(params, "userId", { required: true }),
43
+ durationMinutes: readNumberParam(params, "durationMinutes", { integer: true }),
44
+ until: readStringParam(params, "until"),
45
+ reason: readStringParam(params, "reason"),
46
+ deleteMessageDays: readNumberParam(params, "deleteMessageDays", { integer: true }),
47
+ };
48
+ }