@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.
- package/dist/{account-inspect-CqzrH14k.js → account-inspect-D5xmUpnj.js} +1 -1
- package/dist/account-inspect-api.js +1 -1
- package/dist/accounts-DNl-oCEw.js +371 -0
- package/dist/action-runtime-api.js +1 -1
- package/dist/{activities-api-DS7vpdtp.js → activities-api-KCBAmWxD.js} +133 -175
- package/dist/activities-api.js +1 -1
- package/dist/api.js +17 -17
- package/dist/{approval-handler.runtime-B6yEV79q.js → approval-handler.runtime-B12RCYr8.js} +6 -6
- package/dist/{approval-message-safety-AcIxvrf3.js → approval-message-safety-XGFPbDoI.js} +89 -3
- package/dist/{audit-Db-rlntl.js → audit-Yc7eZDd6.js} +5 -5
- package/dist/{channel-actions-5s_hjYKd.js → channel-actions-Dr2QI8Bf.js} +10 -6
- package/dist/{channel-actions.runtime-CLKrx6tr.js → channel-actions.runtime-CODTvo7c.js} +53 -68
- package/dist/{channel-CnnbJSt5.js → channel-cXYzGc4L.js} +74 -50
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.setup-BFAO-V1P.js → channel.setup-CSiwnMgs.js} +5 -5
- package/dist/{outbound-session-route-DxLkrgKQ.js → components-ezGKo_Yh.js} +3 -49
- package/dist/{config-schema-BgEskFAs.js → config-schema-DC5kDtQ5.js} +33 -7
- package/dist/conversation-binding-route-D6rCQ5S0.js +43 -0
- package/dist/{directory-config-BVX7Cflc.js → directory-config-XyCfoqLg.js} +2 -2
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-DGIGxpIo.js → directory-live-Df0NbFJB.js} +3 -3
- package/dist/{doctor-BzC-TLnB.js → doctor-DYY31GrO.js} +33 -12
- package/dist/doctor-contract-api.js +3 -3
- package/dist/{handle-action.guild-admin-BNVTUISF.js → handle-action.guild-admin-6Tvvinsa.js} +2 -2
- package/dist/index.js +3 -4
- package/dist/{message-handler-Unk_f10F.js → message-handler-B61q5MOF.js} +82 -6
- package/dist/{message-handler.preflight-C9zecxR9.js → message-handler.preflight-Bzg_Hawz.js} +36 -46
- package/dist/{message-handler.process-DWQ6UHHu.js → message-handler.process--4_712Ec.js} +159 -183
- package/dist/{message-utils-BSCPVgy0.js → message-utils-BXLLnFl6.js} +31 -32
- package/dist/{outbound-adapter-D9nRivT1.js → outbound-adapter-DxHTOqiN.js} +83 -53
- package/dist/{outbound-components-cTzwBJ60.js → outbound-components-B2PL0ooH.js} +3 -3
- package/dist/owner-access-Bg41VzAf.js +107 -0
- package/dist/{pluralkit-DdiJ9KMK.js → pluralkit-dUl4v1X3.js} +1 -1
- package/dist/{probe-Bl-k5_Ku.js → probe-BTdtVRwU.js} +1 -1
- package/dist/{probe.runtime-M9fREKvp.js → probe.runtime-Dq5-PRKT.js} +1 -1
- package/dist/{provider-DvSNb-2v.js → provider-DlK_ynqt.js} +356 -967
- package/dist/{provider-session.runtime-BUEqD0rA.js → provider-session.runtime-CvvphHvs.js} +3 -3
- package/dist/provider.runtime-CzKGRiAF.js +2 -0
- package/dist/{realtime-session.runtime-C7wen-aF.js → realtime-session.runtime-ysbMG8v7.js} +24 -13
- package/dist/{resolve-allowlist-common-D04lpEzb.js → resolve-allowlist-common-DIVXbD1P.js} +2 -2
- package/dist/{resolve-channels-Dm7jEeg6.js → resolve-channels-CGeUoIqb.js} +3 -3
- package/dist/{resolve-users-bktrCUUU.js → resolve-users-BtKxLUZv.js} +2 -2
- package/dist/{retry-CLpJcXXf.js → retry-DNsVTeTo.js} +18 -64
- package/dist/{runtime-DoHjckYm.js → runtime-CQovMsH3.js} +9 -10
- package/dist/{runtime-DGsSyDTS.js → runtime-D71_VFLr.js} +29 -43
- package/dist/runtime-api.actions.js +2 -2
- package/dist/runtime-api.js +22 -21
- package/dist/runtime-api.lookup.js +5 -5
- package/dist/runtime-api.monitor-CzeTYF32.js +6 -0
- package/dist/runtime-api.monitor.js +6 -5
- package/dist/runtime-api.send.js +6 -6
- package/dist/runtime-api.threads.js +4 -4
- package/dist/{sdk-runtime-QpY8PvCh.js → sdk-runtime-37OU6_Yh.js} +3 -4
- package/dist/{secret-config-contract-B1akrlyY.js → secret-config-contract-B3i6WxV5.js} +53 -25
- package/dist/secret-contract-api.js +1 -1
- package/dist/security-audit-contract-api.js +1 -1
- package/dist/{security-audit.runtime-CPN0xFYz.js → security-audit.runtime-BVKF9VtY.js} +1 -1
- package/dist/{send-B7Q6Oc1I.js → send-rQIffSYu.js} +10 -10
- package/dist/{send.components-iJyFXw9L.js → send.components-ChK1wS7w.js} +14 -24
- package/dist/{send.outbound-DS5tHwfR.js → send.outbound-HIkgji_7.js} +26 -16
- package/dist/{send.reactions-BAn0iiVQ.js → send.reactions-gmJ6yFPo.js} +2 -2
- package/dist/{send.receipt-IPI1p-SP.js → send.receipt-Cnhoautb.js} +11 -1
- package/dist/{send.shared-BmwFjW6T.js → send.shared-B3fpaLWJ.js} +104 -104
- package/dist/{sender-identity-QtalnCYv.js → sender-identity-BJtfyise.js} +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{shared-BIXIX6uJ.js → shared-CaAaoksy.js} +15 -10
- package/dist/subagent-hooks-CNT2ZJTJ.js +49 -0
- package/dist/subagent-hooks-api.js +2 -2
- package/dist/{subagent-progress-DhaE_h8a.js → subagent-progress-FPLqBY1s.js} +5 -4
- package/dist/{system-events-CTqDf6_s.js → system-events-Nuwoq_au.js} +2 -2
- package/dist/{target-resolver-maOKSqO0.js → target-resolver-DIXShHaZ.js} +3 -3
- package/dist/targets-B2pf49zc.js +3 -0
- package/dist/{thread-bindings-3L8p82GV.js → thread-bindings-VlymUnbz.js} +29 -26
- package/dist/{thread-bindings.manager-DCIH6WDC.js → thread-bindings.manager-CngsgErq.js} +9 -8
- package/dist/{thread-bindings.session-updates-bJ2KQFY6.js → thread-bindings.session-updates-CJb-BpPL.js} +1 -1
- package/dist/{thread-bindings.state-aeV8HNgV.js → thread-bindings.state-D8OMdk4O.js} +1 -1
- package/dist/threading-DU6pgeGm.js +456 -0
- package/dist/transcripts-source-DeIMNbRh.js +265 -0
- package/dist/transcripts-source-api.js +7 -2
- package/dist/{typing-CS-nNVoe.js → typing-oLiS5Z13.js} +1 -1
- package/dist/{voice-runtime-BEdqNcST.js → voice-runtime-CjNFaynA.js} +181 -91
- package/openclaw.plugin.json +12 -6
- package/package.json +4 -6
- package/dist/accounts-DJTf1LtA.js +0 -219
- package/dist/channel-api-CAJ0wMoV.js +0 -21
- package/dist/provider.runtime-C9PnJZbZ.js +0 -2
- package/dist/runtime-api.monitor-CHxrFPnW.js +0 -5
- package/dist/subagent-hooks-CTt5KCJr.js +0 -120
- package/dist/targets-yUFTHoAx.js +0 -3
- package/dist/transcripts-source-CfFMexGt.js +0 -123
- package/node_modules/p-map/index.d.ts +0 -155
- package/node_modules/p-map/index.js +0 -285
- package/node_modules/p-map/license +0 -9
- package/node_modules/p-map/package.json +0 -57
- package/node_modules/p-map/readme.md +0 -190
- package/dist/{allow-list-DnxIlPP2.js → allow-list-BDMimASD.js} +1 -1
- package/dist/{audit-core-xwjIczO0.js → audit-core-BCX8UeFH.js} +1 -1
- package/dist/{doctor-contract-DLa-BTiU.js → doctor-contract-DsWvKIXF.js} +1 -1
- package/dist/{security-audit-jGnJF__m.js → security-audit-BfJhAXZp.js} +1 -1
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { S as ResumedListener, T as VoiceStateUpdateListener, Ut as getGuildVoiceState, j as isUnknownDiscordVoiceStateError, p as discord_exports, x as ReadyListener } from "./retry-DNsVTeTo.js";
|
|
2
|
+
import { k as parseDiscordTarget } from "./accounts-DNl-oCEw.js";
|
|
2
3
|
import { t as getDiscordRuntime } from "./runtime-DgnVQ7zW.js";
|
|
3
|
-
import { a as normalizeDiscordSlug, h as resolveDiscordOwnerAccess, x as formatDiscordUserTag } from "./allow-list-
|
|
4
|
-
import { a as formatMention } from "./send.outbound-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
|
+
import { a as normalizeDiscordSlug, h as resolveDiscordOwnerAccess, x as formatDiscordUserTag } from "./allow-list-BDMimASD.js";
|
|
5
|
+
import { a as formatMention } from "./send.outbound-HIkgji_7.js";
|
|
6
|
+
import { n as resolveDiscordVoiceEnabled, r as authorizeDiscordVoiceIngress, t as resolveDiscordVoiceAccess } from "./owner-access-Bg41VzAf.js";
|
|
7
|
+
import { p as buildDiscordGroupSystemPrompt, y as resolveFetchedDiscordThreadLikeChannelContext } from "./provider-DlK_ynqt.js";
|
|
8
|
+
import { S as formatVoiceLogPreview, _ as decodeOpusStream, a as SPEAKING_READY_TIMEOUT_MS, b as formatVoiceIngressPrompt, c as isDiscordRealtimeVoiceMode, d as resolveDiscordVoiceMode, f as resolveVoiceTimeoutMs, g as createDiscordOpusPlaybackStream, i as PLAYBACK_READY_TIMEOUT_MS, l as isVoiceChannel, n as CAPTURE_FINALIZE_GRACE_MS, o as VOICE_CONNECT_READY_TIMEOUT_MS, s as VOICE_RECONNECT_GRACE_MS, t as loadDiscordVoiceSdk, u as logVoiceVerbose, v as decodeOpusStreamChunks, x as maybeControlDiscordVoiceAgentRun, y as writeVoiceWavFile } from "./sdk-runtime-37OU6_Yh.js";
|
|
9
9
|
import { asDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
|
|
10
10
|
import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
|
|
11
11
|
import { formatErrorMessage } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
12
|
+
import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
|
|
13
|
+
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
12
14
|
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
|
|
13
15
|
import { escapeRegExp, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
14
16
|
import { stripInlineDirectiveTagsForDisplay } from "openclaw/plugin-sdk/text-chunking";
|
|
15
|
-
import
|
|
17
|
+
import { unlinkIfExists } from "openclaw/plugin-sdk/media-runtime";
|
|
16
18
|
import { agentCommandFromIngress, resolveAgentDir } from "openclaw/plugin-sdk/agent-runtime";
|
|
17
19
|
import { enqueueRoutedSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
|
|
18
20
|
import { Readable } from "node:stream";
|
|
@@ -88,6 +90,7 @@ async function runDiscordVoiceAgentTurn(params) {
|
|
|
88
90
|
agentId: params.entry.route.agentId,
|
|
89
91
|
messageChannel: "discord",
|
|
90
92
|
messageProvider: DISCORD_VOICE_MESSAGE_PROVIDER,
|
|
93
|
+
accountId: params.accountId,
|
|
91
94
|
extraSystemPrompt: context.extraSystemPrompt,
|
|
92
95
|
senderIsOwner: context.senderIsOwner,
|
|
93
96
|
allowModelOverride: Boolean(voiceModel),
|
|
@@ -193,7 +196,7 @@ function countDiscordVoiceHumanParticipants(params) {
|
|
|
193
196
|
const userId = state.user_id?.trim();
|
|
194
197
|
if (!userId || userId === params.botUserId || knownUserIds.has(userId)) continue;
|
|
195
198
|
knownUserIds.add(userId);
|
|
196
|
-
if (state.member?.user
|
|
199
|
+
if (state.member?.user && state.member.user.bot !== true) count += 1;
|
|
197
200
|
}
|
|
198
201
|
for (const rawUserId of params.additionalUserIds ?? []) {
|
|
199
202
|
const userId = rawUserId.trim();
|
|
@@ -654,7 +657,8 @@ function normalizeVoiceChannelResidencies(entries) {
|
|
|
654
657
|
const channelId = entry.channelId?.trim();
|
|
655
658
|
if (guildId && channelId) normalized.push({
|
|
656
659
|
guildId,
|
|
657
|
-
channelId
|
|
660
|
+
channelId,
|
|
661
|
+
...entry.whenOccupied === true ? { whenOccupied: true } : {}
|
|
658
662
|
});
|
|
659
663
|
}
|
|
660
664
|
return normalized;
|
|
@@ -1017,6 +1021,7 @@ var DiscordVoiceFollowing = class {
|
|
|
1017
1021
|
}
|
|
1018
1022
|
resolveVoiceResidencyTarget(guildId) {
|
|
1019
1023
|
const autoJoinTarget = this.params.autoJoinChannels.toReversed().find((entry) => entry.guildId === guildId);
|
|
1024
|
+
if (autoJoinTarget?.whenOccupied) return null;
|
|
1020
1025
|
if (autoJoinTarget && this.params.isAllowedVoiceChannel(autoJoinTarget)) return autoJoinTarget;
|
|
1021
1026
|
if (this.params.allowedChannels === null) return null;
|
|
1022
1027
|
const guildAllowed = this.params.allowedChannels.filter((entry) => entry.guildId === guildId);
|
|
@@ -1142,6 +1147,7 @@ async function synthesizeVoiceReplyAudio(params) {
|
|
|
1142
1147
|
release: streamResult.release,
|
|
1143
1148
|
speakText
|
|
1144
1149
|
};
|
|
1150
|
+
const streamFailure = streamResult && !streamResult.success ? streamResult.attempts?.findLast((attempt) => attempt.outcome === "failed") : void 0;
|
|
1145
1151
|
const result = await runtime.tts.textToSpeech({
|
|
1146
1152
|
text: speakText,
|
|
1147
1153
|
cfg: prepared.cfg,
|
|
@@ -1156,7 +1162,11 @@ async function synthesizeVoiceReplyAudio(params) {
|
|
|
1156
1162
|
status: "ok",
|
|
1157
1163
|
mode: "file",
|
|
1158
1164
|
audioPath: result.audioPath,
|
|
1159
|
-
speakText
|
|
1165
|
+
speakText,
|
|
1166
|
+
...streamFailure ? { streamFailure: {
|
|
1167
|
+
provider: streamFailure.provider,
|
|
1168
|
+
reasonCode: streamFailure.reasonCode
|
|
1169
|
+
} } : {}
|
|
1160
1170
|
};
|
|
1161
1171
|
}
|
|
1162
1172
|
//#endregion
|
|
@@ -1219,10 +1229,12 @@ async function processDiscordVoiceSegment(params) {
|
|
|
1219
1229
|
logger$4.info(`discord voice: active-run control handled mode=${control.result.mode} ok=${control.result.ok} active=${control.result.active} reason=${control.result.reason ?? "none"} session=${entry.route.sessionKey}`);
|
|
1220
1230
|
replyText = control.speakText ?? "";
|
|
1221
1231
|
} else {
|
|
1232
|
+
const prompt = formatVoiceIngressPrompt(transcript, ingress.speakerLabel);
|
|
1222
1233
|
const turn = await runDiscordVoiceAgentTurn({
|
|
1223
1234
|
entry,
|
|
1235
|
+
accountId: params.accountId,
|
|
1224
1236
|
userId,
|
|
1225
|
-
message:
|
|
1237
|
+
message: prompt,
|
|
1226
1238
|
cfg: params.cfg,
|
|
1227
1239
|
discordConfig: params.discordConfig,
|
|
1228
1240
|
runtime: params.runtime,
|
|
@@ -1256,26 +1268,30 @@ async function processDiscordVoiceSegment(params) {
|
|
|
1256
1268
|
logger$4.warn(`discord voice: TTS failed: ${voiceReplyAudio.error ?? "unknown error"}`);
|
|
1257
1269
|
return;
|
|
1258
1270
|
}
|
|
1271
|
+
const streamFailure = voiceReplyAudio.mode === "file" ? voiceReplyAudio.streamFailure : void 0;
|
|
1272
|
+
if (streamFailure && !entry.ttsStreamFallbackWarned) {
|
|
1273
|
+
entry.ttsStreamFallbackWarned = true;
|
|
1274
|
+
logger$4.warn(`discord voice: streaming TTS failed provider=${streamFailure.provider} reasonCode=${streamFailure.reasonCode}; using file fallback`);
|
|
1275
|
+
}
|
|
1259
1276
|
logVoiceVerbose(`tts ok (${voiceReplyAudio.speakText.length} chars): guild ${entry.guildId} channel ${entry.channelId}`);
|
|
1277
|
+
const releaseAudio = voiceReplyAudio.mode === "stream" ? voiceReplyAudio.release : () => unlinkIfExists(voiceReplyAudio.audioPath);
|
|
1278
|
+
if (entry.sessionLifecycle.status === "stopped") {
|
|
1279
|
+
await releaseAudio?.();
|
|
1280
|
+
return;
|
|
1281
|
+
}
|
|
1260
1282
|
params.enqueuePlayback(entry, async () => {
|
|
1261
1283
|
const voiceSdk = loadDiscordVoiceSdk();
|
|
1262
|
-
const releaseAudioStream = voiceReplyAudio.mode === "stream" ? voiceReplyAudio.release : void 0;
|
|
1263
1284
|
try {
|
|
1264
|
-
if (
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
} else {
|
|
1270
|
-
logVoiceVerbose(`playback start: guild ${entry.guildId} channel ${entry.channelId} file ${path.basename(voiceReplyAudio.audioPath)}`);
|
|
1271
|
-
const resource = voiceSdk.createAudioResource(createDiscordOpusPlaybackStream(voiceReplyAudio.audioPath), { inputType: voiceSdk.StreamType.Opus });
|
|
1272
|
-
entry.player.play(resource);
|
|
1273
|
-
}
|
|
1285
|
+
if (entry.sessionLifecycle.status === "stopped") return;
|
|
1286
|
+
const input = voiceReplyAudio.mode === "stream" ? Readable.fromWeb(voiceReplyAudio.audioStream) : voiceReplyAudio.audioPath;
|
|
1287
|
+
logVoiceVerbose(`playback start: guild ${entry.guildId} channel ${entry.channelId} ${voiceReplyAudio.mode}`);
|
|
1288
|
+
const resource = voiceSdk.createAudioResource(createDiscordOpusPlaybackStream(input), { inputType: voiceSdk.StreamType.Opus });
|
|
1289
|
+
entry.player.play(resource);
|
|
1274
1290
|
await voiceSdk.entersState(entry.player, voiceSdk.AudioPlayerStatus.Playing, PLAYBACK_READY_TIMEOUT_MS).catch(() => void 0);
|
|
1275
1291
|
await voiceSdk.entersState(entry.player, voiceSdk.AudioPlayerStatus.Idle, SPEAKING_READY_TIMEOUT_MS).catch(() => void 0);
|
|
1276
1292
|
logVoiceVerbose(`playback done: guild ${entry.guildId} channel ${entry.channelId}`);
|
|
1277
1293
|
} finally {
|
|
1278
|
-
await
|
|
1294
|
+
await releaseAudio?.();
|
|
1279
1295
|
}
|
|
1280
1296
|
});
|
|
1281
1297
|
}
|
|
@@ -1415,6 +1431,7 @@ var DiscordVoiceReceive = class {
|
|
|
1415
1431
|
async processSegment(params) {
|
|
1416
1432
|
await processDiscordVoiceSegment({
|
|
1417
1433
|
...params,
|
|
1434
|
+
accountId: this.params.accountId,
|
|
1418
1435
|
cfg: this.params.cfg,
|
|
1419
1436
|
discordConfig: this.params.discordConfig,
|
|
1420
1437
|
admissionAllowFrom: this.params.admissionAllowFrom,
|
|
@@ -1515,6 +1532,7 @@ var DiscordVoiceReceive = class {
|
|
|
1515
1532
|
logger$3.info(`discord voice: agent turn start guild=${entry.guildId} channel=${entry.channelId} voiceSession=${entry.voiceSessionKey} supervisorSession=${entry.route.sessionKey} agent=${entry.route.agentId} user=${userId} speaker=${context.speakerLabel} owner=${context.senderIsOwner} model=${this.params.discordConfig.voice?.model ?? "route-default"} message=${formatVoiceLogPreview(message)}`);
|
|
1516
1533
|
const turn = await runDiscordVoiceAgentTurn({
|
|
1517
1534
|
entry,
|
|
1535
|
+
accountId: this.params.accountId,
|
|
1518
1536
|
userId,
|
|
1519
1537
|
message,
|
|
1520
1538
|
cfg: this.params.cfg,
|
|
@@ -1574,7 +1592,10 @@ var DiscordVoiceReceive = class {
|
|
|
1574
1592
|
const result = await this.params.join({
|
|
1575
1593
|
guildId: entry.guildId,
|
|
1576
1594
|
channelId: entry.channelId
|
|
1577
|
-
}, {
|
|
1595
|
+
}, {
|
|
1596
|
+
preserveFollowState,
|
|
1597
|
+
autoJoinWhenOccupied: entry.autoJoinWhenOccupied
|
|
1598
|
+
});
|
|
1578
1599
|
if (!result.ok) logger$3.warn(`discord voice: rejoin after decrypt failures failed: ${result.message}`);
|
|
1579
1600
|
}
|
|
1580
1601
|
};
|
|
@@ -1660,8 +1681,15 @@ var DiscordVoiceSessions = class {
|
|
|
1660
1681
|
const { guildId, channelId } = params;
|
|
1661
1682
|
const voiceConfig = this.params.discordConfig.voice;
|
|
1662
1683
|
const voiceMode = resolveDiscordVoiceMode(voiceConfig);
|
|
1684
|
+
const cancelledJoinResult = () => ({
|
|
1685
|
+
ok: false,
|
|
1686
|
+
message: "Discord voice join was cancelled.",
|
|
1687
|
+
guildId,
|
|
1688
|
+
channelId
|
|
1689
|
+
});
|
|
1663
1690
|
const existing = this.params.sessions.get(guildId);
|
|
1664
1691
|
if (existing && existing.channelId === channelId) {
|
|
1692
|
+
existing.autoJoinWhenOccupied = options?.autoJoinWhenOccupied === true;
|
|
1665
1693
|
if (authority) existing.generation = authority.generation;
|
|
1666
1694
|
if (options?.transcripts) existing.transcripts = options.transcripts;
|
|
1667
1695
|
if (!options?.transcripts && isDiscordRealtimeVoiceMode(voiceMode) && existing.realtimeLifecycle.status !== "active" && existing.realtimeLifecycle.status !== "starting") {
|
|
@@ -1688,14 +1716,20 @@ var DiscordVoiceSessions = class {
|
|
|
1688
1716
|
logVoiceVerbose(`join: replacing existing session for guild ${guildId}`);
|
|
1689
1717
|
await this.leave({ guildId }, { preserveFollowState: options?.preserveFollowState });
|
|
1690
1718
|
}
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1719
|
+
let channelInfo;
|
|
1720
|
+
try {
|
|
1721
|
+
channelInfo = await this.params.client.fetchChannel(channelId);
|
|
1722
|
+
} catch (err) {
|
|
1723
|
+
if (authority && !authority.isCurrent()) return cancelledJoinResult();
|
|
1724
|
+
return {
|
|
1725
|
+
ok: false,
|
|
1726
|
+
message: `Failed to resolve Discord channel ${channelId}: ${formatErrorMessage(err)}`,
|
|
1727
|
+
guildId,
|
|
1728
|
+
channelId
|
|
1729
|
+
};
|
|
1730
|
+
}
|
|
1731
|
+
if (authority && !authority.isCurrent()) return cancelledJoinResult();
|
|
1732
|
+
if (!isVoiceChannel(channelInfo.type)) return {
|
|
1699
1733
|
ok: false,
|
|
1700
1734
|
message: `Channel ${channelId} is not a voice channel.`
|
|
1701
1735
|
};
|
|
@@ -1774,12 +1808,7 @@ var DiscordVoiceSessions = class {
|
|
|
1774
1808
|
voiceSdk,
|
|
1775
1809
|
reason: `cancelled join guild ${guildId} channel ${channelId}`
|
|
1776
1810
|
});
|
|
1777
|
-
return
|
|
1778
|
-
ok: false,
|
|
1779
|
-
message: "Discord voice join was cancelled.",
|
|
1780
|
-
guildId,
|
|
1781
|
-
channelId
|
|
1782
|
-
};
|
|
1811
|
+
return cancelledJoinResult();
|
|
1783
1812
|
}
|
|
1784
1813
|
if (this.params.destroyed()) {
|
|
1785
1814
|
destroyVoiceConnectionSafely({
|
|
@@ -1855,6 +1884,7 @@ var DiscordVoiceSessions = class {
|
|
|
1855
1884
|
};
|
|
1856
1885
|
const entry = {
|
|
1857
1886
|
generation: authority?.generation ?? 0,
|
|
1887
|
+
autoJoinWhenOccupied: options?.autoJoinWhenOccupied === true,
|
|
1858
1888
|
sessionLifecycle: { status: "active" },
|
|
1859
1889
|
guildId,
|
|
1860
1890
|
guildName: channelInfo && "guild" in channelInfo && channelInfo.guild && typeof channelInfo.guild.name === "string" ? channelInfo.guild.name : void 0,
|
|
@@ -1867,6 +1897,7 @@ var DiscordVoiceSessions = class {
|
|
|
1867
1897
|
player,
|
|
1868
1898
|
playbackQueue: Promise.resolve(),
|
|
1869
1899
|
processingQueue: Promise.resolve(),
|
|
1900
|
+
ttsStreamFallbackWarned: false,
|
|
1870
1901
|
capture: createVoiceCaptureState(),
|
|
1871
1902
|
transcripts: options?.transcripts,
|
|
1872
1903
|
receiveRecovery: createVoiceReceiveRecoveryState(),
|
|
@@ -2011,8 +2042,9 @@ var DiscordVoiceSessions = class {
|
|
|
2011
2042
|
ok: false,
|
|
2012
2043
|
message: "Discord realtime voice session stopped before startup completed."
|
|
2013
2044
|
};
|
|
2014
|
-
const { DiscordRealtimeVoiceSession } = await import("./realtime-session.runtime-
|
|
2045
|
+
const { DiscordRealtimeVoiceSession } = await import("./realtime-session.runtime-ysbMG8v7.js");
|
|
2015
2046
|
const realtime = new DiscordRealtimeVoiceSession({
|
|
2047
|
+
accountId: this.params.accountId,
|
|
2016
2048
|
bootstrapContextInstructions,
|
|
2017
2049
|
cfg: this.params.cfg,
|
|
2018
2050
|
discordConfig: this.params.discordConfig,
|
|
@@ -2069,8 +2101,8 @@ var DiscordVoiceSessions = class {
|
|
|
2069
2101
|
//#endregion
|
|
2070
2102
|
//#region extensions/discord/src/voice/listeners.ts
|
|
2071
2103
|
const logger$1 = createSubsystemLogger("discord/voice");
|
|
2072
|
-
function startAutoJoin(
|
|
2073
|
-
|
|
2104
|
+
function startAutoJoin(operation, context = "") {
|
|
2105
|
+
operation().catch((err) => logger$1.warn(`discord voice: autoJoin${context} failed: ${formatErrorMessage(err)}`));
|
|
2074
2106
|
}
|
|
2075
2107
|
var DiscordVoiceReadyListener = class extends ReadyListener {
|
|
2076
2108
|
constructor(manager) {
|
|
@@ -2078,7 +2110,7 @@ var DiscordVoiceReadyListener = class extends ReadyListener {
|
|
|
2078
2110
|
this.manager = manager;
|
|
2079
2111
|
}
|
|
2080
2112
|
async handle(_data, _client) {
|
|
2081
|
-
startAutoJoin(this.manager);
|
|
2113
|
+
startAutoJoin(() => this.manager.autoJoin());
|
|
2082
2114
|
}
|
|
2083
2115
|
};
|
|
2084
2116
|
var DiscordVoiceResumedListener = class extends ResumedListener {
|
|
@@ -2087,7 +2119,7 @@ var DiscordVoiceResumedListener = class extends ResumedListener {
|
|
|
2087
2119
|
this.manager = manager;
|
|
2088
2120
|
}
|
|
2089
2121
|
async handle(_data, _client) {
|
|
2090
|
-
startAutoJoin(this.manager);
|
|
2122
|
+
startAutoJoin(() => this.manager.autoJoin());
|
|
2091
2123
|
}
|
|
2092
2124
|
};
|
|
2093
2125
|
var DiscordVoiceGuildCreateListener = class {
|
|
@@ -2096,7 +2128,10 @@ var DiscordVoiceGuildCreateListener = class {
|
|
|
2096
2128
|
this.type = discord_exports.GatewayDispatchEvents.GuildCreate;
|
|
2097
2129
|
}
|
|
2098
2130
|
async handle(data, _client) {
|
|
2099
|
-
if (!data.unavailable)
|
|
2131
|
+
if (!data.unavailable) {
|
|
2132
|
+
this.manager.refreshGuildRoster(data.id);
|
|
2133
|
+
startAutoJoin(() => this.manager.reconcileAutoJoinGuild(data.id), ` occupancy reconciliation guild=${data.id}`);
|
|
2134
|
+
}
|
|
2100
2135
|
}
|
|
2101
2136
|
};
|
|
2102
2137
|
var DiscordVoiceStateUpdateListener = class extends VoiceStateUpdateListener {
|
|
@@ -2137,9 +2172,10 @@ var DiscordVoiceManager = class {
|
|
|
2137
2172
|
this.guildLifecycles = /* @__PURE__ */ new Map();
|
|
2138
2173
|
this.nextGuildGeneration = 0;
|
|
2139
2174
|
this.joinTasks = /* @__PURE__ */ new Map();
|
|
2140
|
-
this.
|
|
2175
|
+
this.autoJoinTasks = /* @__PURE__ */ new Map();
|
|
2141
2176
|
this.fatalAutoJoinFailures = /* @__PURE__ */ new Map();
|
|
2142
2177
|
this.destroyed = false;
|
|
2178
|
+
this.client = params.client;
|
|
2143
2179
|
this.botUserId = params.botUserId;
|
|
2144
2180
|
this.voiceEnabled = resolveDiscordVoiceEnabled(params.discordConfig.voice);
|
|
2145
2181
|
const voiceAccess = resolveDiscordVoiceAccess(params);
|
|
@@ -2153,6 +2189,7 @@ var DiscordVoiceManager = class {
|
|
|
2153
2189
|
});
|
|
2154
2190
|
this.membership = new DiscordVoiceMembershipTracker(params.client, this.speakerContext, params.accountId);
|
|
2155
2191
|
this.receive = new DiscordVoiceReceive({
|
|
2192
|
+
accountId: params.accountId,
|
|
2156
2193
|
admissionAllowFrom: this.admissionAllowFrom,
|
|
2157
2194
|
botUserId: () => this.botUserId,
|
|
2158
2195
|
cfg: params.cfg,
|
|
@@ -2218,51 +2255,24 @@ var DiscordVoiceManager = class {
|
|
|
2218
2255
|
}
|
|
2219
2256
|
async autoJoin() {
|
|
2220
2257
|
if (!this.voiceEnabled || this.destroyed) return;
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
if (selected) logger.warn(`discord voice: autoJoin has multiple entries for guild ${guildId}; using channel ${selected.channelId}`);
|
|
2240
|
-
}
|
|
2241
|
-
for (const entry of entriesByGuild.values()) {
|
|
2242
|
-
const failureKey = formatAutoJoinFailureKey(entry);
|
|
2243
|
-
const fatalFailure = this.fatalAutoJoinFailures.get(failureKey);
|
|
2244
|
-
if (fatalFailure) {
|
|
2245
|
-
if (!fatalFailure.skipLogged) {
|
|
2246
|
-
logger.warn(`discord voice: autoJoin suppressed guild=${entry.guildId} channel=${entry.channelId} after fatal startup failure; retry with /vc join or reload config after fixing credentials: ${fatalFailure.message}`);
|
|
2247
|
-
fatalFailure.skipLogged = true;
|
|
2248
|
-
}
|
|
2249
|
-
continue;
|
|
2250
|
-
}
|
|
2251
|
-
logVoiceVerbose(`autoJoin: joining guild ${entry.guildId} channel ${entry.channelId}`);
|
|
2252
|
-
const result = await this.join(entry);
|
|
2253
|
-
if (!result.ok) {
|
|
2254
|
-
logger.warn(`discord voice: autoJoin skipped guild=${entry.guildId} channel=${entry.channelId}: ${result.message}`);
|
|
2255
|
-
if (isFatalAutoJoinFailure(result.message)) this.fatalAutoJoinFailures.set(failureKey, {
|
|
2256
|
-
message: result.message,
|
|
2257
|
-
skipLogged: false
|
|
2258
|
-
});
|
|
2259
|
-
}
|
|
2260
|
-
}
|
|
2261
|
-
await this.following.startReconciliation();
|
|
2262
|
-
})().finally(() => {
|
|
2263
|
-
this.autoJoinTask = null;
|
|
2264
|
-
});
|
|
2265
|
-
return this.autoJoinTask;
|
|
2258
|
+
const entriesByGuild = /* @__PURE__ */ new Map();
|
|
2259
|
+
const duplicateGuilds = /* @__PURE__ */ new Set();
|
|
2260
|
+
for (const entry of this.autoJoinChannels) {
|
|
2261
|
+
if (entriesByGuild.has(entry.guildId)) duplicateGuilds.add(entry.guildId);
|
|
2262
|
+
entriesByGuild.set(entry.guildId, entry);
|
|
2263
|
+
}
|
|
2264
|
+
logVoiceVerbose(`autoJoin: ${this.autoJoinChannels.length} entries, ${entriesByGuild.size} guilds`);
|
|
2265
|
+
for (const guildId of duplicateGuilds) {
|
|
2266
|
+
const selected = entriesByGuild.get(guildId);
|
|
2267
|
+
if (selected) logger.warn(`discord voice: autoJoin has multiple entries for guild ${guildId}; using channel ${selected.channelId}`);
|
|
2268
|
+
}
|
|
2269
|
+
for (const entry of entriesByGuild.values()) await this.enqueueAutoJoin(entry);
|
|
2270
|
+
await this.following.startReconciliation();
|
|
2271
|
+
}
|
|
2272
|
+
async reconcileAutoJoinGuild(guildId) {
|
|
2273
|
+
const entry = this.resolveAutoJoinTarget(guildId);
|
|
2274
|
+
if (!entry?.whenOccupied || !this.voiceEnabled || this.destroyed) return;
|
|
2275
|
+
await this.enqueueAutoJoin(entry);
|
|
2266
2276
|
}
|
|
2267
2277
|
status() {
|
|
2268
2278
|
return Array.from(this.guildLifecycles.values()).filter((lifecycle) => lifecycle.status === "active").map(({ instance: session }) => ({
|
|
@@ -2279,6 +2289,24 @@ var DiscordVoiceManager = class {
|
|
|
2279
2289
|
channelId: params.channelId.trim()
|
|
2280
2290
|
});
|
|
2281
2291
|
}
|
|
2292
|
+
async resolveAccessTarget(params) {
|
|
2293
|
+
const [guild, channel] = await Promise.all([this.client.fetchGuild(params.guildId).catch(() => null), this.client.fetchChannel(params.channelId).catch(() => null)]);
|
|
2294
|
+
if (!guild || !channel) return;
|
|
2295
|
+
const context = await resolveFetchedDiscordThreadLikeChannelContext({
|
|
2296
|
+
client: this.client,
|
|
2297
|
+
channel,
|
|
2298
|
+
channelIdFallback: params.channelId
|
|
2299
|
+
});
|
|
2300
|
+
return {
|
|
2301
|
+
guild,
|
|
2302
|
+
...context.channelName ? { channelName: context.channelName } : {},
|
|
2303
|
+
channelSlug: context.channelSlug,
|
|
2304
|
+
...context.parentId ? { parentId: context.parentId } : {},
|
|
2305
|
+
...context.threadParentName ? { parentName: context.threadParentName } : {},
|
|
2306
|
+
...context.threadParentSlug ? { parentSlug: context.threadParentSlug } : {},
|
|
2307
|
+
scope: context.isThreadChannel ? "thread" : "channel"
|
|
2308
|
+
};
|
|
2309
|
+
}
|
|
2282
2310
|
async join(params, options) {
|
|
2283
2311
|
if (this.destroyed) return {
|
|
2284
2312
|
ok: false,
|
|
@@ -2429,6 +2457,7 @@ var DiscordVoiceManager = class {
|
|
|
2429
2457
|
guildId,
|
|
2430
2458
|
channelId
|
|
2431
2459
|
});
|
|
2460
|
+
await this.reconcileAutoJoinGuild(guildId);
|
|
2432
2461
|
return;
|
|
2433
2462
|
}
|
|
2434
2463
|
this.membership.track(this.sessions.get(guildId), data, previousVoiceState);
|
|
@@ -2437,6 +2466,8 @@ var DiscordVoiceManager = class {
|
|
|
2437
2466
|
channelId,
|
|
2438
2467
|
userId
|
|
2439
2468
|
});
|
|
2469
|
+
const autoJoinTarget = this.resolveAutoJoinTarget(guildId);
|
|
2470
|
+
if (autoJoinTarget?.whenOccupied) await this.enqueueAutoJoin(autoJoinTarget);
|
|
2440
2471
|
}
|
|
2441
2472
|
async destroy() {
|
|
2442
2473
|
this.destroyed = true;
|
|
@@ -2454,6 +2485,65 @@ var DiscordVoiceManager = class {
|
|
|
2454
2485
|
const lifecycle = this.guildLifecycles.get(entry.guildId);
|
|
2455
2486
|
return lifecycle?.status === "active" && lifecycle.generation === entry.generation && lifecycle.instance === entry && entry.sessionLifecycle.status === "active";
|
|
2456
2487
|
}
|
|
2488
|
+
resolveAutoJoinTarget(guildId) {
|
|
2489
|
+
return this.autoJoinChannels.toReversed().find((entry) => entry.guildId === guildId.trim());
|
|
2490
|
+
}
|
|
2491
|
+
enqueueAutoJoin(entry) {
|
|
2492
|
+
const task = (this.autoJoinTasks.get(entry.guildId) ?? Promise.resolve()).catch(() => void 0).then(async () => await this.reconcileAutoJoinEntry(entry)).finally(() => {
|
|
2493
|
+
if (this.autoJoinTasks.get(entry.guildId) === task) this.autoJoinTasks.delete(entry.guildId);
|
|
2494
|
+
});
|
|
2495
|
+
this.autoJoinTasks.set(entry.guildId, task);
|
|
2496
|
+
return task;
|
|
2497
|
+
}
|
|
2498
|
+
async reconcileAutoJoinEntry(entry) {
|
|
2499
|
+
if (this.destroyed) return;
|
|
2500
|
+
const failureKey = formatAutoJoinFailureKey(entry);
|
|
2501
|
+
const fatalFailure = this.fatalAutoJoinFailures.get(failureKey);
|
|
2502
|
+
if (fatalFailure) {
|
|
2503
|
+
if (!fatalFailure.skipLogged) {
|
|
2504
|
+
logger.warn(`discord voice: autoJoin suppressed guild=${entry.guildId} channel=${entry.channelId} after fatal startup failure; retry with /vc join or reload config after fixing credentials: ${fatalFailure.message}`);
|
|
2505
|
+
fatalFailure.skipLogged = true;
|
|
2506
|
+
}
|
|
2507
|
+
return;
|
|
2508
|
+
}
|
|
2509
|
+
if (entry.whenOccupied) {
|
|
2510
|
+
const states = listDiscordVoiceParticipantStates({
|
|
2511
|
+
client: this.client,
|
|
2512
|
+
guildId: entry.guildId,
|
|
2513
|
+
channelId: entry.channelId
|
|
2514
|
+
});
|
|
2515
|
+
if (states === null) {
|
|
2516
|
+
logVoiceVerbose(`autoJoin waiting for guild voice snapshot guild=${entry.guildId} channel=${entry.channelId}`);
|
|
2517
|
+
return;
|
|
2518
|
+
}
|
|
2519
|
+
const humanCount = countDiscordVoiceHumanParticipants({
|
|
2520
|
+
states,
|
|
2521
|
+
botUserId: this.botUserId
|
|
2522
|
+
});
|
|
2523
|
+
const existing = this.sessions.get(entry.guildId);
|
|
2524
|
+
if (humanCount === 0) {
|
|
2525
|
+
if (!existing?.autoJoinWhenOccupied || existing.channelId !== entry.channelId) return;
|
|
2526
|
+
logger.info(`discord voice: occupied autoJoin leaving empty channel guild=${entry.guildId} channel=${entry.channelId}`);
|
|
2527
|
+
const result = await this.leave({
|
|
2528
|
+
guildId: entry.guildId,
|
|
2529
|
+
channelId: entry.channelId
|
|
2530
|
+
});
|
|
2531
|
+
if (!result.ok) logger.warn(`discord voice: occupied autoJoin failed to leave guild=${entry.guildId} channel=${entry.channelId}: ${result.message}`);
|
|
2532
|
+
return;
|
|
2533
|
+
}
|
|
2534
|
+
const lifecycle = this.guildLifecycles.get(entry.guildId);
|
|
2535
|
+
if (existing || lifecycle?.status === "starting" || lifecycle?.status === "active") return;
|
|
2536
|
+
logger.info(`discord voice: occupied autoJoin joining guild=${entry.guildId} channel=${entry.channelId} humans=${humanCount}`);
|
|
2537
|
+
} else logVoiceVerbose(`autoJoin: joining guild ${entry.guildId} channel ${entry.channelId}`);
|
|
2538
|
+
const result = await this.join(entry, { autoJoinWhenOccupied: entry.whenOccupied === true });
|
|
2539
|
+
if (!result.ok) {
|
|
2540
|
+
logger.warn(`discord voice: autoJoin skipped guild=${entry.guildId} channel=${entry.channelId}: ${result.message}`);
|
|
2541
|
+
if (isFatalAutoJoinFailure(result.message)) this.fatalAutoJoinFailures.set(failureKey, {
|
|
2542
|
+
message: result.message,
|
|
2543
|
+
skipLogged: false
|
|
2544
|
+
});
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2457
2547
|
};
|
|
2458
2548
|
//#endregion
|
|
2459
2549
|
export { DiscordVoiceGuildCreateListener, DiscordVoiceManager, DiscordVoiceReadyListener, DiscordVoiceResumedListener, DiscordVoiceStateUpdateListener };
|
package/openclaw.plugin.json
CHANGED
|
@@ -17,10 +17,6 @@
|
|
|
17
17
|
"discord"
|
|
18
18
|
],
|
|
19
19
|
"contracts": {
|
|
20
|
-
"tools": [
|
|
21
|
-
"show_widget",
|
|
22
|
-
"discord_widget"
|
|
23
|
-
],
|
|
24
20
|
"transcriptSourceProviders": [
|
|
25
21
|
"discord-voice"
|
|
26
22
|
]
|
|
@@ -1181,6 +1177,9 @@
|
|
|
1181
1177
|
"channelId": {
|
|
1182
1178
|
"type": "string",
|
|
1183
1179
|
"minLength": 1
|
|
1180
|
+
},
|
|
1181
|
+
"whenOccupied": {
|
|
1182
|
+
"type": "boolean"
|
|
1184
1183
|
}
|
|
1185
1184
|
},
|
|
1186
1185
|
"required": [
|
|
@@ -2989,6 +2988,9 @@
|
|
|
2989
2988
|
"channelId": {
|
|
2990
2989
|
"type": "string",
|
|
2991
2990
|
"minLength": 1
|
|
2991
|
+
},
|
|
2992
|
+
"whenOccupied": {
|
|
2993
|
+
"type": "boolean"
|
|
2992
2994
|
}
|
|
2993
2995
|
},
|
|
2994
2996
|
"required": [
|
|
@@ -3902,7 +3904,11 @@
|
|
|
3902
3904
|
},
|
|
3903
3905
|
"voice.autoJoin": {
|
|
3904
3906
|
"label": "Discord Voice Auto-Join",
|
|
3905
|
-
"help": "Voice channels to auto-join
|
|
3907
|
+
"help": "Voice channels to auto-join (list of guildId/channelId entries). Set whenOccupied on an entry to connect only while humans are present."
|
|
3908
|
+
},
|
|
3909
|
+
"voice.autoJoin.*.whenOccupied": {
|
|
3910
|
+
"label": "Discord Voice Auto-Join When Occupied",
|
|
3911
|
+
"help": "Join and remain in this auto-managed voice channel only while at least one human is present. The OpenClaw bot and other bots do not count. Default: false."
|
|
3906
3912
|
},
|
|
3907
3913
|
"voice.allowedChannels": {
|
|
3908
3914
|
"label": "Discord Voice Allowed Channels",
|
|
@@ -4035,7 +4041,7 @@
|
|
|
4035
4041
|
},
|
|
4036
4042
|
"activities": {
|
|
4037
4043
|
"label": "Discord Activities",
|
|
4038
|
-
"help": "Enable Discord Activity
|
|
4044
|
+
"help": "Enable the Discord Activity presenter for the core show_widget tool on this account. Activity routes and the launch handler remain disabled when this block is absent."
|
|
4039
4045
|
},
|
|
4040
4046
|
"activities.clientSecret": {
|
|
4041
4047
|
"label": "Discord Activities Client Secret",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/discord",
|
|
3
|
-
"version": "2026.8.1-beta.
|
|
3
|
+
"version": "2026.8.1-beta.3",
|
|
4
4
|
"description": "OpenClaw Discord channel plugin for channels, DMs, commands, and app events.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -13,14 +13,13 @@
|
|
|
13
13
|
"discord-api-types": "0.38.52",
|
|
14
14
|
"libopus-wasm": "0.2.0",
|
|
15
15
|
"mdast-util-from-markdown": "2.0.3",
|
|
16
|
-
"p-map": "7.0.6",
|
|
17
16
|
"typebox": "1.3.6",
|
|
18
17
|
"undici": "8.9.0",
|
|
19
18
|
"ws": "8.21.1",
|
|
20
19
|
"zod": "4.4.3"
|
|
21
20
|
},
|
|
22
21
|
"peerDependencies": {
|
|
23
|
-
"openclaw": ">=2026.8.1-beta.
|
|
22
|
+
"openclaw": ">=2026.8.1-beta.3"
|
|
24
23
|
},
|
|
25
24
|
"peerDependenciesMeta": {
|
|
26
25
|
"openclaw": {
|
|
@@ -95,10 +94,10 @@
|
|
|
95
94
|
"allowInvalidConfigRecovery": true
|
|
96
95
|
},
|
|
97
96
|
"compat": {
|
|
98
|
-
"pluginApi": ">=2026.8.1-beta.
|
|
97
|
+
"pluginApi": ">=2026.8.1-beta.3"
|
|
99
98
|
},
|
|
100
99
|
"build": {
|
|
101
|
-
"openclawVersion": "2026.8.1-beta.
|
|
100
|
+
"openclawVersion": "2026.8.1-beta.3",
|
|
102
101
|
"staticAssets": [
|
|
103
102
|
{
|
|
104
103
|
"source": "./assets/embedded-app-sdk.mjs",
|
|
@@ -130,7 +129,6 @@
|
|
|
130
129
|
"discord-api-types",
|
|
131
130
|
"libopus-wasm",
|
|
132
131
|
"mdast-util-from-markdown",
|
|
133
|
-
"p-map",
|
|
134
132
|
"typebox",
|
|
135
133
|
"undici",
|
|
136
134
|
"ws",
|