
























@@ -21,7 +21,10 @@ import { DISCORD_GATEWAY_TRANSPORT_ACTIVITY_EVENT } from "./gateway-handle.js";
2121const DISCORD_GATEWAY_BOT_URL = "https://discord.com/api/v10/gateway/bot";
2222const DISCORD_API_HOST = "discord.com";
2323const DEFAULT_DISCORD_GATEWAY_URL = "wss://gateway.discord.gg/";
24-const DISCORD_GATEWAY_INFO_TIMEOUT_MS = 10_000;
24+const DEFAULT_DISCORD_GATEWAY_INFO_TIMEOUT_MS = 30_000;
25+const MAX_DISCORD_GATEWAY_INFO_TIMEOUT_MS = 120_000;
26+const DISCORD_GATEWAY_INFO_TIMEOUT_ENV = "OPENCLAW_DISCORD_GATEWAY_INFO_TIMEOUT_MS";
27+const DISCORD_GATEWAY_METADATA_FALLBACK_LOG_INTERVAL_MS = 60_000;
25282629type DiscordGatewayMetadataResponse = Pick<Response, "ok" | "status" | "text">;
2730type DiscordGatewayFetchInit = Record<string, unknown> & {
@@ -35,6 +38,7 @@ type DiscordGatewayFetch = (
3538type DiscordGatewayMetadataError = Error & { transient?: boolean };
3639type DiscordGatewayWebSocketCtor = new (url: string, options?: { agent?: unknown }) => ws.WebSocket;
3740const registrationPromises = new WeakMap<carbonGateway.GatewayPlugin, Promise<void>>();
41+const gatewayMetadataFallbackLogLastAt = new WeakMap<RuntimeEnv, number>();
3842type CarbonGatewayRegistrationState = {
3943client?: Parameters<carbonGateway.GatewayPlugin["registerClient"]>[0];
4044ws?: unknown;
@@ -72,17 +76,36 @@ function hasCarbonGatewaySocketStarted(plugin: carbonGateway.GatewayPlugin): boo
7276return state.ws != null || state.isConnecting === true;
7377}
747875-export function resolveDiscordGatewayIntents(
76-intentsConfig?: import("openclaw/plugin-sdk/config-types").DiscordIntentsConfig,
77-): number {
79+type ResolveDiscordGatewayIntentsParams =
80+| import("openclaw/plugin-sdk/config-types").DiscordIntentsConfig
81+| {
82+intentsConfig?: import("openclaw/plugin-sdk/config-types").DiscordIntentsConfig;
83+voiceEnabled?: boolean;
84+};
85+86+function isGatewayIntentsResolverOptions(
87+value: ResolveDiscordGatewayIntentsParams | undefined,
88+): value is Exclude<ResolveDiscordGatewayIntentsParams, undefined> & {
89+intentsConfig?: import("openclaw/plugin-sdk/config-types").DiscordIntentsConfig;
90+voiceEnabled?: boolean;
91+} {
92+return Boolean(value && ("intentsConfig" in value || "voiceEnabled" in value));
93+}
94+95+export function resolveDiscordGatewayIntents(params?: ResolveDiscordGatewayIntentsParams): number {
96+const intentsConfig = isGatewayIntentsResolverOptions(params) ? params.intentsConfig : params;
97+const voiceEnabled = isGatewayIntentsResolverOptions(params) ? params.voiceEnabled : undefined;
98+const voiceStatesEnabled = intentsConfig?.voiceStates ?? voiceEnabled ?? true;
7899let intents =
79100carbonGateway.GatewayIntents.Guilds |
80101carbonGateway.GatewayIntents.GuildMessages |
81102carbonGateway.GatewayIntents.MessageContent |
82103carbonGateway.GatewayIntents.DirectMessages |
83104carbonGateway.GatewayIntents.GuildMessageReactions |
84-carbonGateway.GatewayIntents.DirectMessageReactions |
85-carbonGateway.GatewayIntents.GuildVoiceStates;
105+carbonGateway.GatewayIntents.DirectMessageReactions;
106+if (voiceStatesEnabled) {
107+intents |= carbonGateway.GatewayIntents.GuildVoiceStates;
108+}
86109if (intentsConfig?.presence) {
87110intents |= carbonGateway.GatewayIntents.GuildPresences;
88111}
@@ -92,6 +115,26 @@ export function resolveDiscordGatewayIntents(
92115return intents;
93116}
94117118+function normalizeGatewayInfoTimeoutMs(value: unknown): number | undefined {
119+const numeric =
120+typeof value === "number" ? value : typeof value === "string" ? Number(value) : NaN;
121+if (!Number.isFinite(numeric) || numeric <= 0) {
122+return undefined;
123+}
124+return Math.min(Math.floor(numeric), MAX_DISCORD_GATEWAY_INFO_TIMEOUT_MS);
125+}
126+127+export function resolveDiscordGatewayInfoTimeoutMs(params?: {
128+configuredTimeoutMs?: number;
129+env?: NodeJS.ProcessEnv;
130+}): number {
131+return (
132+normalizeGatewayInfoTimeoutMs(params?.configuredTimeoutMs) ??
133+normalizeGatewayInfoTimeoutMs(params?.env?.[DISCORD_GATEWAY_INFO_TIMEOUT_ENV]) ??
134+DEFAULT_DISCORD_GATEWAY_INFO_TIMEOUT_MS
135+);
136+}
137+95138function summarizeGatewayResponseBody(body: string): string {
96139const normalized = body.trim().replace(/\s+/g, " ");
97140if (!normalized) {
@@ -215,7 +258,7 @@ async function fetchDiscordGatewayInfoWithTimeout(params: {
215258fetchInit?: DiscordGatewayFetchInit;
216259timeoutMs?: number;
217260}): Promise<APIGatewayBotInfo> {
218-const timeoutMs = Math.max(1, params.timeoutMs ?? DISCORD_GATEWAY_INFO_TIMEOUT_MS);
261+const timeoutMs = Math.max(1, params.timeoutMs ?? DEFAULT_DISCORD_GATEWAY_INFO_TIMEOUT_MS);
219262const abortController = new AbortController();
220263let timeoutId: ReturnType<typeof setTimeout> | undefined;
221264const timeoutPromise = new Promise<never>((_, reject) => {
@@ -259,9 +302,19 @@ function resolveGatewayInfoWithFallback(params: { runtime?: RuntimeEnv; error: u
259302throw params.error;
260303}
261304const message = formatErrorMessage(params.error);
262-params.runtime?.log?.(
263-`discord: gateway metadata lookup failed transiently; using default gateway url (${message})`,
264-);
305+const now = Date.now();
306+if (params.runtime) {
307+const previous = gatewayMetadataFallbackLogLastAt.get(params.runtime);
308+if (
309+previous === undefined ||
310+now - previous >= DISCORD_GATEWAY_METADATA_FALLBACK_LOG_INTERVAL_MS
311+) {
312+params.runtime.log?.(
313+`discord: gateway metadata lookup failed transiently; using default gateway url (${message})`,
314+);
315+gatewayMetadataFallbackLogLastAt.set(params.runtime, now);
316+}
317+}
265318return {
266319info: createDefaultGatewayInfo(),
267320usedFallback: true,
@@ -274,6 +327,7 @@ function createGatewayPlugin(params: {
274327intents: number;
275328autoInteractions: boolean;
276329};
330+gatewayInfoTimeoutMs: number;
277331fetchImpl: DiscordGatewayFetch;
278332fetchInit?: DiscordGatewayFetchInit;
279333wsAgent?: InstanceType<typeof httpsProxyAgent.HttpsProxyAgent<string>>;
@@ -334,6 +388,7 @@ function createGatewayPlugin(params: {
334388token: client.options.token,
335389fetchImpl: params.fetchImpl,
336390fetchInit: params.fetchInit,
391+timeoutMs: params.gatewayInfoTimeoutMs,
337392})
338393.then((info) => ({
339394 info,
@@ -479,9 +534,16 @@ export function createDiscordGatewayPlugin(params: {
479534) => Promise<void>;
480535};
481536}): carbonGateway.GatewayPlugin {
482-const intents = resolveDiscordGatewayIntents(params.discordConfig?.intents);
537+const intents = resolveDiscordGatewayIntents({
538+intentsConfig: params.discordConfig?.intents,
539+voiceEnabled: params.discordConfig?.voice?.enabled !== false,
540+});
483541const proxy = resolveEffectiveDebugProxyUrl(params.discordConfig?.proxy);
484542const debugProxySettings = resolveDebugProxySettings();
543+const gatewayInfoTimeoutMs = resolveDiscordGatewayInfoTimeoutMs({
544+configuredTimeoutMs: params.discordConfig?.gatewayInfoTimeoutMs,
545+env: process.env,
546+});
485547const options = {
486548reconnect: { maxAttempts: 50 },
487549 intents,
@@ -493,6 +555,7 @@ export function createDiscordGatewayPlugin(params: {
493555if (!proxy) {
494556return createGatewayPlugin({
495557 options,
558+ gatewayInfoTimeoutMs,
496559fetchImpl: async (input, init) => {
497560return await fetchDiscordGatewayMetadataDirect(
498561input,
@@ -525,6 +588,7 @@ export function createDiscordGatewayPlugin(params: {
525588526589return createGatewayPlugin({
527590 options,
591+ gatewayInfoTimeoutMs,
528592fetchImpl: async (input, init) => {
529593return await fetchDiscordGatewayMetadataDirect(
530594input,
@@ -550,6 +614,7 @@ export function createDiscordGatewayPlugin(params: {
550614params.runtime.error?.(danger(`discord: invalid gateway proxy: ${String(err)}`));
551615return createGatewayPlugin({
552616 options,
617+ gatewayInfoTimeoutMs,
553618fetchImpl: (input, init) => fetchDiscordGatewayMetadataDirect(input, init, false),
554619runtime: params.runtime,
555620testing: params.__testing
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。