@openclaw/discord 2026.8.1-beta.2 → 2026.8.1-beta.3

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 (100) hide show
  1. package/dist/{account-inspect-CqzrH14k.js → account-inspect-D5xmUpnj.js} +1 -1
  2. package/dist/account-inspect-api.js +1 -1
  3. package/dist/accounts-DNl-oCEw.js +371 -0
  4. package/dist/action-runtime-api.js +1 -1
  5. package/dist/{activities-api-DS7vpdtp.js → activities-api-KCBAmWxD.js} +133 -175
  6. package/dist/activities-api.js +1 -1
  7. package/dist/api.js +17 -17
  8. package/dist/{approval-handler.runtime-B6yEV79q.js → approval-handler.runtime-B12RCYr8.js} +6 -6
  9. package/dist/{approval-message-safety-AcIxvrf3.js → approval-message-safety-XGFPbDoI.js} +89 -3
  10. package/dist/{audit-Db-rlntl.js → audit-Yc7eZDd6.js} +5 -5
  11. package/dist/{channel-actions-5s_hjYKd.js → channel-actions-Dr2QI8Bf.js} +10 -6
  12. package/dist/{channel-actions.runtime-CLKrx6tr.js → channel-actions.runtime-CODTvo7c.js} +53 -68
  13. package/dist/{channel-CnnbJSt5.js → channel-cXYzGc4L.js} +74 -50
  14. package/dist/channel-config-api.js +1 -1
  15. package/dist/channel-plugin-api.js +1 -1
  16. package/dist/{channel.setup-BFAO-V1P.js → channel.setup-CSiwnMgs.js} +5 -5
  17. package/dist/{outbound-session-route-DxLkrgKQ.js → components-ezGKo_Yh.js} +3 -49
  18. package/dist/{config-schema-BgEskFAs.js → config-schema-DC5kDtQ5.js} +33 -7
  19. package/dist/conversation-binding-route-D6rCQ5S0.js +43 -0
  20. package/dist/{directory-config-BVX7Cflc.js → directory-config-XyCfoqLg.js} +2 -2
  21. package/dist/directory-contract-api.js +1 -1
  22. package/dist/{directory-live-DGIGxpIo.js → directory-live-Df0NbFJB.js} +3 -3
  23. package/dist/{doctor-BzC-TLnB.js → doctor-DYY31GrO.js} +33 -12
  24. package/dist/doctor-contract-api.js +3 -3
  25. package/dist/{handle-action.guild-admin-BNVTUISF.js → handle-action.guild-admin-6Tvvinsa.js} +2 -2
  26. package/dist/index.js +3 -4
  27. package/dist/{message-handler-Unk_f10F.js → message-handler-B61q5MOF.js} +82 -6
  28. package/dist/{message-handler.preflight-C9zecxR9.js → message-handler.preflight-Bzg_Hawz.js} +36 -46
  29. package/dist/{message-handler.process-DWQ6UHHu.js → message-handler.process--4_712Ec.js} +159 -183
  30. package/dist/{message-utils-BSCPVgy0.js → message-utils-BXLLnFl6.js} +31 -32
  31. package/dist/{outbound-adapter-D9nRivT1.js → outbound-adapter-DxHTOqiN.js} +83 -53
  32. package/dist/{outbound-components-cTzwBJ60.js → outbound-components-B2PL0ooH.js} +3 -3
  33. package/dist/owner-access-Bg41VzAf.js +107 -0
  34. package/dist/{pluralkit-DdiJ9KMK.js → pluralkit-dUl4v1X3.js} +1 -1
  35. package/dist/{probe-Bl-k5_Ku.js → probe-BTdtVRwU.js} +1 -1
  36. package/dist/{probe.runtime-M9fREKvp.js → probe.runtime-Dq5-PRKT.js} +1 -1
  37. package/dist/{provider-DvSNb-2v.js → provider-DlK_ynqt.js} +356 -967
  38. package/dist/{provider-session.runtime-BUEqD0rA.js → provider-session.runtime-CvvphHvs.js} +3 -3
  39. package/dist/provider.runtime-CzKGRiAF.js +2 -0
  40. package/dist/{realtime-session.runtime-C7wen-aF.js → realtime-session.runtime-ysbMG8v7.js} +24 -13
  41. package/dist/{resolve-allowlist-common-D04lpEzb.js → resolve-allowlist-common-DIVXbD1P.js} +2 -2
  42. package/dist/{resolve-channels-Dm7jEeg6.js → resolve-channels-CGeUoIqb.js} +3 -3
  43. package/dist/{resolve-users-bktrCUUU.js → resolve-users-BtKxLUZv.js} +2 -2
  44. package/dist/{retry-CLpJcXXf.js → retry-DNsVTeTo.js} +18 -64
  45. package/dist/{runtime-DoHjckYm.js → runtime-CQovMsH3.js} +9 -10
  46. package/dist/{runtime-DGsSyDTS.js → runtime-D71_VFLr.js} +29 -43
  47. package/dist/runtime-api.actions.js +2 -2
  48. package/dist/runtime-api.js +22 -21
  49. package/dist/runtime-api.lookup.js +5 -5
  50. package/dist/runtime-api.monitor-CzeTYF32.js +6 -0
  51. package/dist/runtime-api.monitor.js +6 -5
  52. package/dist/runtime-api.send.js +6 -6
  53. package/dist/runtime-api.threads.js +4 -4
  54. package/dist/{sdk-runtime-QpY8PvCh.js → sdk-runtime-37OU6_Yh.js} +3 -4
  55. package/dist/{secret-config-contract-B1akrlyY.js → secret-config-contract-B3i6WxV5.js} +53 -25
  56. package/dist/secret-contract-api.js +1 -1
  57. package/dist/security-audit-contract-api.js +1 -1
  58. package/dist/{security-audit.runtime-CPN0xFYz.js → security-audit.runtime-BVKF9VtY.js} +1 -1
  59. package/dist/{send-B7Q6Oc1I.js → send-rQIffSYu.js} +10 -10
  60. package/dist/{send.components-iJyFXw9L.js → send.components-ChK1wS7w.js} +14 -24
  61. package/dist/{send.outbound-DS5tHwfR.js → send.outbound-HIkgji_7.js} +26 -16
  62. package/dist/{send.reactions-BAn0iiVQ.js → send.reactions-gmJ6yFPo.js} +2 -2
  63. package/dist/{send.receipt-IPI1p-SP.js → send.receipt-Cnhoautb.js} +11 -1
  64. package/dist/{send.shared-BmwFjW6T.js → send.shared-B3fpaLWJ.js} +104 -104
  65. package/dist/{sender-identity-QtalnCYv.js → sender-identity-BJtfyise.js} +1 -1
  66. package/dist/setup-plugin-api.js +1 -1
  67. package/dist/{shared-BIXIX6uJ.js → shared-CaAaoksy.js} +15 -10
  68. package/dist/subagent-hooks-CNT2ZJTJ.js +49 -0
  69. package/dist/subagent-hooks-api.js +2 -2
  70. package/dist/{subagent-progress-DhaE_h8a.js → subagent-progress-FPLqBY1s.js} +5 -4
  71. package/dist/{system-events-CTqDf6_s.js → system-events-Nuwoq_au.js} +2 -2
  72. package/dist/{target-resolver-maOKSqO0.js → target-resolver-DIXShHaZ.js} +3 -3
  73. package/dist/targets-B2pf49zc.js +3 -0
  74. package/dist/{thread-bindings-3L8p82GV.js → thread-bindings-VlymUnbz.js} +29 -26
  75. package/dist/{thread-bindings.manager-DCIH6WDC.js → thread-bindings.manager-CngsgErq.js} +9 -8
  76. package/dist/{thread-bindings.session-updates-bJ2KQFY6.js → thread-bindings.session-updates-CJb-BpPL.js} +1 -1
  77. package/dist/{thread-bindings.state-aeV8HNgV.js → thread-bindings.state-D8OMdk4O.js} +1 -1
  78. package/dist/threading-DU6pgeGm.js +456 -0
  79. package/dist/transcripts-source-DeIMNbRh.js +265 -0
  80. package/dist/transcripts-source-api.js +7 -2
  81. package/dist/{typing-CS-nNVoe.js → typing-oLiS5Z13.js} +1 -1
  82. package/dist/{voice-runtime-BEdqNcST.js → voice-runtime-CjNFaynA.js} +181 -91
  83. package/openclaw.plugin.json +12 -6
  84. package/package.json +4 -6
  85. package/dist/accounts-DJTf1LtA.js +0 -219
  86. package/dist/channel-api-CAJ0wMoV.js +0 -21
  87. package/dist/provider.runtime-C9PnJZbZ.js +0 -2
  88. package/dist/runtime-api.monitor-CHxrFPnW.js +0 -5
  89. package/dist/subagent-hooks-CTt5KCJr.js +0 -120
  90. package/dist/targets-yUFTHoAx.js +0 -3
  91. package/dist/transcripts-source-CfFMexGt.js +0 -123
  92. package/node_modules/p-map/index.d.ts +0 -155
  93. package/node_modules/p-map/index.js +0 -285
  94. package/node_modules/p-map/license +0 -9
  95. package/node_modules/p-map/package.json +0 -57
  96. package/node_modules/p-map/readme.md +0 -190
  97. package/dist/{allow-list-DnxIlPP2.js → allow-list-BDMimASD.js} +1 -1
  98. package/dist/{audit-core-xwjIczO0.js → audit-core-BCX8UeFH.js} +1 -1
  99. package/dist/{doctor-contract-DLa-BTiU.js → doctor-contract-DsWvKIXF.js} +1 -1
  100. package/dist/{security-audit-jGnJF__m.js → security-audit-BfJhAXZp.js} +1 -1
