@openclaw/discord 2026.5.16-beta.2 → 2026.5.16-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.
package/dist/api.js CHANGED
@@ -6,7 +6,7 @@ import { n as fetchDiscord, r as requestDiscord, t as DiscordApiError } from "./
6
6
  import { i as parseDiscordSendTarget, n as resolveDiscordTarget } from "./target-resolver-BsGT9hI7.js";
7
7
  import "./targets-DwW6OieO.js";
8
8
  import { a as getDiscordExecApprovalApprovers, c as shouldSuppressLocalDiscordExecApprovalPrompt, o as isDiscordExecApprovalApprover, s as isDiscordExecApprovalClientEnabled } from "./conversation-identity-Dh8wIQ_K.js";
9
- import { i as resolveDiscordGroupToolPolicy, n as collectDiscordStatusIssues, r as resolveDiscordGroupRequireMention, t as discordPlugin } from "./channel-ngFtP-WD.js";
9
+ import { i as resolveDiscordGroupToolPolicy, n as collectDiscordStatusIssues, r as resolveDiscordGroupRequireMention, t as discordPlugin } from "./channel-DdqtpKwY.js";
10
10
  import { t as normalizeExplicitDiscordSessionKey } from "./session-key-normalization-B7h83qD2.js";
11
11
  import { t as discordSetupPlugin } from "./channel.setup-BwmvzHMR.js";
12
12
  import { n as handleDiscordSubagentEnded, r as handleDiscordSubagentSpawning, t as handleDiscordSubagentDeliveryTarget } from "./subagent-hooks-vwV-pjIA.js";
