@openclaw/discord 2026.5.26 → 2026.5.27

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 (66) hide show
  1. package/dist/action-runtime-api.js +1 -1
  2. package/dist/api.js +12 -12
  3. package/dist/{approval-handler.runtime-BlGs6D0-.js → approval-handler.runtime-BDxD97LJ.js} +18 -5
  4. package/dist/{audit-DE8lNdMv.js → audit-BdUjE2tr.js} +3 -3
  5. package/dist/{channel-XYTSE8wN.js → channel-9YoMy5Jf.js} +16 -16
  6. package/dist/{channel-actions-DICb5UUl.js → channel-actions-DZfkB0nd.js} +17 -2
  7. package/dist/{channel-actions.runtime-92Esj8jy.js → channel-actions.runtime-suaDJHH0.js} +5 -5
  8. package/dist/channel-plugin-api.js +1 -1
  9. package/dist/{channel.setup-JaozRxYz.js → channel.setup-B-kHacpx.js} +3 -3
  10. package/dist/{components-Bpf9ITyn.js → components-Dlc81IU5.js} +1 -1
  11. package/dist/contract-api.js +3 -3
  12. package/dist/{conversation-identity-Be5JQPP9.js → conversation-identity-DAEgiGDV.js} +2 -2
  13. package/dist/{directory-config-oK2sOZ2m.js → directory-config-Cgp0csDd.js} +1 -1
  14. package/dist/directory-contract-api.js +1 -1
  15. package/dist/{directory-live-BRjo48ro.js → directory-live-C-ECRrM8.js} +1 -1
  16. package/dist/{doctor-DBPfLj15.js → doctor-Q80i7GdG.js} +2 -2
  17. package/dist/{doctor-contract-CLMMYrdF.js → doctor-contract-8-Ia3d_X.js} +1 -1
  18. package/dist/doctor-contract-api.js +1 -1
  19. package/dist/{handle-action.guild-admin-_LgqCYcN.js → handle-action.guild-admin-DWFTAcfd.js} +30 -12
  20. package/dist/index.js +1 -1
  21. package/dist/{manager.runtime-Bs0ngLSw.js → manager.runtime-D6V2SPKr.js} +3 -3
  22. package/dist/{message-handler-B9n5CtIS.js → message-handler-B5-UG_oD.js} +7 -7
  23. package/dist/{message-handler.preflight-Cu8cFBgW.js → message-handler.preflight-Ddww-wnF.js} +12 -13
  24. package/dist/{message-handler.process-DO17vBlT.js → message-handler.process-HWGh2NOP.js} +379 -352
  25. package/dist/{message-utils-DxHZcpPf.js → message-utils-4w0_DPFE.js} +1 -1
  26. package/dist/{outbound-adapter-C8lzfSt6.js → outbound-adapter-DYUYRaBd.js} +7 -8
  27. package/dist/{pluralkit-CTbOoDPp.js → pluralkit-BS1MuvYs.js} +1 -1
  28. package/dist/{preview-streaming-CQ7PsV9J.js → preview-streaming-DXT8oJdo.js} +1 -1
  29. package/dist/{provider-D3RwHRhI.js → provider-CO6pih5z.js} +21 -24
  30. package/dist/{provider-session.runtime-DbNYskMy.js → provider-session.runtime-BD5XLPI8.js} +3 -3
  31. package/dist/provider.runtime-pUGk7VR5.js +2 -0
  32. package/dist/{resolve-channels-CIV0C8ST.js → resolve-channels-pD06YNCU.js} +1 -1
  33. package/dist/{resolve-users-LZKYHrJx.js → resolve-users-BiWLqNNO.js} +1 -1
  34. package/dist/runtime-api.actions.js +2 -2
  35. package/dist/runtime-api.js +18 -18
  36. package/dist/runtime-api.lookup.js +4 -4
  37. package/dist/runtime-api.monitor-BjgSsR6H.js +5 -0
  38. package/dist/runtime-api.monitor.js +4 -4
  39. package/dist/runtime-api.send.js +5 -5
  40. package/dist/runtime-api.threads.js +3 -3
  41. package/dist/{runtime-DBkHf0qH.js → runtime-xSazIM0F.js} +144 -9
  42. package/dist/{send-CM1NFFrZ.js → send-BzXZ8iUI.js} +6 -3
  43. package/dist/{send.components-swKESEWc.js → send.components-AK8K4TwB.js} +4 -4
  44. package/dist/{send.outbound-BHQPWbwU.js → send.outbound-ZrMnBa8C.js} +3 -3
  45. package/dist/{send.receipt-D_6lR7zH.js → send.receipt-BzfsP3Bb.js} +1 -1
  46. package/dist/{send.shared-aYGYz83q.js → send.shared-ehnDGwXx.js} +81 -3
  47. package/dist/setup-plugin-api.js +1 -1
  48. package/dist/{shared-BwF8ShpE.js → shared-ToNRC7ax.js} +2 -2
  49. package/dist/{subagent-hooks-DHA_1pBI.js → subagent-hooks-Di_2iXU8.js} +2 -2
  50. package/dist/subagent-hooks-api.js +1 -1
  51. package/dist/{system-events-Cr3EqBah.js → system-events-DbqKnNPF.js} +1 -1
  52. package/dist/{target-resolver-CVgOsap6.js → target-resolver-DXPvq5-L.js} +2 -2
  53. package/dist/targets-BBVHRaeO.js +3 -0
  54. package/dist/test-api.js +3 -3
  55. package/dist/{thread-bindings-Dw4wcHWn.js → thread-bindings-Bw40FTRZ.js} +4 -4
  56. package/dist/{thread-bindings.discord-api-xCfun-pQ.js → thread-bindings.discord-api-irWYI8YX.js} +4 -4
  57. package/dist/{thread-bindings.manager-UJ5FvZfO.js → thread-bindings.manager-LoYZzlss.js} +3 -3
  58. package/dist/{transcripts-source-emawQzBc.js → transcripts-source-CwahHAYt.js} +1 -1
  59. package/dist/transcripts-source-api.js +1 -1
  60. package/dist/{typing-BhIpRSfR.js → typing-Cv09OhaY.js} +1 -1
  61. package/npm-shrinkwrap.json +3 -3
  62. package/openclaw.plugin.json +2 -0
  63. package/package.json +6 -6
  64. package/dist/provider.runtime-rUg1sHKP.js +0 -2
  65. package/dist/runtime-api.monitor-CUn-x5uG.js +0 -5
  66. package/dist/targets-CNDNKpqQ.js +0 -3