@@ -0,0 +1,43 @@
1
+ import { c as shouldIgnoreStaleDiscordRouteBinding } from "./approval-message-safety-XGFPbDoI.js";
2
+ import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
3
+ import { resolveConfiguredBindingRoute, resolveRuntimeConversationBindingRoute } from "openclaw/plugin-sdk/conversation-binding-runtime";
4
+ //#region extensions/discord/src/monitor/conversation-binding-route.ts
5
+ function resolveDiscordConversationBindingRoute(params) {
6
+ let runtimeRoute = resolveRuntimeConversationBindingRoute({
7
+ route: params.route,
8
+ touchBinding: params.touchBinding,
9
+ conversation: {
10
+ channel: "discord",
11
+ accountId: params.accountId,
12
+ conversationId: params.runtimeConversationId,
13
+ parentConversationId: params.parentConversationId
14
+ }
15
+ });
16
+ if (shouldIgnoreStaleDiscordRouteBinding({
17
+ bindingRecord: runtimeRoute.bindingRecord,
18
+ route: params.route
19
+ })) {
20
+ logVerbose(`discord: ignoring stale route binding for conversation ${params.runtimeConversationId} (${runtimeRoute.bindingRecord?.targetSessionKey} -> ${params.route.sessionKey})`);
21
+ runtimeRoute = {
22
+ bindingOwnerAvailable: true,
23
+ bindingRecord: null,
24
+ route: params.route
25
+ };
26
+ }
27
+ const configuredRoute = runtimeRoute.bindingRecord ? null : resolveConfiguredBindingRoute({
28
+ cfg: params.cfg,
29
+ route: params.route,
30
+ conversation: {
31
+ channel: "discord",
32
+ accountId: params.accountId,
33
+ conversationId: params.configuredConversationId,
34
+ parentConversationId: params.parentConversationId
35
+ }
36
+ });
37
+ return {
38
+ runtimeRoute,
39
+ configuredRoute
40
+ };
41
+ }
42
+ //#endregion
43
+ export { resolveDiscordConversationBindingRoute as t };
@@ -1,5 +1,5 @@
1
- import { tn as __exportAll } from "./retry-CLpJcXXf.js";
2
- import { a as mergeDiscordAccountConfig, c as resolveDiscordAccountAllowFrom, o as resolveDefaultDiscordAccountId } from "./accounts-DJTf1LtA.js";
1
+ import { en as __exportAll } from "./retry-DNsVTeTo.js";
2
+ import { l as resolveDiscordAccountAllowFrom, o as mergeDiscordAccountConfig, s as resolveDefaultDiscordAccountId } from "./accounts-DNl-oCEw.js";
3
3
  import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