@@ -132,7 +132,7 @@ const loadDiscordResolveUsersModule = createLazyRuntimeModule(() => import("./re
132
132
  const loadDiscordThreadBindingsManagerModule = createLazyRuntimeModule(() => import("./thread-bindings.manager-BL5QlX3G.js").then((n) => n.a));
133
133
  const loadDiscordTargetResolverModule = createLazyRuntimeModule(() => import("./target-resolver-BsGT9hI7.js").then((n) => n.r));
134
134
  async function loadDiscordProviderRuntime() {
135
- discordProviderRuntimePromise ??= import("./provider.runtime-B_3TYTb7.js");
135
+ discordProviderRuntimePromise ??= import("./provider.runtime-DMPCr3Hh.js");
136
136
  return await discordProviderRuntimePromise;
137
137
  }
138
138
  async function loadDiscordProbeRuntime() {
@@ -1,2 +1,2 @@
1
- import { t as discordPlugin } from "./channel-ngFtP-WD.js";
1
+ import { t as discordPlugin } from "./channel-DdqtpKwY.js";
2
2
  export { discordPlugin };
@@ -3,7 +3,7 @@ import { c as resolveDiscordAccountAllowFrom } from "./accounts-DnNVBDfc.js";
3
3
  import { a as normalizeDiscordSlug, b as formatDiscordUserTag, m as resolveDiscordOwnerAccess } from "./allow-list-CBI-M84K.js";
4
4
  import { i as formatMention } from "./send.outbound-BKh71kjw.js";
5
5
  import { t as getDiscordRuntime } from "./runtime-Tqtvj5GX.js";
6
- import { o as authorizeDiscordVoiceIngress, u as resolveDiscordVoiceEnabled } from "./provider-B81nXBRc.js";
6
+ import { o as authorizeDiscordVoiceIngress, u as resolveDiscordVoiceEnabled } from "./provider-C4J1o-3R.js";
7
7
  import { t as buildDiscordGroupSystemPrompt } from "./inbound-context-BdfOEkhj.js";
8
8
  import { createRequire } from "node:module";
9
9
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
@@ -121,7 +121,7 @@ function applyImplicitReplyBatchGate(ctx, replyToMode, isBatched) {
121
121
  //#region extensions/discord/src/monitor/message-run-queue.ts
122
122
  let messageProcessRuntimePromise;
123
123
  async function loadMessageProcessRuntime() {
124
- messageProcessRuntimePromise ??= import("./message-handler.process-Dfu_aSv1.js");
124
+ messageProcessRuntimePromise ??= import("./message-handler.process-Ce7Xh_dH.js");
125
125
  return await messageProcessRuntimePromise;
126
126
  }
127
127
  async function processDiscordQueuedMessage(params) {
@@ -173,7 +173,7 @@ function createDiscordMessageRunQueue(params) {
173
173
  //#region extensions/discord/src/monitor/message-handler.ts
174
174
  let messagePreflightRuntimePromise;
175
175
  async function loadMessagePreflightRuntime() {
176
- messagePreflightRuntimePromise ??= import("./message-handler.preflight-BMgBVbmR.js");
176
+ messagePreflightRuntimePromise ??= import("./message-handler.preflight-DFw-r_C5.js");
177
177
  return await messagePreflightRuntimePromise;
178
178
  }
179
179
  function isNonEmptyString(value) {
@@ -5,7 +5,7 @@ import { t as resolveDiscordConversationIdentity } from "./conversation-identity
5
5
  import { l as isRecentlyUnboundThreadWebhookMessage } from "./thread-bindings.state-BdBeo7Rx.js";
6
6
  import { d as resolveDiscordChannelNameSafe, u as resolveDiscordChannelInfoSafe } from "./thread-bindings.discord-api-BtXi8-Fz.js";
7
7
  import "./thread-bindings-BwcE40jS.js";
8
- import { C as resolveDiscordDmCommandAccess, f as buildDiscordRoutePeer, g as handleDiscordDmCommandDecision, h as shouldIgnoreStaleDiscordRouteBinding, m as resolveDiscordEffectiveRoute, p as resolveDiscordConversationRoute, w as resolveDiscordTextCommandAccess } from "./provider-B81nXBRc.js";
8
+ import { C as resolveDiscordDmCommandAccess, f as buildDiscordRoutePeer, g as handleDiscordDmCommandDecision, h as shouldIgnoreStaleDiscordRouteBinding, m as resolveDiscordEffectiveRoute, p as resolveDiscordConversationRoute, w as resolveDiscordTextCommandAccess } from "./provider-C4J1o-3R.js";
9
9
  import { d as resolveDiscordMessageChannelId, l as resolveDiscordMessageStickers, o as resolveMediaList, r as resolveDiscordMessageText, u as resolveDiscordChannelInfo } from "./message-utils-CY91O2k2.js";
10
10
  import { n as resolveDiscordWebhookId, t as resolveDiscordSenderIdentity } from "./sender-identity-BTGL3VbF.js";
11
11
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
@@ -438,7 +438,7 @@ async function loadSystemEventsRuntime() {
438
438
  return await systemEventsRuntimePromise;
439
439
  }
440
440
  async function loadDiscordThreadingRuntime() {
441
- discordThreadingRuntimePromise ??= import("./provider-B81nXBRc.js").then((n) => n.v);
441
+ discordThreadingRuntimePromise ??= import("./provider-C4J1o-3R.js").then((n) => n.v);
442
442
  return await discordThreadingRuntimePromise;
443
443
  }
444
444
  function isPreflightAborted(abortSignal) {
@@ -8,7 +8,7 @@ import { t as resolveDiscordConversationIdentity } from "./conversation-identity
8
8
  import { t as DISCORD_TEXT_CHUNK_LIMIT } from "./outbound-adapter-Fe4Ee_GO.js";
9
9
  import { t as resolveDiscordPreviewStreamMode } from "./preview-streaming-CXTZydhx.js";
10
10
  import { n as DISCORD_ATTACHMENT_TOTAL_TIMEOUT_MS, t as DISCORD_ATTACHMENT_IDLE_TIMEOUT_MS } from "./timeouts-snXNwR4m.js";
11
- import { a as resolveReplyContext, i as buildGuildLabel, n as deliverDiscordReply, r as buildDirectLabel, x as resolveDiscordThreadStarter, y as resolveDiscordAutoThreadReplyPlan } from "./provider-B81nXBRc.js";
11
+ import { a as resolveReplyContext, i as buildGuildLabel, n as deliverDiscordReply, r as buildDirectLabel, x as resolveDiscordThreadStarter, y as resolveDiscordAutoThreadReplyPlan } from "./provider-C4J1o-3R.js";
12
12
  import { a as resolveForwardedMediaList, o as resolveMediaList, r as resolveDiscordMessageText, s as resolveReferencedReplyMediaList } from "./message-utils-CY91O2k2.js";
13
13
  import { t as sendTyping } from "./typing-C_8U8J7E.js";
14
14
  import { n as buildDiscordInboundAccessContext, r as createDiscordSupplementalContextAccessChecker } from "./inbound-context-BdfOEkhj.js";
@@ -2469,6 +2469,34 @@ function createModelSelect(params) {
2469
2469
  }
2470
2470
  return new DiscordModelPickerSelect();
2471
2471
  }
2472
+ function getRuntimeChoices(params) {
2473
+ const choices = params.data.runtimeChoicesByProvider?.get(normalizeProviderId(params.provider));
2474
+ if (choices?.length) return choices;
2475
+ return [{
2476
+ id: "pi",
2477
+ label: "OpenClaw Pi Default",
2478
+ description: "Use the built-in OpenClaw Pi runtime."
2479
+ }];
2480
+ }
2481
+ function resolveSelectedRuntime(params) {
2482
+ const choices = getRuntimeChoices({
2483
+ data: params.data,
2484
+ provider: params.provider
2485
+ });
2486
+ const allowed = new Set(choices.map((choice) => choice.id));
2487
+ const pending = params.pendingRuntime?.trim();
2488
+ if (pending && allowed.has(pending)) return pending;
2489
+ const current = params.currentRuntime?.trim();
2490
+ if (current && allowed.has(current)) return current;
2491
+ return choices[0]?.id ?? "pi";
2492
+ }
2493
+ function resolveExplicitRuntimeState(params) {
2494
+ const allowed = new Set(params.choices.map((choice) => choice.id));
2495
+ const pending = params.pendingRuntime?.trim();
2496
+ if (pending && allowed.has(pending)) return pending;
2497
+ const current = params.currentRuntime?.trim();
2498
+ if (current && current !== "auto" && current !== "default" && allowed.has(current)) return current;
2499
+ }
2472
2500
  function buildRenderedShell(params) {
2473
2501
  if (params.layout === "classic") return {
2474
2502
  layout: "classic",
@@ -2551,6 +2579,44 @@ function buildModelRows(params) {
2551
2579
  options: providerOptions,
2552
2580
  placeholder: "Select provider"
2553
2581
  })]));
2582
+ const runtimeChoices = getRuntimeChoices({
2583
+ data: params.data,
2584
+ provider: params.modelPage.provider
2585
+ });
2586
+ const selectedRuntime = resolveSelectedRuntime({
2587
+ data: params.data,
2588
+ provider: params.modelPage.provider,
2589
+ currentRuntime: params.currentRuntime,
2590
+ pendingRuntime: params.pendingRuntime
2591
+ });
2592
+ const stateRuntime = resolveExplicitRuntimeState({
2593
+ choices: runtimeChoices,
2594
+ currentRuntime: params.currentRuntime,
2595
+ pendingRuntime: params.pendingRuntime
2596
+ });
2597
+ if (runtimeChoices.length > 1) rows.push(new Row([createModelSelect({
2598
+ customId: buildDiscordModelPickerCustomId({
2599
+ command: params.command,
2600
+ action: "runtime",
2601
+ view: "models",
2602
+ provider: params.modelPage.provider,
2603
+ runtime: selectedRuntime,
2604
+ page: params.modelPage.page,
2605
+ providerPage: providerPage.page,
2606
+ modelIndex: params.pendingModelIndex,
2607
+ userId: params.userId
2608
+ }),
2609
+ options: runtimeChoices.map((choice) => {
2610
+ const option = {
2611
+ label: choice.label,
2612
+ value: choice.id,
2613
+ default: choice.id === selectedRuntime
2614
+ };
2615
+ if (choice.description) option.description = choice.description;
2616
+ return option;
2617
+ }),
2618
+ placeholder: "Select runtime"
2619
+ })]));
2554
2620
  const selectedModelRef = parsedPendingModel ?? parsedCurrentModel;
2555
2621
  const modelOptions = params.modelPage.items.map((model) => ({
2556
2622
  label: model,
@@ -2563,6 +2629,7 @@ function buildModelRows(params) {
2563
2629
  action: "model",
2564
2630
  view: "models",
2565
2631
  provider: params.modelPage.provider,
2632
+ runtime: stateRuntime,
2566
2633
  page: params.modelPage.page,
2567
2634
  providerPage: providerPage.page,
2568
2635
  userId: params.userId
@@ -2581,6 +2648,7 @@ function buildModelRows(params) {
2581
2648
  action: "cancel",
2582
2649
  view: "models",
2583
2650
  provider: params.modelPage.provider,
2651
+ runtime: stateRuntime,
2584
2652
  page: params.modelPage.page,
2585
2653
  providerPage: providerPage.page,
2586
2654
  userId: params.userId
@@ -2594,6 +2662,7 @@ function buildModelRows(params) {
2594
2662
  action: "reset",
2595
2663
  view: "models",
2596
2664
  provider: params.modelPage.provider,
2665
+ runtime: stateRuntime,
2597
2666
  page: params.modelPage.page,
2598
2667
  providerPage: providerPage.page,
2599
2668
  userId: params.userId
@@ -2607,6 +2676,7 @@ function buildModelRows(params) {
2607
2676
  action: "recents",
2608
2677
  view: "recents",
2609
2678
  provider: params.modelPage.provider,
2679
+ runtime: stateRuntime,
2610
2680
  page: params.modelPage.page,
2611
2681
  providerPage: providerPage.page,
2612
2682
  userId: params.userId
@@ -2621,6 +2691,7 @@ function buildModelRows(params) {
2621
2691
  action: "submit",
2622
2692
  view: "models",
2623
2693
  provider: params.modelPage.provider,
2694
+ runtime: stateRuntime,
2624
2695
  page: params.modelPage.page,
2625
2696
  providerPage: providerPage.page,
2626
2697
  modelIndex: params.pendingModelIndex,
@@ -2686,12 +2757,19 @@ function renderDiscordModelPickerModelsView(params) {
2686
2757
  providerPage,
2687
2758
  modelPage,
2688
2759
  currentModel: params.currentModel,
2760
+ currentRuntime: params.currentRuntime,
2689
2761
  pendingModel: params.pendingModel,
2690
2762
  pendingModelIndex: params.pendingModelIndex,
2763
+ pendingRuntime: params.pendingRuntime,
2691
2764
  quickModels: params.quickModels
2692
2765
  });
2693
2766
  const defaultModel = `${params.data.resolvedDefault.provider}/${params.data.resolvedDefault.model}`;
2694
- const pendingLine = params.pendingModel ? `Selected: ${params.pendingModel} (press Submit)` : "Select a model, then press Submit.";
2767
+ const pendingLine = params.pendingModel ? `Selected: ${params.pendingModel} · runtime ${resolveSelectedRuntime({
2768
+ data: params.data,
2769
+ provider: modelPage.provider,
2770
+ currentRuntime: params.currentRuntime,
2771
+ pendingRuntime: params.pendingRuntime
2772
+ })} (press Submit)` : "Select a model, then press Submit.";
2695
2773
  return buildRenderedShell({
2696
2774
  layout: params.layout ?? "v2",
2697
2775
  title: "Model Picker",
@@ -2720,6 +2798,7 @@ function renderDiscordModelPickerRecentsView(params) {
2720
2798
  view: "recents",
2721
2799
  recentSlot: 1,
2722
2800
  provider: params.provider,
2801
+ runtime: params.runtime,
2723
2802
  page: params.page,
2724
2803
  providerPage: params.providerPage,
2725
2804
  userId: params.userId
@@ -2736,6 +2815,7 @@ function renderDiscordModelPickerRecentsView(params) {
2736
2815
  view: "recents",
2737
2816
  recentSlot: i + 2,
2738
2817
  provider: params.provider,
2818
+ runtime: params.runtime,
2739
2819
  page: params.page,
2740
2820
  providerPage: params.providerPage,
2741
2821
  userId: params.userId
@@ -2750,6 +2830,7 @@ function renderDiscordModelPickerRecentsView(params) {
2750
2830
  action: "back",
2751
2831
  view: "models",
2752
2832
  provider: params.provider,
2833
+ runtime: params.runtime,
2753
2834
  page: params.page,
2754
2835
  providerPage: params.providerPage,
2755
2836
  userId: params.userId
@@ -2777,8 +2858,11 @@ async function persistDiscordModelPickerOverride(params) {
2777
2858
  const storePath = resolveStorePath(params.cfg.session?.store, { agentId: params.route.agentId });
2778
2859
  let persisted = false;
2779
2860
  await updateSessionStore(storePath, (store) => {
2780
- const entry = store[params.route.sessionKey];
2781
- if (!entry) return;
2861
+ const entry = store[params.route.sessionKey] ?? {
2862
+ sessionId: randomUUID(),
2863
+ updatedAt: Date.now()
2864
+ };
2865
+ store[params.route.sessionKey] = entry;
2782
2866
  persisted = applyModelOverrideToSessionEntry({
2783
2867
  entry,
2784
2868
  selection: {
@@ -2788,6 +2872,18 @@ async function persistDiscordModelPickerOverride(params) {
2788
2872
  },
2789
2873
  markLiveSwitchPending: true
2790
2874
  }).updated || persisted;
2875
+ const runtime = params.runtime?.trim();
2876
+ if (runtime && runtime !== "auto" && runtime !== "default") {
2877
+ if (entry.agentRuntimeOverride !== runtime) {
2878
+ entry.agentRuntimeOverride = runtime;
2879
+ delete entry.agentHarnessId;
2880
+ persisted = true;
2881
+ }
2882
+ } else if (runtime && entry.agentRuntimeOverride) {
2883
+ delete entry.agentRuntimeOverride;
2884
+ delete entry.agentHarnessId;
2885
+ persisted = true;
2886
+ }
2791
2887
  });
2792
2888
  return persisted;
2793
2889
  }
@@ -2814,6 +2910,19 @@ async function applyDiscordModelPickerSelection(params) {
2814
2910
  if (params.settleMs > 0) await new Promise((resolve) => setTimeout(resolve, params.settleMs));
2815
2911
  let effectiveModelRef = params.resolveCurrentModel(fallbackRoute);
2816
2912
  let persisted = effectiveModelRef === params.resolvedModelRef;
2913
+ if (params.selectedRuntime?.trim()) {
2914
+ await persistDiscordModelPickerOverride({
2915
+ cfg: params.cfg,
2916
+ route: fallbackRoute,
2917
+ provider: params.selectedProvider,
2918
+ model: params.selectedModel,
2919
+ isDefault: params.selectedProvider === params.defaultProvider && params.selectedModel === params.defaultModel,
2920
+ runtime: params.selectedRuntime
2921
+ });
2922
+ await new Promise((resolve) => setTimeout(resolve, 100));
2923
+ effectiveModelRef = params.resolveCurrentModel(fallbackRoute);
2924
+ persisted = effectiveModelRef === params.resolvedModelRef;
2925
+ }
2817
2926
  if (!persisted) {
2818
2927
  logVerbose(`discord: model picker override mismatch — expected ${params.resolvedModelRef} but read ${effectiveModelRef} from session key ${fallbackRoute.sessionKey}; attempting direct session override persist`);
2819
2928
  try {
@@ -2822,7 +2931,8 @@ async function applyDiscordModelPickerSelection(params) {
2822
2931
  route: fallbackRoute,
2823
2932
  provider: params.selectedProvider,
2824
2933
  model: params.selectedModel,
2825
- isDefault: params.selectedProvider === params.defaultProvider && params.selectedModel === params.defaultModel
2934
+ isDefault: params.selectedProvider === params.defaultProvider && params.selectedModel === params.defaultModel,
2935
+ runtime: params.selectedRuntime
2826
2936
  });
2827
2937
  await new Promise((resolve) => setTimeout(resolve, 100));
2828
2938
  effectiveModelRef = params.resolveCurrentModel(fallbackRoute);
@@ -2981,6 +3091,13 @@ function resolveDiscordModelPickerCurrentModel(params) {
2981
3091
  return fallback;
2982
3092
  }
2983
3093
  }
3094
+ function resolveDiscordModelPickerCurrentRuntime(params) {
3095
+ try {
3096
+ const sessionRuntime = normalizeOptionalString(loadSessionStore(resolveStorePath(params.cfg.session?.store, { agentId: params.route.agentId }), { skipCache: true })[params.route.sessionKey]?.agentRuntimeOverride);
3097
+ if (sessionRuntime) return sessionRuntime;
3098
+ } catch {}
3099
+ return "auto";
3100
+ }
2984
3101
  async function replyWithDiscordModelPickerProviders(params) {
2985
3102
  const route = await resolveDiscordModelPickerRoute({
2986
3103
  interaction: params.interaction,
@@ -2994,6 +3111,10 @@ async function replyWithDiscordModelPickerProviders(params) {
2994
3111
  route,
2995
3112
  data
2996
3113
  });
3114
+ const currentRuntime = resolveDiscordModelPickerCurrentRuntime({
3115
+ cfg: params.cfg,
3116
+ route
3117
+ });
2997
3118
  const quickModels = await readDiscordModelPickerRecentModels({
2998
3119
  scope: resolveDiscordModelPickerPreferenceScope({
2999
3120
  interaction: params.interaction,
@@ -3014,6 +3135,7 @@ async function replyWithDiscordModelPickerProviders(params) {
3014
3135
  page: 1,
3015
3136
  providerPage: 1,
3016
3137
  currentModel,
3138
+ currentRuntime,
3017
3139
  quickModels
3018
3140
  })),
3019
3141
  ephemeral: true
@@ -3078,6 +3200,26 @@ function resolveDiscordModelPickerModelByIndex(params) {
3078
3200
  if (!models.length) return null;
3079
3201
  return models[params.modelIndex - 1] ?? null;
3080
3202
  }
3203
+ function resolveDiscordModelPickerRuntimeForProvider(params) {
3204
+ const runtime = normalizeOptionalString(params.runtime);
3205
+ if (!runtime) return;
3206
+ if (runtime === "auto" || runtime === "default") return params.allowResetRuntime ? runtime : void 0;
3207
+ const choices = params.data.runtimeChoicesByProvider?.get(params.provider);
3208
+ if (!choices?.length) return runtime === "pi" ? runtime : void 0;
3209
+ return choices.some((choice) => choice.id === runtime) ? runtime : void 0;
3210
+ }
3211
+ function resolveDiscordModelPickerSubmissionRuntime(params) {
3212
+ return resolveDiscordModelPickerRuntimeForProvider({
3213
+ data: params.data,
3214
+ provider: params.provider,
3215
+ runtime: params.parsedRuntime,
3216
+ allowResetRuntime: true
3217
+ }) ?? resolveDiscordModelPickerRuntimeForProvider({
3218
+ data: params.data,
3219
+ provider: params.provider,
3220
+ runtime: params.currentRuntime
3221
+ });
3222
+ }
3081
3223
  async function handleDiscordModelPickerInteraction(params) {
3082
3224
  const { interaction, data, ctx } = params;
3083
3225
  const parsed = parseDiscordModelPickerData(data);
@@ -3106,6 +3248,10 @@ async function handleDiscordModelPickerInteraction(params) {
3106
3248
  route,
3107
3249
  data: pickerData
3108
3250
  });
3251
+ const currentRuntime = resolveDiscordModelPickerCurrentRuntime({
3252
+ cfg: ctx.cfg,
3253
+ route
3254
+ });
3109
3255
  const allowedModelRefs = buildDiscordModelPickerAllowedModelRefs(pickerData);
3110
3256
  const preferenceScope = resolveDiscordModelPickerPreferenceScope({
3111
3257
  interaction,
@@ -3126,6 +3272,7 @@ async function handleDiscordModelPickerInteraction(params) {
3126
3272
  data: pickerData,
3127
3273
  quickModels,
3128
3274
  currentModel: currentModelRef,
3275
+ runtime: parsed.runtime,
3129
3276
  provider: parsed.provider,
3130
3277
  page: parsed.page,
3131
3278
  providerPage: parsed.providerPage
@@ -3152,6 +3299,8 @@ async function handleDiscordModelPickerInteraction(params) {
3152
3299
  page: parsed.page ?? 1,
3153
3300
  providerPage: parsed.providerPage ?? 1,
3154
3301
  currentModel: currentModelRef,
3302
+ currentRuntime,
3303
+ pendingRuntime: parsed.runtime,
3155
3304
  quickModels
3156
3305
  })));
3157
3306
  return;
@@ -3170,6 +3319,7 @@ async function handleDiscordModelPickerInteraction(params) {
3170
3319
  page: 1,
3171
3320
  providerPage: parsed.providerPage ?? parsed.page,
3172
3321
  currentModel: currentModelRef,
3322
+ currentRuntime,
3173
3323
  quickModels
3174
3324
  })));
3175
3325
  return;
@@ -3199,8 +3349,39 @@ async function handleDiscordModelPickerInteraction(params) {
3199
3349
  page: parsed.page,
3200
3350
  providerPage: parsed.providerPage ?? 1,
3201
3351
  currentModel: currentModelRef,
3352
+ currentRuntime,
3202
3353
  pendingModel: modelRef,
3203
3354
  pendingModelIndex: modelIndex,
3355
+ pendingRuntime: parsed.runtime,
3356
+ quickModels
3357
+ })));
3358
+ return;
3359
+ }
3360
+ if (parsed.action === "runtime") {
3361
+ const selectedRuntime = resolveModelPickerSelectionValue(interaction) ?? parsed.runtime ?? "auto";
3362
+ const provider = parsed.provider;
3363
+ if (!provider || !pickerData.byProvider.has(provider)) {
3364
+ await showNotice("Sorry, that provider isn't available anymore.");
3365
+ return;
3366
+ }
3367
+ const selectedModel = resolveDiscordModelPickerModelByIndex({
3368
+ data: pickerData,
3369
+ provider,
3370
+ modelIndex: parsed.modelIndex
3371
+ });
3372
+ const pendingModel = selectedModel ? `${provider}/${selectedModel}` : void 0;
3373
+ await updatePicker(toDiscordModelPickerMessagePayload(renderDiscordModelPickerModelsView({
3374
+ command: parsed.command,
3375
+ userId: parsed.userId,
3376
+ data: pickerData,
3377
+ provider,
3378
+ page: parsed.page,
3379
+ providerPage: parsed.providerPage ?? 1,
3380
+ currentModel: currentModelRef,
3381
+ currentRuntime,
3382
+ ...pendingModel ? { pendingModel } : {},
3383
+ pendingModelIndex: parsed.modelIndex,
3384
+ pendingRuntime: selectedRuntime,
3204
3385
  quickModels
3205
3386
  })));
3206
3387
  return;
@@ -3232,6 +3413,12 @@ async function handleDiscordModelPickerInteraction(params) {
3232
3413
  return;
3233
3414
  }
3234
3415
  const resolvedModelRef = `${parsedModelRef.provider}/${parsedModelRef.model}`;
3416
+ const selectedRuntime = resolveDiscordModelPickerSubmissionRuntime({
3417
+ data: pickerData,
3418
+ provider: parsedModelRef.provider,
3419
+ parsedRuntime: parsed.runtime,
3420
+ currentRuntime
3421
+ });
3235
3422
  const selectionCommand = buildDiscordModelPickerSelectionCommand({ modelRef: resolvedModelRef });
3236
3423
  if (!selectionCommand) {
3237
3424
  await showNotice("Sorry, /model is unavailable right now.");
@@ -3251,6 +3438,7 @@ async function handleDiscordModelPickerInteraction(params) {
3251
3438
  resolvedModelRef,
3252
3439
  selectedProvider: parsedModelRef.provider,
3253
3440
  selectedModel: parsedModelRef.model,
3441
+ selectedRuntime,
3254
3442
  defaultProvider: pickerData.resolvedDefault.provider,
3255
3443
  defaultModel: pickerData.resolvedDefault.model,
3256
3444
  preferenceScope,
@@ -4294,7 +4482,7 @@ var GatewayPlugin = class extends Plugin {
4294
4482
  this.emitter.emit("error", /* @__PURE__ */ new Error("Invalid gateway payload"));
4295
4483
  return;
4296
4484
  }
4297
- this.handlePayload(payload, resume);
4485
+ this.handlePayload(payload, resume, socket);
4298
4486
  });
4299
4487
  socket.on("close", (code) => {
4300
4488
  if (socket !== this.ws) return;
@@ -4319,7 +4507,7 @@ var GatewayPlugin = class extends Plugin {
4319
4507
  this.emitter.emit("error", error);
4320
4508
  });
4321
4509
  }
4322
- handlePayload(payload, resume) {
4510
+ handlePayload(payload, resume, sourceSocket) {
4323
4511
  if (payload.s !== null && payload.s !== void 0) this.sequence = payload.s;
4324
4512
  switch (payload.op) {
4325
4513
  case GatewayOpcodes.Hello:
@@ -4332,7 +4520,7 @@ var GatewayPlugin = class extends Plugin {
4332
4520
  seq: this.sequence ?? 0
4333
4521
  }
4334
4522
  }, true);
4335
- else this.identifyWithConcurrency().catch((error) => {
4523
+ else this.identifyWithConcurrency(sourceSocket).catch((error) => {
4336
4524
  this.emitter.emit("error", error instanceof Error ? error : new Error(String(error), { cause: error }));
4337
4525
  });
4338
4526
  break;
@@ -4396,16 +4584,15 @@ var GatewayPlugin = class extends Plugin {
4396
4584
  }
4397
4585
  }, true);
4398
4586
  }
4399
- async identifyWithConcurrency() {
4587
+ async identifyWithConcurrency(sourceSocket) {
4400
4588
  await sharedGatewayIdentifyLimiter.wait({
4401
4589
  shardId: this.shardId,
4402
4590
  maxConcurrency: this.gatewayInfo?.session_start_limit.max_concurrency
4403
4591
  });
4404
- const socket = this.ws;
4405
- if (!socket || socket.readyState !== READY_STATE_OPEN) {
4406
- const error = /* @__PURE__ */ new Error("Discord gateway socket closed before IDENTIFY could be sent");
4407
- this.emitter.emit("error", error);
4408
- if (socket) this.scheduleReconnect(false);
4592
+ const socket = sourceSocket ?? this.ws;
4593
+ if (!socket || socket !== this.ws) return;
4594
+ if (socket.readyState !== READY_STATE_OPEN) {
4595
+ this.scheduleReconnect(false);
4409
4596
  return;
4410
4597
  }
4411
4598
  this.identify();
@@ -8979,7 +9166,7 @@ function logDiscordStartupPhase(params) {
8979
9166
  });
8980
9167
  }
8981
9168
  async function loadDiscordVoiceRuntime() {
8982
- const promise = discordVoiceRuntimePromise ?? import("./manager.runtime-D8sDxzBv.js");
9169
+ const promise = discordVoiceRuntimePromise ?? import("./manager.runtime-BU2-AM3y.js");
8983
9170
  discordVoiceRuntimePromise = promise;
8984
9171
  try {
8985
9172
  return await promise;
@@ -8989,7 +9176,7 @@ async function loadDiscordVoiceRuntime() {
8989
9176
  }
8990
9177
  }
8991
9178
  async function loadDiscordProviderSessionRuntime() {
8992
- const promise = discordProviderSessionRuntimePromise ?? import("./provider-session.runtime-C7p_WbqZ.js");
9179
+ const promise = discordProviderSessionRuntimePromise ?? import("./provider-session.runtime-Y2zL_aqr.js");
8993
9180
  discordProviderSessionRuntimePromise = promise;
8994
9181
  try {
8995
9182
  return await promise;
@@ -1,6 +1,6 @@
1
1
  import { a as reconcileAcpThreadBindingsOnStartup } from "./thread-bindings-BwcE40jS.js";
2
2
  import { n as createNoopThreadBindingManager, r as createThreadBindingManager } from "./thread-bindings.manager-BL5QlX3G.js";
3
- import { t as createDiscordMessageHandler } from "./message-handler-D-Nboii4.js";
3
+ import { t as createDiscordMessageHandler } from "./message-handler-CgU3pJi2.js";
4
4
  import { resolveThreadBindingIdleTimeoutMs, resolveThreadBindingMaxAgeMs, resolveThreadBindingsEnabled } from "openclaw/plugin-sdk/conversation-runtime";
5
5
  import { getAcpSessionManager, isAcpRuntimeError } from "openclaw/plugin-sdk/acp-runtime";
6
6
  export { createDiscordMessageHandler, createNoopThreadBindingManager, createThreadBindingManager, getAcpSessionManager, isAcpRuntimeError, reconcileAcpThreadBindingsOnStartup, resolveThreadBindingIdleTimeoutMs, resolveThreadBindingMaxAgeMs, resolveThreadBindingsEnabled };
@@ -0,0 +1,2 @@
1
+ import { t as monitorDiscordProvider } from "./provider-C4J1o-3R.js";
2
+ export { monitorDiscordProvider };
@@ -21,10 +21,10 @@ import { a as mergeAbortSignals, i as DISCORD_DEFAULT_LISTENER_TIMEOUT_MS, n as
21
21
  import "./runtime-api.actions.js";
22
22
  import { r as collectDiscordAuditChannelIds, t as auditDiscordChannelPermissions } from "./audit-BZOw16KT.js";
23
23
  import "./runtime-api.lookup.js";
24
- import { S as sanitizeDiscordThreadName, _ as registerDiscordListener, b as resolveDiscordReplyTarget, c as resolveDiscordGatewayIntents, d as createDiscordNativeCommand, l as waitForDiscordGatewayPluginRegistration, s as createDiscordGatewayPlugin, t as monitorDiscordProvider } from "./provider-B81nXBRc.js";
24
+ import { S as sanitizeDiscordThreadName, _ as registerDiscordListener, b as resolveDiscordReplyTarget, c as resolveDiscordGatewayIntents, d as createDiscordNativeCommand, l as waitForDiscordGatewayPluginRegistration, s as createDiscordGatewayPlugin, t as monitorDiscordProvider } from "./provider-C4J1o-3R.js";
25
25
  import { i as buildDiscordMediaPayload } from "./message-utils-CY91O2k2.js";
26
- import { t as createDiscordMessageHandler } from "./message-handler-D-Nboii4.js";
27
- import "./runtime-api.monitor-DJQdXyzE.js";
26
+ import { t as createDiscordMessageHandler } from "./message-handler-CgU3pJi2.js";
27
+ import "./runtime-api.monitor-dlMXA_pv.js";
28
28
  import "./runtime-api.send.js";
29
29
  import "./runtime-api.threads.js";
30
30
  export { DISCORD_ATTACHMENT_IDLE_TIMEOUT_MS, DISCORD_ATTACHMENT_TOTAL_TIMEOUT_MS, DISCORD_DEFAULT_INBOUND_WORKER_TIMEOUT_MS, DISCORD_DEFAULT_LISTENER_TIMEOUT_MS, DiscordSendError, __testing, addRoleDiscord, allowListMatches, auditDiscordChannelPermissions, autoBindSpawnedDiscordSubagent, banMemberDiscord, buildDiscordMediaPayload, clearGateways, clearPresences, collectDiscordAuditChannelIds, createChannelDiscord, createDiscordGatewayPlugin, createDiscordMessageHandler, createDiscordNativeCommand, createNoopThreadBindingManager, createScheduledEventDiscord, createThreadBindingManager, createThreadDiscord, deleteChannelDiscord, deleteMessageDiscord, discordMessageActions, editChannelDiscord, editDiscordComponentMessage, editMessageDiscord, fetchChannelInfoDiscord, fetchChannelPermissionsDiscord, fetchDiscordApplicationId, fetchDiscordApplicationSummary, fetchMemberGuildPermissionsDiscord, fetchMemberInfoDiscord, fetchMessageDiscord, fetchReactionsDiscord, fetchRoleInfoDiscord, fetchVoiceStatusDiscord, formatThreadBindingDurationLabel, getGateway, getPresence, getThreadBindingManager, handleDiscordAction, hasAllGuildPermissionsDiscord, hasAnyGuildPermissionDiscord, isDiscordGroupAllowedByPolicy, isDiscordModerationAction, isRecentlyUnboundThreadWebhookMessage, kickMemberDiscord, listDiscordDirectoryGroupsLive, listDiscordDirectoryPeersLive, listGuildChannelsDiscord, listGuildEmojisDiscord, listPinsDiscord, listScheduledEventsDiscord, listThreadBindingsBySessionKey, listThreadBindingsForAccount, listThreadsDiscord, mergeAbortSignals, monitorDiscordProvider, moveChannelDiscord, normalizeDiscordAllowList, normalizeDiscordSlug, parseApplicationIdFromToken, pinMessageDiscord, presenceCacheSize, probeDiscord, reactMessageDiscord, readDiscordChannelCreateParams, readDiscordChannelEditParams, readDiscordChannelMoveParams, readDiscordModerationCommand, readDiscordParentIdParam, readMessagesDiscord, reconcileAcpThreadBindingsOnStartup, registerBuiltDiscordComponentMessage, registerDiscordListener, registerGateway, removeChannelPermissionDiscord, removeOwnReactionsDiscord, removeReactionDiscord, removeRoleDiscord, requiredGuildPermissionForModerationAction, resolveDiscordChannelAllowlist, resolveDiscordChannelConfig, resolveDiscordChannelConfigWithFallback, resolveDiscordCommandAuthorized, resolveDiscordGatewayIntents, resolveDiscordGuildEntry, resolveDiscordOutboundSessionRoute, resolveDiscordPrivilegedIntentsFromFlags, resolveDiscordReplyTarget, resolveDiscordShouldRequireMention, resolveDiscordThreadBindingIdleTimeoutMs, resolveDiscordThreadBindingMaxAgeMs, resolveDiscordUserAllowlist, resolveEventCoverImage, resolveGroupDmAllow, resolveThreadBindingIdleTimeoutMs, resolveThreadBindingInactivityExpiresAt, resolveThreadBindingIntroText, resolveThreadBindingMaxAgeExpiresAt, resolveThreadBindingMaxAgeMs, resolveThreadBindingPersona, resolveThreadBindingPersonaFromRecord, resolveThreadBindingThreadName, resolveThreadBindingsEnabled, sanitizeDiscordThreadName, searchMessagesDiscord, sendDiscordComponentMessage, sendMessageDiscord, sendPollDiscord, sendStickerDiscord, sendTypingDiscord, sendVoiceMessageDiscord, sendWebhookMessageDiscord, setChannelPermissionDiscord, setDiscordRuntime, setPresence, setThreadBindingIdleTimeoutBySessionKey, setThreadBindingMaxAgeBySessionKey, shouldEmitDiscordReactionNotification, timeoutMemberDiscord, unbindThreadBindingsBySessionKey, unpinMessageDiscord, unregisterGateway, uploadEmojiDiscord, uploadStickerDiscord, waitForDiscordGatewayPluginRegistration };
@@ -1,5 +1,5 @@
1
1
  import "./allow-list-CBI-M84K.js";
2
- import "./provider-B81nXBRc.js";
2
+ import "./provider-C4J1o-3R.js";
3
3
  import "./message-utils-CY91O2k2.js";
4
- import "./message-handler-D-Nboii4.js";
4
+ import "./message-handler-CgU3pJi2.js";
5
5
  export {};
@@ -1,8 +1,8 @@
1
1
  import { a as clearPresences, c as setPresence, i as unregisterGateway, n as getGateway, o as getPresence, r as registerGateway, s as presenceCacheSize, t as clearGateways } from "./gateway-registry-BKSpa4GB.js";
2
2
  import { _ as resolveGroupDmAllow, a as normalizeDiscordSlug, c as resolveDiscordChannelConfigWithFallback, d as resolveDiscordGuildEntry, g as resolveDiscordShouldRequireMention, n as isDiscordGroupAllowedByPolicy, r as normalizeDiscordAllowList, s as resolveDiscordChannelConfig, t as allowListMatches, u as resolveDiscordCommandAuthorized, v as shouldEmitDiscordReactionNotification } from "./allow-list-CBI-M84K.js";
3
3
  import { a as mergeAbortSignals, i as DISCORD_DEFAULT_LISTENER_TIMEOUT_MS, n as DISCORD_ATTACHMENT_TOTAL_TIMEOUT_MS, r as DISCORD_DEFAULT_INBOUND_WORKER_TIMEOUT_MS, t as DISCORD_ATTACHMENT_IDLE_TIMEOUT_MS } from "./timeouts-snXNwR4m.js";
4
- import { S as sanitizeDiscordThreadName, _ as registerDiscordListener, b as resolveDiscordReplyTarget, c as resolveDiscordGatewayIntents, d as createDiscordNativeCommand, l as waitForDiscordGatewayPluginRegistration, s as createDiscordGatewayPlugin, t as monitorDiscordProvider } from "./provider-B81nXBRc.js";
4
+ import { S as sanitizeDiscordThreadName, _ as registerDiscordListener, b as resolveDiscordReplyTarget, c as resolveDiscordGatewayIntents, d as createDiscordNativeCommand, l as waitForDiscordGatewayPluginRegistration, s as createDiscordGatewayPlugin, t as monitorDiscordProvider } from "./provider-C4J1o-3R.js";
5
5
  import { i as buildDiscordMediaPayload } from "./message-utils-CY91O2k2.js";
6
- import { t as createDiscordMessageHandler } from "./message-handler-D-Nboii4.js";
7
- import "./runtime-api.monitor-DJQdXyzE.js";
6
+ import { t as createDiscordMessageHandler } from "./message-handler-CgU3pJi2.js";
7
+ import "./runtime-api.monitor-dlMXA_pv.js";
8
8
  export { DISCORD_ATTACHMENT_IDLE_TIMEOUT_MS, DISCORD_ATTACHMENT_TOTAL_TIMEOUT_MS, DISCORD_DEFAULT_INBOUND_WORKER_TIMEOUT_MS, DISCORD_DEFAULT_LISTENER_TIMEOUT_MS, allowListMatches, buildDiscordMediaPayload, clearGateways, clearPresences, createDiscordGatewayPlugin, createDiscordMessageHandler, createDiscordNativeCommand, getGateway, getPresence, isDiscordGroupAllowedByPolicy, mergeAbortSignals, monitorDiscordProvider, normalizeDiscordAllowList, normalizeDiscordSlug, presenceCacheSize, registerDiscordListener, registerGateway, resolveDiscordChannelConfig, resolveDiscordChannelConfigWithFallback, resolveDiscordCommandAuthorized, resolveDiscordGatewayIntents, resolveDiscordGuildEntry, resolveDiscordReplyTarget, resolveDiscordShouldRequireMention, resolveGroupDmAllow, sanitizeDiscordThreadName, setPresence, shouldEmitDiscordReactionNotification, unregisterGateway, waitForDiscordGatewayPluginRegistration };
package/dist/test-api.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as discordPlugin } from "./channel-ngFtP-WD.js";
1
+ import { t as discordPlugin } from "./channel-DdqtpKwY.js";
2
2
  import { n as discordOutbound } from "./outbound-adapter-Fe4Ee_GO.js";
3
3
  import { t as __testing } from "./thread-bindings.manager-BL5QlX3G.js";
4
4
  import { n as buildDiscordInboundAccessContext } from "./inbound-context-BdfOEkhj.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/discord",
3
- "version": "2026.5.16-beta.2",
3
+ "version": "2026.5.16-beta.3",
4
4
  "description": "OpenClaw Discord channel plugin",
5
5
  "repository": {
6
6
  "type": "git",
@@ -21,7 +21,7 @@
21
21
  "openclaw": "workspace:*"
22
22
  },
23
23
  "peerDependencies": {
24
- "openclaw": ">=2026.5.16-beta.2"
24
+ "openclaw": ">=2026.5.16-beta.3"
25
25
  },
26
26
  "peerDependenciesMeta": {
27
27
  "openclaw": {
@@ -65,10 +65,10 @@
65
65
  "allowInvalidConfigRecovery": true
66
66
  },
67
67
  "compat": {
68
- "pluginApi": ">=2026.5.16-beta.2"
68
+ "pluginApi": ">=2026.5.16-beta.3"
69
69
  },
70
70
  "build": {
71
- "openclawVersion": "2026.5.16-beta.2"
71
+ "openclawVersion": "2026.5.16-beta.3"
72
72
  },
73
73
  "release": {
74
74
  "publishToClawHub": true,
@@ -1,2 +0,0 @@
1
- import { t as monitorDiscordProvider } from "./provider-B81nXBRc.js";
2
- export { monitorDiscordProvider };