@@ -1,7 +1,7 @@
1
- import { At as getGuildMember, Bt as removeGuildMemberRole, C as readDiscordCode, Ct as createGuildBan, Dt as createGuildSticker, Et as createGuildScheduledEvent, Ft as listGuildRoles, It as listGuildScheduledEvents, Lt as moveGuildChannels, Mt as listGuildActiveThreads, Nt as listGuildChannels, Ot as deleteChannelPermission, Pt as listGuildEmojis, Rt as putChannelPermission, S as RateLimitError, St as addGuildMemberRole, T as readRetryAfter, Tt as createGuildEmoji, Vt as timeoutGuildMember, Wt as __exportAll, _t as listChannelPins, at as deleteOwnMessageReaction, bt as sendChannelTyping, ct as createThread, dt as editChannel, ft as editChannelMessage, gt as listChannelMessages, ht as listChannelArchivedThreads, it as createOwnMessageReaction, jt as getGuildVoiceState, kt as getGuild, lt as deleteChannel, mt as getChannelMessage, n as createDiscordSendResult, ot as listMessageReactionUsers, pt as getChannel, st as createChannelMessage, ut as deleteChannelMessage, vt as pinChannelMessage, w as readDiscordMessage, wt as createGuildChannel, x as DiscordError, xt as unpinChannelMessage, yt as searchGuildMessages, zt as removeGuildMember } from "./send.receipt-D_6lR7zH.js";
1
+ import { At as getGuildMember, Bt as removeGuildMemberRole, C as readDiscordCode, Ct as createGuildBan, Dt as createGuildSticker, Et as createGuildScheduledEvent, Ft as listGuildRoles, It as listGuildScheduledEvents, Lt as moveGuildChannels, Mt as listGuildActiveThreads, Nt as listGuildChannels, Ot as deleteChannelPermission, Pt as listGuildEmojis, Rt as putChannelPermission, S as RateLimitError, St as addGuildMemberRole, T as readRetryAfter, Tt as createGuildEmoji, Vt as timeoutGuildMember, Wt as __exportAll, _t as listChannelPins, at as deleteOwnMessageReaction, bt as sendChannelTyping, ct as createThread, dt as editChannel, ft as editChannelMessage, gt as listChannelMessages, ht as listChannelArchivedThreads, it as createOwnMessageReaction, jt as getGuildVoiceState, kt as getGuild, lt as deleteChannel, mt as getChannelMessage, n as createDiscordSendResult, ot as listMessageReactionUsers, pt as getChannel, st as createChannelMessage, ut as deleteChannelMessage, vt as pinChannelMessage, w as readDiscordMessage, wt as createGuildChannel, x as DiscordError, xt as unpinChannelMessage, yt as searchGuildMessages, zt as removeGuildMember } from "./send.receipt-BzfsP3Bb.js";
2
2
  import { s as resolveDiscordAccount } from "./accounts-dXTfmnSZ.js";
3
- import { C as DISCORD_MAX_STICKER_BYTES, D as fetchMemberGuildPermissionsDiscord, E as fetchChannelPermissionsDiscord, F as resolveDiscordClientAccountContext, I as resolveDiscordRest, M as createDiscordClient, O as hasAllGuildPermissionsDiscord, S as DISCORD_MAX_EVENT_COVER_BYTES, T as canViewDiscordGuildChannel, i as formatReactionEmoji, j as parseAndResolveChannelRecipient, k as hasAnyGuildPermissionDiscord, l as resolveChannelId, o as normalizeEmojiName, r as buildReactionIdentifier, s as normalizeReactionEmoji, t as buildDiscordSendError, w as DiscordSendError, x as DISCORD_MAX_EMOJI_BYTES } from "./send.shared-aYGYz83q.js";
4
- import { a as rewriteDiscordKnownMentions, n as sendPollDiscord, r as sendStickerDiscord, t as sendMessageDiscord } from "./send.outbound-BHQPWbwU.js";
3
+ import { A as hasAllGuildPermissionsDiscord, C as DISCORD_MAX_STICKER_BYTES, D as canViewDiscordGuildChannel, E as canManageGuildRoleDiscord, F as createDiscordClient, M as hasAnyGuildPermissionDiscord, O as fetchChannelPermissionsDiscord, P as parseAndResolveChannelRecipient, R as resolveDiscordClientAccountContext, S as DISCORD_MAX_EVENT_COVER_BYTES, T as canManageGuildMemberRoleDiscord, i as formatReactionEmoji, j as hasAnyChannelPermissionDiscord, k as fetchMemberGuildPermissionsDiscord, l as resolveChannelId, o as normalizeEmojiName, r as buildReactionIdentifier, s as normalizeReactionEmoji, t as buildDiscordSendError, w as DiscordSendError, x as DISCORD_MAX_EMOJI_BYTES, z as resolveDiscordRest } from "./send.shared-ehnDGwXx.js";
4
+ import { a as rewriteDiscordKnownMentions, n as sendPollDiscord, r as sendStickerDiscord, t as sendMessageDiscord } from "./send.outbound-ZrMnBa8C.js";
5
5
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
6
6
  import { ChannelType } from "discord-api-types/v10";