4
4
  import { createResolvedDirectoryEntriesLister } from "openclaw/plugin-sdk/directory-config-runtime";
5
5
  //#region extensions/discord/src/directory-config.ts
@@ -1,4 +1,4 @@
1
- import { n as listDiscordDirectoryGroupsFromConfig, r as listDiscordDirectoryPeersFromConfig } from "./directory-config-BVX7Cflc.js";
1
+ import { n as listDiscordDirectoryGroupsFromConfig, r as listDiscordDirectoryPeersFromConfig } from "./directory-config-XyCfoqLg.js";
2
2
  //#region extensions/discord/directory-contract-api.ts
3
3
  const discordDirectoryContractPlugin = {
4
4
  id: "discord",
@@ -1,7 +1,7 @@
1
- import { tn as __exportAll } from "./retry-CLpJcXXf.js";
2
- import { p as normalizeDiscordToken, s as resolveDiscordAccount } from "./accounts-DJTf1LtA.js";
1
+ import { en as __exportAll } from "./retry-DNsVTeTo.js";
2
+ import { c as resolveDiscordAccount, m as normalizeDiscordToken } from "./accounts-DNl-oCEw.js";
3
3
  import { r as fetchDiscord, t as DISCORD_DIRECTORY_LOOKUP_TIMEOUT_MS } from "./api-DNVbJyEy.js";
4
- import { a as normalizeDiscordSlug } from "./allow-list-DnxIlPP2.js";
4
+ import { a as normalizeDiscordSlug } from "./allow-list-BDMimASD.js";
5
5
  import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/routing";
6
6
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeOptionalStringifiedId } from "openclaw/plugin-sdk/string-coerce-runtime";
7
7
  //#region extensions/discord/src/directory-cache-state.ts
@@ -1,10 +1,11 @@
1
- import { o as resolveDefaultDiscordAccountId } from "./accounts-DJTf1LtA.js";
2
- import { t as inspectDiscordAccount } from "./account-inspect-CqzrH14k.js";
3
- import { r as DISCORD_LEGACY_CONFIG_RULES } from "./shared-BIXIX6uJ.js";
4
- import { n as normalizeCompatibilityConfig } from "./doctor-contract-DLa-BTiU.js";
1
+ import { s as resolveDefaultDiscordAccountId } from "./accounts-DNl-oCEw.js";
2
+ import { t as discordVoiceTranscriptsSourceProvider } from "./transcripts-source-DeIMNbRh.js";
3
+ import { t as inspectDiscordAccount } from "./account-inspect-D5xmUpnj.js";
4
+ import { r as DISCORD_LEGACY_CONFIG_RULES } from "./shared-CaAaoksy.js";
5
+ import { n as normalizeCompatibilityConfig } from "./doctor-contract-DsWvKIXF.js";
5
6
  import { t as isDiscordMutableAllowEntry } from "./security-doctor-nGgPm65L.js";
6
- import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
7
7
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
8
+ import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
8
9
  import { asObjectRecord, collectChannelAccountScopes, collectProviderDangerousNameMatchingScopes } from "openclaw/plugin-sdk/runtime-doctor-migrations";
9
10
  //#region extensions/discord/src/doctor.ts
