fix: harden discord voice receive recovery (#41536) (thanks @wit-oc)

This commit is contained in:
Peter Steinberger
2026-04-06 18:42:07 +01:00
parent 37e89b930f
commit dfa14001a4
2 changed files with 11 additions and 7 deletions

View File

@@ -38,6 +38,7 @@ Docs: https://docs.openclaw.ai
- Gateway/containers: auto-bind to `0.0.0.0` during container startup for Docker and Podman compatibility, while keeping host-side status and doctor checks on the hardened loopback default when `gateway.bind` is unset. (#61818) Thanks @openperf.
- Gateway/status: probe local TLS gateways over `wss://`, forward the local cert fingerprint for self-signed loopback probes, and warn when the local TLS runtime cannot load the configured cert. (#61935) Thanks @ThanhNguyxn07.
- Slack/threading: keep legacy thread stickiness for real replies when older callers omit `isThreadReply`, while still honoring `replyToMode` for Slack's auto-created top-level `thread_ts`. (#61835) Thanks @kaonash.
- Discord/voice: re-arm DAVE receive passthrough without suppressing decrypt-failure rejoin recovery, and clear capture state before finalize teardown so rapid speaker restarts keep their next utterance. (#41536) Thanks @wit-oc.
- Providers/Google: recognize Gemma model ids in native Google forward-compat resolution, keep the requested provider when cloning fallback templates, and force Gemma reasoning off so Gemma 4 routes stop failing through the Google catalog fallback. (#61507) Thanks @eyjohn.
- Providers/Anthropic: skip `service_tier` injection for OAuth-authenticated stream wrapper requests so Claude OAuth requests stop failing with HTTP 401. (#60356) thanks @openperf.
- Providers/OpenAI: keep WebSocket text buffered until a real assistant phase arrives, even when text deltas land before a phaseless `output_item.added` announcement. (#61954) Thanks @100yenadmin.
@@ -59,6 +60,7 @@ Docs: https://docs.openclaw.ai
- Tools/web_fetch and web_search: fix `TypeError: fetch failed` caused by undici 8.0 enabling HTTP/2 by default; pinned SSRF-guard dispatchers now explicitly set `allowH2: false` to restore HTTP/1.1 behavior and keep the custom DNS-pinning lookup compatible. (#61738, #61777) Thanks @zozo123.
- Agents/session keys: backfill `sessionKey` from `sessionId` in the embedded PI runner when callers omit it, so hooks, LCM, and compaction receive a valid key; also normalize whitespace-only session keys to `undefined` before downstream consumers see them. (#60555) Thanks @100yenadmin.
- Plugins/provider hooks: stop recursive provider snapshot loads from overflowing the stack during plugin initialization, while still preserving cached nested provider-hook results. (#61922, #61938, #61946, #61951)
## 2026.4.5
### Breaking

View File

@@ -176,8 +176,14 @@ function isAbortLikeError(err: unknown): boolean {
if (!err || typeof err !== "object") {
return false;
}
const name = "name" in err ? String((err as { name?: unknown }).name ?? "") : "";
const message = "message" in err ? String((err as { message?: unknown }).message ?? "") : "";
const name =
"name" in err && typeof (err as { name?: unknown }).name === "string"
? (err as { name: string }).name
: "";
const message =
"message" in err && typeof (err as { message?: unknown }).message === "string"
? (err as { message: string }).message
: "";
return (
name === "AbortError" ||
message.includes("The operation was aborted") ||
@@ -653,11 +659,7 @@ export class DiscordVoiceManager {
.catch((err) => logger.warn(`discord voice: playback failed: ${formatErrorMessage(err)}`));
}
private clearCaptureFinalizeTimer(
entry: VoiceSessionEntry,
userId: string,
generation?: number,
) {
private clearCaptureFinalizeTimer(entry: VoiceSessionEntry, userId: string, generation?: number) {
const scheduled = entry.captureFinalizeTimers.get(userId);
if (!scheduled || (generation !== undefined && scheduled.generation !== generation)) {
return false;