7
7
  import crypto from "node:crypto";
@@ -833,6 +833,8 @@ var send_exports = /* @__PURE__ */ __exportAll({
833
833
  DiscordThreadInitialMessageError: () => DiscordThreadInitialMessageError,
834
834
  addRoleDiscord: () => addRoleDiscord,
835
835
  banMemberDiscord: () => banMemberDiscord,
836
+ canManageGuildMemberRoleDiscord: () => canManageGuildMemberRoleDiscord,
837
+ canManageGuildRoleDiscord: () => canManageGuildRoleDiscord,
836
838
  canViewDiscordGuildChannel: () => canViewDiscordGuildChannel,
837
839
  createChannelDiscord: () => createChannelDiscord,
838
840
  createScheduledEventDiscord: () => createScheduledEventDiscord,
@@ -851,6 +853,7 @@ var send_exports = /* @__PURE__ */ __exportAll({
851
853
  fetchRoleInfoDiscord: () => fetchRoleInfoDiscord,
852
854
  fetchVoiceStatusDiscord: () => fetchVoiceStatusDiscord,
853
855
  hasAllGuildPermissionsDiscord: () => hasAllGuildPermissionsDiscord,
856
+ hasAnyChannelPermissionDiscord: () => hasAnyChannelPermissionDiscord,
854
857
  hasAnyGuildPermissionDiscord: () => hasAnyGuildPermissionDiscord,
855
858
  kickMemberDiscord: () => kickMemberDiscord,
856
859
  listGuildChannelsDiscord: () => listGuildChannelsDiscord,
@@ -1,10 +1,10 @@
1
- import { Wt as __exportAll, ft as editChannelMessage, j as serializePayload, n as createDiscordSendResult, st as createChannelMessage } from "./send.receipt-D_6lR7zH.js";
1
+ import { Wt as __exportAll, ft as editChannelMessage, j as serializePayload, n as createDiscordSendResult, st as createChannelMessage } from "./send.receipt-BzfsP3Bb.js";
2
2
  import { s as resolveDiscordAccount } from "./accounts-dXTfmnSZ.js";
3
3
  import "./config-api-JiPdJeb0.js";
4
4
  import "./channel-api-CAJ0wMoV.js";
5
- import { c as buildDiscordComponentMessage, f as resolveDiscordComponentAttachmentName, l as buildDiscordComponentMessageFlags } from "./components-Bpf9ITyn.js";
6
- import { M as createDiscordClient, b as stripUndefinedFields, h as SUPPRESS_NOTIFICATIONS_FLAG, j as parseAndResolveChannelRecipient, l as resolveChannelId, m as toDiscordFileBlob, t as buildDiscordSendError, u as resolveDiscordChannelType } from "./send.shared-aYGYz83q.js";
7
- import { t as sendMessageDiscord } from "./send.outbound-BHQPWbwU.js";
5
+ import { c as buildDiscordComponentMessage, f as resolveDiscordComponentAttachmentName, l as buildDiscordComponentMessageFlags } from "./components-Dlc81IU5.js";
6
+ import { F as createDiscordClient, P as parseAndResolveChannelRecipient, b as stripUndefinedFields, h as SUPPRESS_NOTIFICATIONS_FLAG, l as resolveChannelId, m as toDiscordFileBlob, t as buildDiscordSendError, u as resolveDiscordChannelType } from "./send.shared-ehnDGwXx.js";
7
+ import { t as sendMessageDiscord } from "./send.outbound-ZrMnBa8C.js";
8
8
  import { n as getOptionalDiscordRuntime } from "./runtime-DgnVQ7zW.js";
9
9
  import "openclaw/plugin-sdk/account-id";
10
10
  import "openclaw/plugin-sdk/secret-input";
@@ -1,7 +1,7 @@
1
- import { ct as createThread, n as createDiscordSendResult, st as createChannelMessage } from "./send.receipt-D_6lR7zH.js";
1
+ import { ct as createThread, n as createDiscordSendResult, st as createChannelMessage } from "./send.receipt-BzfsP3Bb.js";
2
2
  import { s as resolveDiscordAccount } from "./accounts-dXTfmnSZ.js";
3
- import { M as createDiscordClient, _ as resolveDiscordMessageFlags, a as normalizeDiscordPollInput, c as normalizeStickerIds, f as sendDiscordMedia, g as buildDiscordMessageRequest, j as parseAndResolveChannelRecipient, l as resolveChannelId, n as buildDiscordTextChunks, p as sendDiscordText, t as buildDiscordSendError, u as resolveDiscordChannelType, v as resolveDiscordSendComponents, y as resolveDiscordSendEmbeds } from "./send.shared-aYGYz83q.js";
4
- import { a as resolveDiscordDirectoryUserId } from "./directory-live-BRjo48ro.js";
3
+ import { F as createDiscordClient, P as parseAndResolveChannelRecipient, _ as resolveDiscordMessageFlags, a as normalizeDiscordPollInput, c as normalizeStickerIds, f as sendDiscordMedia, g as buildDiscordMessageRequest, l as resolveChannelId, n as buildDiscordTextChunks, p as sendDiscordText, t as buildDiscordSendError, u as resolveDiscordChannelType, v as resolveDiscordSendComponents, y as resolveDiscordSendEmbeds } from "./send.shared-ehnDGwXx.js";
4
+ import { a as resolveDiscordDirectoryUserId } from "./directory-live-C-ECRrM8.js";
5
5
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeOptionalStringifiedId } from "openclaw/plugin-sdk/string-coerce-runtime";
6
6
  import { ChannelType } from "discord-api-types/v10";
7
7
  import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
@@ -8,7 +8,7 @@ import { Type } from "typebox";
8
8
  import { Check } from "typebox/value";
9
9
  import { inspect } from "node:util";
10
10
  import { chunkMarkdownTextWithMode } from "openclaw/plugin-sdk/reply-chunking";
11
- import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-message";
11
+ import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
12
12
  //#region \0rolldown/runtime.js
13
13
  var __defProp = Object.defineProperty;
14
14
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -1,6 +1,6 @@
1
- import { At as getGuildMember, M as Embed, S as RateLimitError, b as RequestClient, j as serializePayload, kt as getGuild, nt as createUserDmChannel, pt as getChannel, rt as getCurrentUser, s as chunkDiscordTextWithMode, st as createChannelMessage } from "./send.receipt-D_6lR7zH.js";
1
+ import { At as getGuildMember, M as Embed, S as RateLimitError, b as RequestClient, j as serializePayload, kt as getGuild, nt as createUserDmChannel, pt as getChannel, rt as getCurrentUser, s as chunkDiscordTextWithMode, st as createChannelMessage } from "./send.receipt-BzfsP3Bb.js";
2
2
  import { a as mergeDiscordAccountConfig, p as normalizeDiscordToken, s as resolveDiscordAccount } from "./accounts-dXTfmnSZ.js";
3
- import { t as parseAndResolveDiscordTarget } from "./target-resolver-CVgOsap6.js";
3
+ import { t as parseAndResolveDiscordTarget } from "./target-resolver-DXPvq5-L.js";
4
4
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
6
6
  import { ChannelType, MessageFlags, PermissionFlagsBits } from "discord-api-types/v10";
@@ -266,6 +266,16 @@ function resolveMemberGuildPermissionBits(params) {
266
266
  }
267
267
  return permissions;
268
268
  }
269
+ function rolesById(guild) {
270
+ return new Map((guild.roles ?? []).map((role) => [role.id, role]));
271
+ }
272
+ function rolePosition(role) {
273
+ return typeof role?.position === "number" ? role.position : -1;
274
+ }
275
+ function highestMemberRolePosition(guild, member) {
276
+ const roles = rolesById(guild);
277
+ return Math.max(...(member.roles ?? []).map((roleId) => rolePosition(roles.get(roleId))), 0);
278
+ }
269
279
  function resolveMemberChannelPermissionBits(params) {
270
280
  let permissions = resolveMemberGuildPermissionBits({
271
281
  guild: params.guild,
@@ -291,6 +301,12 @@ function resolveMemberChannelPermissionBits(params) {
291
301
  }
292
302
  return permissions;
293
303
  }
304
+ async function resolveChannelPermissionSubject(rest, channel) {
305
+ const channelType = "type" in channel ? channel.type : void 0;
306
+ const parentId = "parent_id" in channel ? channel.parent_id : void 0;
307
+ if (isThreadChannelType(channelType) && parentId) return await getChannel(rest, parentId);
308
+ return channel;
309
+ }
294
310
  /**
295
311
  * Fetch guild-level permissions for a user. This does not include channel-specific overwrites.
296
312
  */
@@ -298,6 +314,7 @@ async function fetchMemberGuildPermissionsDiscord(guildId, userId, opts) {
298
314
  const rest = resolveDiscordRest(opts);
299
315
  try {
300
316
  const [guild, member] = await Promise.all([getGuild(rest, guildId), getGuildMember(rest, guildId, userId)]);
317
+ if (guild.owner_id === userId) return ALL_PERMISSIONS;
301
318
  return resolveMemberGuildPermissionBits({
302
319
  guild,
303
320
  member
@@ -312,6 +329,7 @@ async function canViewDiscordGuildChannel(guildId, channelId, userId, opts) {
312
329
  const channel = await getChannel(rest, channelId);
313
330
  if (("guild_id" in channel ? channel.guild_id : void 0) !== guildId) return false;
314
331
  const [guild, member] = await Promise.all([getGuild(rest, guildId), getGuildMember(rest, guildId, userId)]);
332
+ if (guild.owner_id === userId) return true;
315
333
  return hasPermissionBit(resolveMemberChannelPermissionBits({
316
334
  guildId,
317
335
  userId,
@@ -324,6 +342,66 @@ async function canViewDiscordGuildChannel(guildId, channelId, userId, opts) {
324
342
  }
325
343
  }
326
344
  /**
345
+ * Returns true when the user has ADMINISTRATOR or any required permission bit
346
+ * after applying channel/category overwrites.
347
+ */
348
+ async function hasAnyChannelPermissionDiscord(guildId, channelId, userId, requiredPermissions, opts) {
349
+ const rest = resolveDiscordRest(opts);
350
+ try {
351
+ const permissionChannel = await resolveChannelPermissionSubject(rest, await getChannel(rest, channelId));
352
+ if (("guild_id" in permissionChannel ? permissionChannel.guild_id : void 0) !== guildId) return false;
353
+ const [guild, member] = await Promise.all([getGuild(rest, guildId), getGuildMember(rest, guildId, userId)]);
354
+ if (guild.owner_id === userId) return true;
355
+ const permissions = resolveMemberChannelPermissionBits({
356
+ guildId,
357
+ userId,
358
+ guild,
359
+ member,
360
+ channel: permissionChannel
361
+ });
362
+ return requiredPermissions.some((permission) => hasPermissionBit(permissions, permission));
363
+ } catch {
364
+ return false;
365
+ }
366
+ }
367
+ async function canManageGuildMemberRoleDiscord(guildId, senderUserId, targetUserId, roleId, opts, requirements) {
368
+ const rest = resolveDiscordRest(opts);
369
+ try {
370
+ const [guild, senderMember, targetMember] = await Promise.all([
371
+ getGuild(rest, guildId),
372
+ getGuildMember(rest, guildId, senderUserId),
373
+ getGuildMember(rest, guildId, targetUserId)
374
+ ]);
375
+ if (guild.owner_id === senderUserId) return true;
376
+ if (guild.owner_id === targetUserId) return false;
377
+ const targetRole = rolesById(guild).get(roleId);
378
+ const targetRolePosition = rolePosition(targetRole);
379
+ if (targetRolePosition < 0) return false;
380
+ const senderPermissions = resolveMemberGuildPermissionBits({
381
+ guild,
382
+ member: senderMember
383
+ });
384
+ if (requirements?.assignablePermissionCeiling && !hasAdministrator(senderPermissions) && (BigInt(targetRole?.permissions ?? "0") & ~senderPermissions) !== 0n) return false;
385
+ const senderHighestRolePosition = highestMemberRolePosition(guild, senderMember);
386
+ if (senderHighestRolePosition <= targetRolePosition) return false;
387
+ return senderHighestRolePosition > highestMemberRolePosition(guild, targetMember);
388
+ } catch {
389
+ return false;
390
+ }
391
+ }
392
+ async function canManageGuildRoleDiscord(guildId, senderUserId, roleId, opts) {
393
+ const rest = resolveDiscordRest(opts);
394
+ try {
395
+ const [guild, senderMember] = await Promise.all([getGuild(rest, guildId), getGuildMember(rest, guildId, senderUserId)]);
396
+ const targetRole = rolesById(guild).get(roleId);
397
+ if (!targetRole) return null;
398
+ if (guild.owner_id === senderUserId) return true;
399
+ return highestMemberRolePosition(guild, senderMember) > rolePosition(targetRole);
400
+ } catch {
401
+ return false;
402
+ }
403
+ }
404
+ /**
327
405
  * Returns true when the user has ADMINISTRATOR or required permission bits
328
406
  * matching the provided predicate.
329
407
  */
@@ -669,4 +747,4 @@ function formatReactionEmoji(emoji) {
669
747
  return buildReactionIdentifier(emoji);
670
748
  }
671
749
  //#endregion
672
- export { isThreadChannelType as A, DISCORD_MAX_STICKER_BYTES as C, fetchMemberGuildPermissionsDiscord as D, fetchChannelPermissionsDiscord as E, resolveDiscordClientAccountContext as F, resolveDiscordRest as I, DISCORD_REST_TIMEOUT_MS as L, createDiscordClient as M, createDiscordRestClient as N, hasAllGuildPermissionsDiscord as O, createDiscordRuntimeAccountContext as P, validateDiscordProxyUrl as R, DISCORD_MAX_EVENT_COVER_BYTES as S, canViewDiscordGuildChannel as T, resolveDiscordMessageFlags as _, normalizeDiscordPollInput as a, stripUndefinedFields as b, normalizeStickerIds as c, resolveDiscordTargetChannelId as d, sendDiscordMedia as f, buildDiscordMessageRequest as g, SUPPRESS_NOTIFICATIONS_FLAG as h, formatReactionEmoji as i, parseAndResolveChannelRecipient as j, hasAnyGuildPermissionDiscord as k, resolveChannelId as l, toDiscordFileBlob as m, buildDiscordTextChunks as n, normalizeEmojiName as o, sendDiscordText as p, buildReactionIdentifier as r, normalizeReactionEmoji as s, buildDiscordSendError as t, resolveDiscordChannelType as u, resolveDiscordSendComponents as v, DiscordSendError as w, DISCORD_MAX_EMOJI_BYTES as x, resolveDiscordSendEmbeds as y, withValidatedDiscordProxy as z };
750
+ export { hasAllGuildPermissionsDiscord as A, DISCORD_REST_TIMEOUT_MS as B, DISCORD_MAX_STICKER_BYTES as C, canViewDiscordGuildChannel as D, canManageGuildRoleDiscord as E, createDiscordClient as F, withValidatedDiscordProxy as H, createDiscordRestClient as I, createDiscordRuntimeAccountContext as L, hasAnyGuildPermissionDiscord as M, isThreadChannelType as N, fetchChannelPermissionsDiscord as O, parseAndResolveChannelRecipient as P, resolveDiscordClientAccountContext as R, DISCORD_MAX_EVENT_COVER_BYTES as S, canManageGuildMemberRoleDiscord as T, validateDiscordProxyUrl as V, resolveDiscordMessageFlags as _, normalizeDiscordPollInput as a, stripUndefinedFields as b, normalizeStickerIds as c, resolveDiscordTargetChannelId as d, sendDiscordMedia as f, buildDiscordMessageRequest as g, SUPPRESS_NOTIFICATIONS_FLAG as h, formatReactionEmoji as i, hasAnyChannelPermissionDiscord as j, fetchMemberGuildPermissionsDiscord as k, resolveChannelId as l, toDiscordFileBlob as m, buildDiscordTextChunks as n, normalizeEmojiName as o, sendDiscordText as p, buildReactionIdentifier as r, normalizeReactionEmoji as s, buildDiscordSendError as t, resolveDiscordChannelType as u, resolveDiscordSendComponents as v, DiscordSendError as w, DISCORD_MAX_EMOJI_BYTES as x, resolveDiscordSendEmbeds as y, resolveDiscordRest as z };
@@ -1,2 +1,2 @@
1
- import { t as discordSetupPlugin } from "./channel.setup-JaozRxYz.js";
1
+ import { t as discordSetupPlugin } from "./channel.setup-B-kHacpx.js";
2
2
  export { discordSetupPlugin };
@@ -2,7 +2,7 @@ import { a as mergeDiscordAccountConfig, c as resolveDiscordAccountAllowFrom, d
2
2
  import { t as inspectDiscordAccount } from "./account-inspect-C4sJZNbI.js";
3
3
  import { i as getChatChannelMeta, o as resolveConfiguredFromCredentialStatuses } from "./channel-api-CAJ0wMoV.js";
4
4
  import { t as DiscordChannelConfigSchema } from "./config-schema-CTzLsQlB.js";
5
- import { n as normalizeCompatibilityConfig } from "./doctor-contract-CLMMYrdF.js";
5
+ import { n as normalizeCompatibilityConfig } from "./doctor-contract-8-Ia3d_X.js";
6
6
  import { n as secretTargetRegistryEntries, t as collectRuntimeConfigAssignments } from "./secret-config-contract-BjM-1hr9.js";
7
7
  import { n as unsupportedSecretRefSurfacePatterns, t as collectUnsupportedSecretRefConfigCandidates } from "./security-contract-DSHk7I2w.js";
8
8
  import { t as deriveLegacySessionChatType } from "./session-contract-BO5tlIdl.js";
@@ -71,7 +71,7 @@ const DISCORD_LEGACY_CONFIG_RULES = [];
71
71
  const DISCORD_CHANNEL = "discord";
72
72
  let discordDoctorModulePromise;
73
73
  async function loadDiscordDoctorModule() {
74
- discordDoctorModulePromise ??= import("./doctor-DBPfLj15.js");
74
+ discordDoctorModulePromise ??= import("./doctor-Q80i7GdG.js");
75
75
  return await discordDoctorModulePromise;
76
76
  }
77
77
  const discordDoctor = {
@@ -1,6 +1,6 @@
1
- import { Wt as __exportAll } from "./send.receipt-D_6lR7zH.js";
1
+ import { Wt as __exportAll } from "./send.receipt-BzfsP3Bb.js";
2
2
  import { s as resolveDiscordAccount } from "./accounts-dXTfmnSZ.js";
3
- import { n as autoBindSpawnedDiscordSubagent, o as unbindThreadBindingsBySessionKey, r as listThreadBindingsBySessionKey } from "./thread-bindings-Dw4wcHWn.js";
3
+ import { n as autoBindSpawnedDiscordSubagent, o as unbindThreadBindingsBySessionKey, r as listThreadBindingsBySessionKey } from "./thread-bindings-Bw40FTRZ.js";
4
4
  import { normalizeOptionalLowercaseString, normalizeOptionalStringifiedId } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  import { formatThreadBindingDisabledError, formatThreadBindingSpawnDisabledError, resolveThreadBindingSpawnPolicy } from "openclaw/plugin-sdk/conversation-runtime";
6
6
  //#region extensions/discord/src/subagent-hooks.ts
@@ -1,7 +1,7 @@
1
1
  //#region extensions/discord/subagent-hooks-api.ts
2
2
  let discordSubagentHooksPromise = null;
3
3
  function loadDiscordSubagentHooksModule() {
4
- discordSubagentHooksPromise ??= import("./subagent-hooks-DHA_1pBI.js").then((n) => n.i);
4
+ discordSubagentHooksPromise ??= import("./subagent-hooks-Di_2iXU8.js").then((n) => n.i);
5
5
  return discordSubagentHooksPromise;
6
6
  }
7
7
  function registerDiscordSubagentHooks(api) {
@@ -1,4 +1,4 @@
1
- import { c as discord_exports } from "./send.receipt-D_6lR7zH.js";
1
+ import { c as discord_exports } from "./send.receipt-BzfsP3Bb.js";
2
2
  import { b as formatDiscordUserTag } from "./allow-list-BnkWtVpA.js";
3
3
  //#region extensions/discord/src/monitor/system-events.ts
4
4
  function resolveDiscordSystemEvent(message, location) {
@@ -1,6 +1,6 @@
1
- import { Ht as parseDiscordTarget, Wt as __exportAll, r as allowFromContainsDiscordUserId } from "./send.receipt-D_6lR7zH.js";
1
+ import { Ht as parseDiscordTarget, Wt as __exportAll, r as allowFromContainsDiscordUserId } from "./send.receipt-BzfsP3Bb.js";
2
2
  import { c as resolveDiscordAccountAllowFrom, s as resolveDiscordAccount } from "./accounts-dXTfmnSZ.js";
3
- import { i as rememberDiscordDirectoryUser, r as listDiscordDirectoryPeersLive } from "./directory-live-BRjo48ro.js";
3
+ import { i as rememberDiscordDirectoryUser, r as listDiscordDirectoryPeersLive } from "./directory-live-C-ECRrM8.js";
4
4
  import { buildMessagingTarget } from "openclaw/plugin-sdk/channel-targets";
5
5
  //#region extensions/discord/src/send-target-parsing.ts
6
6
  const parseDiscordSendTarget = (raw, options = {}) => parseDiscordTarget(raw, options);
@@ -0,0 +1,3 @@
1
+ import "./send.receipt-BzfsP3Bb.js";
2
+ import "./target-resolver-DXPvq5-L.js";
3
+ export {};
package/dist/test-api.js CHANGED
@@ -1,6 +1,6 @@
1
- import { t as discordPlugin } from "./channel-XYTSE8wN.js";
2
- import { n as discordOutbound } from "./outbound-adapter-C8lzfSt6.js";
3
- import { i as testing } from "./thread-bindings.manager-UJ5FvZfO.js";
1
+ import { t as discordPlugin } from "./channel-9YoMy5Jf.js";
2
+ import { n as discordOutbound } from "./outbound-adapter-DYUYRaBd.js";
3
+ import { i as testing } from "./thread-bindings.manager-LoYZzlss.js";
4
4
  import { n as buildDiscordInboundAccessContext } from "./inbound-context-B5EsqsSr.js";
5
5
  import { finalizeInboundContext } from "openclaw/plugin-sdk/reply-dispatch-runtime";
6
6
  //#region extensions/discord/src/monitor/inbound-context.test-helpers.ts
@@ -1,9 +1,9 @@
1
- import { Ht as parseDiscordTarget, Wt as __exportAll } from "./send.receipt-D_6lR7zH.js";
2
- import "./targets-CNDNKpqQ.js";
1
+ import { Ht as parseDiscordTarget, Wt as __exportAll } from "./send.receipt-BzfsP3Bb.js";
2
+ import "./targets-BBVHRaeO.js";
3
3
  import { C as resolveThreadBindingMaxAgeMs$1, O as shouldPersistBindingMutations, S as resolveThreadBindingMaxAgeExpiresAt, T as saveBindingsToDisk, b as resolveThreadBindingIdleTimeoutMs$1, c as getThreadBindingToken, f as normalizeThreadId, g as removeBindingRecord, l as isRecentlyUnboundThreadWebhookMessage, n as MANAGERS_BY_ACCOUNT_ID, p as rememberRecentUnboundWebhookEcho, t as BINDINGS_BY_THREAD_ID, x as resolveThreadBindingInactivityExpiresAt } from "./thread-bindings.state-BsOnj5NX.js";
4
4
  import { n as setThreadBindingMaxAgeBySessionKey, r as resolveBindingIdsForTargetSession, t as setThreadBindingIdleTimeoutBySessionKey } from "./thread-bindings.session-updates-D5gY2ZTE.js";
5
- import { _ as formatThreadBindingDurationLabel, b as resolveThreadBindingThreadName, g as resolveThreadBindingPersonaFromRecord, h as resolveThreadBindingPersona, s as resolveChannelIdForBinding, y as resolveThreadBindingIntroText } from "./thread-bindings.discord-api-xCfun-pQ.js";
6
- import { i as testing, n as createThreadBindingManager, r as getThreadBindingManager, t as createNoopThreadBindingManager } from "./thread-bindings.manager-UJ5FvZfO.js";
5
+ import { _ as formatThreadBindingDurationLabel, b as resolveThreadBindingThreadName, g as resolveThreadBindingPersonaFromRecord, h as resolveThreadBindingPersona, s as resolveChannelIdForBinding, y as resolveThreadBindingIntroText } from "./thread-bindings.discord-api-irWYI8YX.js";
6
+ import { i as testing, n as createThreadBindingManager, r as getThreadBindingManager, t as createNoopThreadBindingManager } from "./thread-bindings.manager-LoYZzlss.js";
7
7
  import { normalizeOptionalLowercaseString, normalizeOptionalString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
8
8
  import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
9
9
  import { resolveThreadBindingIdleTimeoutMs, resolveThreadBindingMaxAgeMs, resolveThreadBindingsEnabled } from "openclaw/plugin-sdk/conversation-runtime";
@@ -1,7 +1,7 @@
1
- import { Ut as resolveDiscordChannelId, pt as getChannel, tt as createChannelWebhook } from "./send.receipt-D_6lR7zH.js";
2
- import { N as createDiscordRestClient } from "./send.shared-aYGYz83q.js";
3
- import { c as sendWebhookMessageDiscord, u as createThreadDiscord } from "./send-CM1NFFrZ.js";
4
- import { t as sendMessageDiscord } from "./send.outbound-BHQPWbwU.js";
1
+ import { Ut as resolveDiscordChannelId, pt as getChannel, tt as createChannelWebhook } from "./send.receipt-BzfsP3Bb.js";
2
+ import { I as createDiscordRestClient } from "./send.shared-ehnDGwXx.js";
3
+ import { c as sendWebhookMessageDiscord, u as createThreadDiscord } from "./send-BzXZ8iUI.js";
4
+ import { t as sendMessageDiscord } from "./send.outbound-ZrMnBa8C.js";
5
5
  import { i as REUSABLE_WEBHOOKS_BY_ACCOUNT_CHANNEL, k as toReusableWebhookKey, m as rememberReusableWebhook, t as BINDINGS_BY_THREAD_ID } from "./thread-bindings.state-BsOnj5NX.js";
6
6
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
7
7
  import { ChannelType } from "discord-api-types/v10";
@@ -1,7 +1,7 @@
1
- import { Ut as resolveDiscordChannelId, Wt as __exportAll, pt as getChannel } from "./send.receipt-D_6lR7zH.js";
2
- import { N as createDiscordRestClient } from "./send.shared-aYGYz83q.js";
1
+ import { Ut as resolveDiscordChannelId, Wt as __exportAll, pt as getChannel } from "./send.receipt-BzfsP3Bb.js";
2
+ import { I as createDiscordRestClient } from "./send.shared-ehnDGwXx.js";
3
3
  import { A as DEFAULT_THREAD_BINDING_IDLE_TIMEOUT_MS, C as resolveThreadBindingMaxAgeMs$1, D as shouldDefaultPersist, E as setBindingRecord, M as THREAD_BINDINGS_SWEEP_INTERVAL_MS, S as resolveThreadBindingMaxAgeExpiresAt, T as saveBindingsToDisk, _ as resetThreadBindingsForTests, a as THREAD_BINDING_TOUCH_PERSIST_MIN_INTERVAL_MS, b as resolveThreadBindingIdleTimeoutMs$1, c as getThreadBindingToken, d as normalizeThreadBindingDurationMs, f as normalizeThreadId, g as removeBindingRecord, h as rememberThreadBindingToken, n as MANAGERS_BY_ACCOUNT_ID, o as ensureBindingsLoaded, p as rememberRecentUnboundWebhookEcho, r as PERSIST_BY_ACCOUNT_ID, s as forgetThreadBindingToken, t as BINDINGS_BY_THREAD_ID, u as normalizeTargetKind, v as resolveBindingIdsForSession, w as resolveThreadBindingsPath, x as resolveThreadBindingInactivityExpiresAt, y as resolveBindingRecordKey } from "./thread-bindings.state-BsOnj5NX.js";
4
- import { a as isThreadArchived, b as resolveThreadBindingThreadName, c as summarizeDiscordError, i as isDiscordThreadGoneError, n as createWebhookForChannel, o as maybeSendBindingMessage, r as findReusableWebhook, s as resolveChannelIdForBinding, t as createThreadForBinding, v as resolveThreadBindingFarewellText } from "./thread-bindings.discord-api-xCfun-pQ.js";
4
+ import { a as isThreadArchived, b as resolveThreadBindingThreadName, c as summarizeDiscordError, i as isDiscordThreadGoneError, n as createWebhookForChannel, o as maybeSendBindingMessage, r as findReusableWebhook, s as resolveChannelIdForBinding, t as createThreadForBinding, v as resolveThreadBindingFarewellText } from "./thread-bindings.discord-api-irWYI8YX.js";
5
5
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
6
6
  import { normalizeAccountId, resolveAgentIdFromSessionKey } from "openclaw/plugin-sdk/routing";
7
7
  import { getRuntimeConfigSnapshot } from "openclaw/plugin-sdk/runtime-config-snapshot";
@@ -1,4 +1,4 @@
1
- import { Wt as __exportAll } from "./send.receipt-D_6lR7zH.js";
1
+ import { Wt as __exportAll } from "./send.receipt-BzfsP3Bb.js";
2
2
  //#region extensions/discord/src/voice/transcripts-source.ts
3
3
  var transcripts_source_exports = /* @__PURE__ */ __exportAll({
4
4
  discordVoiceTranscriptsSourceProvider: () => discordVoiceTranscriptsSourceProvider,
@@ -1,2 +1,2 @@
1
- import { t as discordVoiceTranscriptsSourceProvider } from "./transcripts-source-emawQzBc.js";
1
+ import { t as discordVoiceTranscriptsSourceProvider } from "./transcripts-source-CwahHAYt.js";
2
2
  export { discordVoiceTranscriptsSourceProvider };
@@ -1,4 +1,4 @@
1
- import { Wt as __exportAll, bt as sendChannelTyping } from "./send.receipt-D_6lR7zH.js";
1
+ import { Wt as __exportAll, bt as sendChannelTyping } from "./send.receipt-BzfsP3Bb.js";
2
2
  import { o as raceWithTimeout } from "./timeouts-l_PsHQvX.js";
3
3
  //#region extensions/discord/src/monitor/typing.ts
4
4
  var typing_exports = /* @__PURE__ */ __exportAll({ sendTyping: () => sendTyping });
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@openclaw/discord",
3
- "version": "2026.5.26",
3
+ "version": "2026.5.27",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/discord",
9
- "version": "2026.5.26",
9
+ "version": "2026.5.27",
10
10
  "dependencies": {
11
11
  "@discordjs/voice": "0.19.2",
12
12
  "discord-api-types": "0.38.48",
@@ -17,7 +17,7 @@
17
17
  "ws": "8.21.0"
18
18
  },
19
19
  "peerDependencies": {
20
- "openclaw": ">=2026.5.26"
20
+ "openclaw": ">=2026.5.27"
21
21
  },
22
22
  "peerDependenciesMeta": {
23
23
  "openclaw": {
@@ -1,5 +1,7 @@
1
1
  {
2
2
  "id": "discord",
3
+ "name": "Discord",
4
+ "description": "OpenClaw Discord channel plugin for channels, DMs, commands, and app events.",
3
5
  "activation": {
4
6
  "onStartup": false
5
7
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@openclaw/discord",
3
- "version": "2026.5.26",
4
- "description": "OpenClaw Discord channel plugin",
3
+ "version": "2026.5.27",
4
+ "description": "OpenClaw Discord channel plugin for channels, DMs, commands, and app events.",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/openclaw/openclaw"
@@ -17,7 +17,7 @@
17
17
  "ws": "8.21.0"
18
18
  },
19
19
  "peerDependencies": {
20
- "openclaw": ">=2026.5.26"
20
+ "openclaw": ">=2026.5.27"
21
21
  },
22
22
  "peerDependenciesMeta": {
23
23
  "openclaw": {
@@ -57,14 +57,14 @@
57
57
  "install": {
58
58
  "npmSpec": "@openclaw/discord",
59
59
  "defaultChoice": "npm",
60
- "minHostVersion": ">=2026.5.26",
60
+ "minHostVersion": ">=2026.5.27",
61
61
  "allowInvalidConfigRecovery": true
62
62
  },
63
63
  "compat": {
64
- "pluginApi": ">=2026.5.26"
64
+ "pluginApi": ">=2026.5.27"
65
65
  },
66
66
  "build": {
67
- "openclawVersion": "2026.5.26"
67
+ "openclawVersion": "2026.5.27"
68
68
  },
69
69
  "release": {
70
70
  "publishToClawHub": true,
@@ -1,2 +0,0 @@
1
- import { t as monitorDiscordProvider } from "./provider-D3RwHRhI.js";
2
- export { monitorDiscordProvider };
@@ -1,5 +0,0 @@
1
- import "./allow-list-BnkWtVpA.js";
2
- import "./provider-D3RwHRhI.js";
3
- import "./message-utils-DxHZcpPf.js";
4
- import "./message-handler-B9n5CtIS.js";
5
- export {};
@@ -1,3 +0,0 @@
1
- import "./send.receipt-D_6lR7zH.js";
2
- import "./target-resolver-CVgOsap6.js";
3
- export {};