10
11
  function sanitizeForLog(value) {
@@ -165,6 +166,22 @@ function collectDiscordMissingEnvTokenWarnings(params) {
165
166
  if (!account.enabled || account.tokenStatus !== "missing" || account.tokenSource !== "none") return [];
166
167
  return ["- channels.discord: default account has no available bot token, and DISCORD_BOT_TOKEN is absent in this doctor environment. After migration, verify DISCORD_BOT_TOKEN is present in the state-dir .env or configure channels.discord.token / channels.discord.accounts.default.token as a SecretRef."];
167
168
  }
169
+ function collectDiscordTranscriptsAutoStartWarnings(cfg) {
170
+ if (cfg.transcripts?.enabled === false || !Array.isArray(cfg.transcripts?.autoStart)) return [];
171
+ const ownership = discordVoiceTranscriptsSourceProvider.accessControl;
172
+ if (!ownership) return [];
173
+ return cfg.transcripts.autoStart.flatMap((entry, index) => {
174
+ const providerId = normalizeOptionalString(entry.providerId)?.toLowerCase();
175
+ if (providerId !== discordVoiceTranscriptsSourceProvider.id && !discordVoiceTranscriptsSourceProvider.aliases?.includes(providerId ?? "") || normalizeOptionalString(entry.accountId)) return [];
176
+ const resolution = ownership.resolveAccountId({
177
+ cfg,
178
+ source: entry
179
+ });
180
+ if (resolution.ok) return [];
181
+ const path = `transcripts.autoStart[${index}]`;
182
+ return [`- ${path} cannot select a Discord voice account: ${resolution.error} Set ${path}.accountId to the intended enabled voice account, or set channels.discord.defaultAccount when one account should be the global default.`];
183
+ });
184
+ }
168
185
  function collectDiscordMutableAllowlistWarnings(cfg) {
169
186
  const hits = [];
170
187
  const addHits = (pathLabel, list) => {
@@ -215,13 +232,17 @@ const discordDoctor = {
215
232
  warnOnEmptyGroupSenderAllowlist: false,
216
233
  legacyConfigRules: DISCORD_LEGACY_CONFIG_RULES,
217
234
  normalizeCompatibilityConfig,
218
- collectPreviewWarnings: ({ cfg, doctorFixCommand, env }) => [...collectDiscordMissingEnvTokenWarnings({
219
- cfg,
220
- env
221
- }), ...collectDiscordNumericIdWarnings({
222
- hits: scanDiscordNumericIdEntries(cfg),
223
- doctorFixCommand
224
- })],
235
+ collectPreviewWarnings: ({ cfg, doctorFixCommand, env }) => [
236
+ ...collectDiscordMissingEnvTokenWarnings({
237
+ cfg,
238
+ env
239
+ }),
240
+ ...collectDiscordNumericIdWarnings({
241
+ hits: scanDiscordNumericIdEntries(cfg),
242
+ doctorFixCommand
243
+ }),
244
+ ...collectDiscordTranscriptsAutoStartWarnings(cfg)
245
+ ],
225
246
  collectMutableAllowlistWarnings: ({ cfg }) => collectDiscordMutableAllowlistWarnings(cfg),
226
247
  repairConfig: ({ cfg, doctorFixCommand }) => maybeRepairDiscordNumericIds(cfg, doctorFixCommand)
227
248
  };
@@ -1,10 +1,10 @@
1
1
  import { n as DISCORD_COMMAND_DEPLOY_HASH_NAMESPACE, t as DISCORD_COMMAND_DEPLOY_HASH_MAX_ENTRIES } from "./command-deploy-store-DFkBTViB.js";
2
- import { a as THREAD_BINDINGS_MAX_ENTRIES, d as normalizePersistedBinding, k as toBindingRecordKey, o as THREAD_BINDINGS_NAMESPACE } from "./thread-bindings.state-aeV8HNgV.js";
3
- import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-DLa-BTiU.js";
2
+ import { a as THREAD_BINDINGS_MAX_ENTRIES, d as normalizePersistedBinding, k as toBindingRecordKey, o as THREAD_BINDINGS_NAMESPACE } from "./thread-bindings.state-D8OMdk4O.js";
3
+ import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-DsWvKIXF.js";
4
4
  import { i as sanitizeRecentModels, r as preferenceTimestampMs, t as buildPreferenceModelKey } from "./model-picker-preference-primitives-BHT1LkR_.js";
5
5
  import { MAX_DATE_TIMESTAMP_MS, timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
6
- import path from "node:path";
7
6
  import { definePluginDoctorMigrationFromPlans } from "openclaw/plugin-sdk/runtime-doctor-migrations";
7
+ import path from "node:path";
8
8
  import fs from "node:fs";
9
9
  //#region extensions/discord/src/monitor/model-picker-preferences-migrations.ts
10
10
  const PREFERENCE_MAX_ENTRIES = 2e3;
@@ -1,6 +1,6 @@
1
- import { c as readDiscordChannelMoveParams, n as isDiscordModerationAction, o as readDiscordChannelCreateParams, r as readDiscordModerationCommand, s as readDiscordChannelEditParams, t as handleDiscordAction } from "./runtime-DGsSyDTS.js";
1
+ import { c as readDiscordChannelMoveParams, n as isDiscordModerationAction, o as readDiscordChannelCreateParams, r as readDiscordModerationCommand, s as readDiscordChannelEditParams, t as handleDiscordAction } from "./runtime-D71_VFLr.js";
2
2
  import "./action-runtime-api.js";
3
- import { n as isTrustedRequesterGuildAdminAction } from "./channel-actions-5s_hjYKd.js";
3
+ import { n as isTrustedRequesterGuildAdminAction } from "./channel-actions-Dr2QI8Bf.js";
4
4
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  import { readNonNegativeIntegerParam, readPositiveIntegerParam, readStringArrayParam, readStringParam } from "openclaw/plugin-sdk/agent-runtime";
6
6
  //#region extensions/discord/src/actions/handle-action.guild-admin.ts
package/dist/index.js CHANGED
@@ -1,7 +1,6 @@
1
- import { t as registerDiscordActivities } from "./activities-api-DS7vpdtp.js";
1
+ import { t as registerDiscordActivities } from "./activities-api-KCBAmWxD.js";
2
2
  import { registerDiscordSubagentHooks } from "./subagent-hooks-api.js";
3
- import { t as discordVoiceTranscriptsSourceProvider } from "./transcripts-source-CfFMexGt.js";
4
- import "./transcripts-source-api.js";
3
+ import { registerDiscordTranscriptSourceProvider } from "./transcripts-source-api.js";
5
4
  import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
6
5
  //#region extensions/discord/index.ts
7
6
  var discord_default = defineBundledChannelEntry({
@@ -26,7 +25,7 @@ var discord_default = defineBundledChannelEntry({
26
25
  registerDiscordSubagentHooks(api);
27
26
  },
28
27
  registerCapabilities(api) {
29
- api.registerTranscriptSourceProvider(discordVoiceTranscriptsSourceProvider);
28
+ registerDiscordTranscriptSourceProvider(api);
30
29
  }
31
30
  });
32
31
  //#endregion
@@ -1,13 +1,15 @@
1
1
  import { t as getDiscordRuntime } from "./runtime-DgnVQ7zW.js";
2
- import { c as resolveDiscordChannelInfoSafe, d as resolveDiscordChannelParentSafe, l as resolveDiscordChannelNameSafe, s as resolveDiscordChannelIdSafe } from "./thread-bindings.manager-DCIH6WDC.js";
3
- import { w as mapGatewayDispatchData } from "./provider-DvSNb-2v.js";
4
- import { f as resolveDiscordMessageChannelId, i as resolveDiscordMessageText, l as hasDiscordMessageStickers } from "./message-utils-BSCPVgy0.js";
5
- import { normalizeNullableString } from "openclaw/plugin-sdk/string-coerce-runtime";
2
+ import { c as resolveDiscordChannelInfoSafe, d as resolveDiscordChannelParentSafe, l as resolveDiscordChannelNameSafe, s as resolveDiscordChannelIdSafe } from "./thread-bindings.manager-CngsgErq.js";
3
+ import { _ as mapGatewayDispatchData } from "./provider-DlK_ynqt.js";
4
+ import { i as resolveDiscordMessageText, l as resolveDiscordCdnPolicy, p as resolveDiscordMessageChannelId, u as hasDiscordMessageStickers } from "./message-utils-BXLLnFl6.js";
5
+ import { logDebug } from "openclaw/plugin-sdk/logging-core";
6
6
  import { GatewayDispatchEvents } from "discord-api-types/v10";
7
7
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
8
+ import { normalizeNullableString } from "openclaw/plugin-sdk/string-coerce-runtime";
8
9
  import { danger } from "openclaw/plugin-sdk/runtime-env";
9
10
  import { resolveBatchedReplyThreadingPolicy } from "openclaw/plugin-sdk/reply-reference";
10
11
  import { DEFAULT_INGRESS_RETRY_MAX_ATTEMPTS, createChannelIngressError, createChannelIngressMonitor, createChannelRunQueue } from "openclaw/plugin-sdk/channel-outbound";
12
+ import { saveRemoteMedia } from "openclaw/plugin-sdk/media-runtime";
11
13
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
12
14
  import { resolveOpenProviderRuntimeGroupPolicy } from "openclaw/plugin-sdk/runtime-group-policy";
13
15
  import { fanInChannelIngressLifecycles } from "openclaw/plugin-sdk/channel-ingress-runtime";
@@ -167,6 +169,77 @@ function normalizeDiscordThreadChannel(threadChannel) {
167
169
  };
168
170
  }
169
171
  //#endregion
172
+ //#region extensions/discord/src/monitor/message-avatar.ts
173
+ const DISCORD_AVATAR_MAX_BYTES = 256 * 1024;
174
+ const DISCORD_AVATAR_CACHE_MAX_ENTRIES = 128;
175
+ const DISCORD_GUILD_ICON_TTL_MS = 5 * 6e4;
176
+ function setBoundedEntry(map, key, value) {
177
+ map.delete(key);
178
+ map.set(key, value);
179
+ while (map.size > DISCORD_AVATAR_CACHE_MAX_ENTRIES) {
180
+ const oldest = map.keys().next().value;
181
+ if (oldest === void 0) break;
182
+ map.delete(oldest);
183
+ }
184
+ }
185
+ function discordAvatarUrl(owner, id, hash) {
186
+ return `https://cdn.discordapp.com/${owner}/${id}/${hash}.png?size=128`;
187
+ }
188
+ /** Dispatcher-lifetime resolver for eventually available Discord conversation images. */
189
+ function createDiscordAvatarResolver() {
190
+ const saved = /* @__PURE__ */ new Map();
191
+ const pending = /* @__PURE__ */ new Set();
192
+ const guildIcons = /* @__PURE__ */ new Map();
193
+ const pendingGuilds = /* @__PURE__ */ new Set();
194
+ const resolveSavedAvatar = (key, url) => {
195
+ const cached = saved.get(key);
196
+ if (cached) {
197
+ saved.delete(key);
198
+ saved.set(key, cached);
199
+ return cached;
200
+ }
201
+ if (pending.has(key) || pending.size >= DISCORD_AVATAR_CACHE_MAX_ENTRIES) return;
202
+ pending.add(key);
203
+ saveRemoteMedia({
204
+ url,
205
+ filePathHint: "conversation-avatar.png",
206
+ maxBytes: DISCORD_AVATAR_MAX_BYTES,
207
+ ssrfPolicy: resolveDiscordCdnPolicy()
208
+ }).then((media) => {
209
+ setBoundedEntry(saved, key, media.path);
210
+ }).catch((error) => {
211
+ logDebug(`discord conversation avatar download failed: ${formatErrorMessage(error)}`);
212
+ }).finally(() => {
213
+ pending.delete(key);
214
+ });
215
+ };
216
+ const refreshGuildIcon = (client, guildId, conversationId) => {
217
+ if (pendingGuilds.has(guildId) || pendingGuilds.size >= DISCORD_AVATAR_CACHE_MAX_ENTRIES) return;
218
+ pendingGuilds.add(guildId);
219
+ client.fetchGuild(guildId).then((guild) => {
220
+ const hash = guild.icon ?? null;
221
+ setBoundedEntry(guildIcons, guildId, {
222
+ expiresAt: Date.now() + DISCORD_GUILD_ICON_TTL_MS,
223
+ hash
224
+ });
225
+ if (hash) resolveSavedAvatar(`${conversationId}\0${hash}`, discordAvatarUrl("icons", guildId, hash));
226
+ }).catch((error) => {
227
+ logDebug(`discord guild icon lookup failed: ${formatErrorMessage(error)}`);
228
+ }).finally(() => {
229
+ pendingGuilds.delete(guildId);
230
+ });
231
+ };
232
+ return { resolve(params) {
233
+ if (!params.guildId) {
234
+ const hash = params.author.avatar;
235
+ return hash ? resolveSavedAvatar(`${params.conversationId}\0${hash}`, discordAvatarUrl("avatars", params.author.id, hash)) : void 0;
236
+ }
237
+ const guildIcon = guildIcons.get(params.guildId);
238
+ if (!guildIcon || guildIcon.expiresAt <= Date.now()) refreshGuildIcon(params.client, params.guildId, params.conversationId);
239
+ return guildIcon?.hash ? resolveSavedAvatar(`${params.conversationId}\0${guildIcon.hash}`, discordAvatarUrl("icons", params.guildId, guildIcon.hash)) : void 0;
240
+ } };
241
+ }
242
+ //#endregion
170
243
  //#region extensions/discord/src/monitor/message-handler.batch-gate.ts
171
244
  function applyImplicitReplyBatchGate(ctx, replyToMode, isBatched) {
172
245
  const replyThreading = resolveBatchedReplyThreadingPolicy(replyToMode, isBatched);
@@ -175,7 +248,7 @@ function applyImplicitReplyBatchGate(ctx, replyToMode, isBatched) {
175
248
  }
176
249
  //#endregion
177
250
  //#region extensions/discord/src/monitor/message-run-queue.ts
178
- const loadMessageProcessRuntime = createLazyRuntimeModule(() => import("./message-handler.process-DWQ6UHHu.js"));
251
+ const loadMessageProcessRuntime = createLazyRuntimeModule(() => import("./message-handler.process--4_712Ec.js"));
179
252
  async function processDiscordQueuedMessage(params) {
180
253
  const abortSignal = params.job.runtime.abortSignal && params.lifecycleSignal ? AbortSignal.any([params.job.runtime.abortSignal, params.lifecycleSignal]) : params.job.runtime.abortSignal ?? params.lifecycleSignal;
181
254
  try {
@@ -262,7 +335,7 @@ function createDiscordMessageRunQueue(params) {
262
335
  }
263
336
  //#endregion
264
337
  //#region extensions/discord/src/monitor/message-dispatcher.ts
265
- const loadMessagePreflightRuntime = createLazyRuntimeModule(() => import("./message-handler.preflight-C9zecxR9.js"));
338
+ const loadMessagePreflightRuntime = createLazyRuntimeModule(() => import("./message-handler.preflight-Bzg_Hawz.js"));
266
339
  function isNonEmptyString(value) {
267
340
  return typeof value === "string" && value.length > 0;
268
341
  }
@@ -281,6 +354,7 @@ function createDiscordMessageDispatcher(params) {
281
354
  testing: params.testing
282
355
  });
283
356
  const dispatcherShutdown = new AbortController();
357
+ const avatarResolver = createDiscordAvatarResolver();
284
358
  const pendingDebounceEntries = /* @__PURE__ */ new Set();
285
359
  const pendingCancellationSettlements = /* @__PURE__ */ new Set();
286
360
  const resolveDebounceKey = (entry) => {
@@ -323,6 +397,7 @@ function createDiscordMessageDispatcher(params) {
323
397
  if (entries.length === 1) {
324
398
  const ctx = await (preflightDiscordMessageImpl ?? (await loadMessagePreflightRuntime()).preflightDiscordMessage)({
325
399
  ...params,
400
+ avatarResolver,
326
401
  ackReactionScope,
327
402
  groupPolicy,
328
403
  abortSignal,
@@ -377,6 +452,7 @@ function createDiscordMessageDispatcher(params) {
377
452
  };
378
453
  const ctx = await (preflightDiscordMessageImpl ?? (await loadMessagePreflightRuntime()).preflightDiscordMessage)({
379
454
  ...params,
455
+ avatarResolver,
380
456
  ackReactionScope,
381
457
  groupPolicy,
382
458
  abortSignal,
@@ -1,18 +1,20 @@
1
- import { B as Message, Et as getChannelMessage, h as discord_exports } from "./retry-CLpJcXXf.js";
2
- import { o as resolveDefaultDiscordAccountId } from "./accounts-DJTf1LtA.js";
3
- import { C as resolveTimestampMs, S as resolveDiscordSystemLocation, _ as resolveDiscordShouldRequireMention, a as normalizeDiscordSlug, c as resolveDiscordChannelConfigWithFallback, f as resolveDiscordGuildEntry, i as normalizeDiscordDisplaySlug, n as isDiscordGroupAllowedByPolicy, p as resolveDiscordMemberAccessState, v as resolveGroupDmAllow, x as formatDiscordUserTag } from "./allow-list-DnxIlPP2.js";
1
+ import { R as Message, Tt as getChannelMessage, p as discord_exports } from "./retry-DNsVTeTo.js";
2
+ import { s as resolveDefaultDiscordAccountId } from "./accounts-DNl-oCEw.js";
3
+ import { C as resolveTimestampMs, S as resolveDiscordSystemLocation, _ as resolveDiscordShouldRequireMention, a as normalizeDiscordSlug, c as resolveDiscordChannelConfigWithFallback, f as resolveDiscordGuildEntry, i as normalizeDiscordDisplaySlug, n as isDiscordGroupAllowedByPolicy, p as resolveDiscordMemberAccessState, v as resolveGroupDmAllow, x as formatDiscordUserTag } from "./allow-list-BDMimASD.js";
4
4
  import { n as DISCORD_ATTACHMENT_TOTAL_TIMEOUT_MS, t as DISCORD_ATTACHMENT_IDLE_TIMEOUT_MS } from "./timeouts-B9cy6RvQ.js";
5
- import { r as resolveDiscordConversationIdentity } from "./approval-message-safety-AcIxvrf3.js";
6
- import { c as resolveDiscordChannelInfoSafe, l as resolveDiscordChannelNameSafe } from "./thread-bindings.manager-DCIH6WDC.js";
7
- import { C as handleDiscordDmCommandDecision, M as resolveDiscordTextCommandAccess, S as shouldIgnoreStaleDiscordRouteBinding, b as resolveDiscordConversationRoute, j as resolveDiscordDmCommandAccess, x as resolveDiscordEffectiveRoute, y as buildDiscordRoutePeer } from "./provider-DvSNb-2v.js";
8
- import { d as resolveDiscordChannelInfo, f as resolveDiscordMessageChannelId, i as resolveDiscordMessageText, o as resolveForwardedMediaList, r as resolveDiscordMessageHistoryText, s as resolveMediaList, u as resolveDiscordMessageStickers } from "./message-utils-BSCPVgy0.js";
9
- import { n as resolveDiscordWebhookId, t as resolveDiscordSenderIdentity } from "./sender-identity-QtalnCYv.js";
5
+ import { d as resolveDiscordRuntimeBindingConversationId, i as buildDiscordRoutePeer, l as resolveDiscordConversationIdentity, o as resolveDiscordConversationRoute, s as resolveDiscordEffectiveRoute } from "./approval-message-safety-XGFPbDoI.js";
6
+ import { t as resolveDiscordConversationBindingRoute } from "./conversation-binding-route-D6rCQ5S0.js";
7
+ import { c as resolveDiscordChannelInfoSafe, l as resolveDiscordChannelNameSafe } from "./thread-bindings.manager-CngsgErq.js";
8
+ import { b as resolveDiscordDmCommandAccess, g as handleDiscordDmCommandDecision, x as resolveDiscordTextCommandAccess } from "./provider-DlK_ynqt.js";
9
+ import { d as resolveDiscordMessageStickers, f as resolveDiscordChannelInfo, i as resolveDiscordMessageText, o as resolveForwardedMediaList, p as resolveDiscordMessageChannelId, r as resolveDiscordMessageHistoryText, s as resolveMediaList } from "./message-utils-BXLLnFl6.js";
10
+ import { n as resolveDiscordWebhookId, t as resolveDiscordSenderIdentity } from "./sender-identity-BJtfyise.js";
10
11
  import { t as createDiscordHistorySenderProvenance } from "./message-handler.history-CJOsN9w5.js";
11
- import { normalizeOptionalString, readStringValue } from "openclaw/plugin-sdk/string-coerce-runtime";
12
12
  import { logDebug } from "openclaw/plugin-sdk/logging-core";
13
13
  import { MessageReferenceType, MessageType } from "discord-api-types/v10";
14
- import { getChildLogger, logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
14
+ import { normalizeOptionalString, readStringValue } from "openclaw/plugin-sdk/string-coerce-runtime";
15
15
  import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
16
+ import { mimeTypeFromFilePath } from "openclaw/plugin-sdk/media-mime";
17
+ import { getChildLogger, logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
16
18
  import { formatAllowlistMatchMeta } from "openclaw/plugin-sdk/allow-from";
17
19
  import { findCodeRegions, isInsideCode } from "openclaw/plugin-sdk/text-chunking";
18
20
  import { isRecentOutboundMessageIdentity } from "openclaw/plugin-sdk/channel-outbound";
@@ -20,14 +22,13 @@ import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
20
22
  import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-name-runtime";
21
23
  import { enqueueRoutedSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
22
24
  import { buildMentionRegexes, classifyChannelInboundEvent, implicitMentionKindWhen, logInboundDrop, matchesMentionWithExplicit, recordChannelBotPairLoopAndCheckSuppression, resolveInboundMentionDecision, resolveUnmentionedGroupInboundPolicy, toHistoryMediaEntries, toInboundMediaFactsWithMetadata } from "openclaw/plugin-sdk/channel-inbound";
23
- import { mimeTypeFromFilePath } from "openclaw/plugin-sdk/media-mime";
24
25
  import { hasControlCommand } from "openclaw/plugin-sdk/command-detection";
25
26
  import { isAbortRequestText } from "openclaw/plugin-sdk/command-primitives-runtime";
26
27
  import { shouldHandleTextCommands } from "openclaw/plugin-sdk/command-surface";
27
28
  import { createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
28
29
  //#region extensions/discord/src/monitor/message-handler.dm-preflight.ts
29
30
  const loadConversationRuntime$1 = createLazyRuntimeModule(() => import("openclaw/plugin-sdk/conversation-binding-runtime"));
30
- const loadDiscordSendRuntime = createLazyRuntimeModule(() => import("./send-B7Q6Oc1I.js").then((n) => n.t));
31
+ const loadDiscordSendRuntime = createLazyRuntimeModule(() => import("./send-rQIffSYu.js").then((n) => n.t));
31
32
  function resolveDiscordDmPairingSenderId(sender) {
32
33
  return sender.isPluralKit ? `pk:${sender.id}` : sender.id;
33
34
  }
@@ -488,10 +489,10 @@ function logDiscordPreflightInboundSummary(params) {
488
489
  }
489
490
  //#endregion
490
491
  //#region extensions/discord/src/monitor/message-handler.preflight-runtime.ts
491
- const loadPluralKitRuntime = createLazyRuntimeModule(() => import("./pluralkit-DdiJ9KMK.js").then((n) => n.n));
492
+ const loadPluralKitRuntime = createLazyRuntimeModule(() => import("./pluralkit-dUl4v1X3.js").then((n) => n.n));
492
493
  const loadPreflightAudioRuntime = createLazyRuntimeModule(() => import("./preflight-audio-DrnqFA8U.js"));
493
- const loadSystemEventsRuntime = createLazyRuntimeModule(() => import("./system-events-CTqDf6_s.js"));
494
- const loadDiscordThreadingRuntime = createLazyRuntimeModule(() => import("./provider-DvSNb-2v.js").then((n) => n.E));
494
+ const loadSystemEventsRuntime = createLazyRuntimeModule(() => import("./system-events-Nuwoq_au.js"));
495
+ const loadDiscordThreadingRuntime = createLazyRuntimeModule(() => import("./threading-DU6pgeGm.js").then((n) => n.t));
495
496
  function isPreflightAborted(abortSignal) {
496
497
  return Boolean(abortSignal?.aborted);
497
498
  }
@@ -554,40 +555,21 @@ async function resolveDiscordPreflightRoute(params) {
554
555
  }),
555
556
  parentConversationId: params.earlyThreadParentId
556
557
  });
557
- const bindingConversationId = params.isDirectMessage ? resolveDiscordConversationIdentity({
558
- isDirectMessage: true,
559
- userId: params.author.id
560
- }) ?? `user:${params.author.id}` : params.messageChannelId;
561
- let runtimeRoute = conversationRuntime.resolveRuntimeConversationBindingRoute({
562
- route,
563
- conversation: {
564
- channel: "discord",
565
- accountId: params.preflight.accountId,
566
- conversationId: bindingConversationId,
567
- parentConversationId: params.earlyThreadParentId
568
- }
558
+ const bindingConversationId = resolveDiscordRuntimeBindingConversationId({
559
+ isDirectMessage: params.isDirectMessage,
560
+ isGroupDm: params.isGroupDm,
561
+ userId: params.author.id,
562
+ channelId: params.messageChannelId
569
563
  });
570
- if (shouldIgnoreStaleDiscordRouteBinding({
571
- bindingRecord: runtimeRoute.bindingRecord,
572
- route
573
- })) {
574
- logVerbose(`discord: ignoring stale route binding for conversation ${bindingConversationId} (${runtimeRoute.bindingRecord?.targetSessionKey} -> ${route.sessionKey})`);
575
- runtimeRoute = {
576
- bindingRecord: null,
577
- route
578
- };
579
- }
580
- let threadBinding = runtimeRoute.bindingRecord ?? void 0;
581
- const configuredRoute = threadBinding == null ? conversationRuntime.resolveConfiguredBindingRoute({
564
+ const { runtimeRoute, configuredRoute } = resolveDiscordConversationBindingRoute({
582
565
  cfg: params.preflight.cfg,
583
566
  route,
584
- conversation: {
585
- channel: "discord",
586
- accountId: params.preflight.accountId,
587
- conversationId: params.messageChannelId,
588
- parentConversationId: params.earlyThreadParentId
589
- }
590
- }) : null;
567
+ accountId: params.preflight.accountId,
568
+ runtimeConversationId: bindingConversationId,
569
+ configuredConversationId: params.messageChannelId,
570
+ parentConversationId: params.earlyThreadParentId
571
+ });
572
+ let threadBinding = runtimeRoute.bindingRecord ?? void 0;
591
573
  const configuredBinding = configuredRoute?.bindingResolution ?? null;
592
574
  if (!threadBinding && configuredBinding) threadBinding = configuredBinding.record;
593
575
  const boundSessionKey = conversationRuntime.isPluginOwnedSessionBindingRecord(threadBinding) ? "" : runtimeRoute.boundSessionKey ?? threadBinding?.targetSessionKey?.trim();
@@ -1121,6 +1103,13 @@ async function preflightDiscordMessage(params) {
1121
1103
  return null;
1122
1104
  }
1123
1105
  }
1106
+ const guildId = isGuildMessage ? data.guild?.id ?? data.guild_id ?? message.guild_id : void 0;
1107
+ const conversationAvatar = isDirectMessage || guildId ? params.avatarResolver?.resolve({
1108
+ client: params.client,
1109
+ conversationId: messageChannelId,
1110
+ author,
1111
+ ...guildId ? { guildId } : {}
1112
+ }) : void 0;
1124
1113
  const mediaResolveOptions = {
1125
1114
  fetchImpl: params.discordRestFetch,
1126
1115
  ssrfPolicy: params.cfg.browser?.ssrfPolicy,
@@ -1157,6 +1146,7 @@ async function preflightDiscordMessage(params) {
1157
1146
  ...preflightTranscript !== void 0 ? { preflightAudioTranscript: preflightTranscript } : {},
1158
1147
  preparedMedia,
1159
1148
  wasMentioned,
1149
+ conversationAvatar,
1160
1150
  route: effectiveRoute,
1161
1151
  threadBinding,
1162
1152
  boundSessionKey: boundSessionKey || void 0,