mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
fix(discord): use libopus structured decode errors
This commit is contained in:
8
extensions/discord/npm-shrinkwrap.json
generated
8
extensions/discord/npm-shrinkwrap.json
generated
@@ -10,7 +10,7 @@
|
||||
"dependencies": {
|
||||
"@discordjs/voice": "0.19.2",
|
||||
"discord-api-types": "0.38.48",
|
||||
"libopus-wasm": "0.1.0",
|
||||
"libopus-wasm": "0.2.0",
|
||||
"typebox": "1.1.39",
|
||||
"undici": "8.3.0",
|
||||
"ws": "8.21.0"
|
||||
@@ -352,9 +352,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/libopus-wasm": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/libopus-wasm/-/libopus-wasm-0.1.0.tgz",
|
||||
"integrity": "sha512-/aurGcAVgy0GcBEUzFaX9pm9qv7zYcy8W5hBXFiK+cyqOXAX4lOS6rlFogkY9CcSIajhjnuXyixsbmziSHCDMQ==",
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/libopus-wasm/-/libopus-wasm-0.2.0.tgz",
|
||||
"integrity": "sha512-x/2Gu1/C6L3IICY09zyfp984AWiOYjn53u4WfdY3yh+3KTzMN8Xkm77q3lenWMVIk5SnSzjGEkQT+VQMFHLBHQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"dependencies": {
|
||||
"@discordjs/voice": "0.19.2",
|
||||
"discord-api-types": "0.38.48",
|
||||
"libopus-wasm": "0.1.0",
|
||||
"libopus-wasm": "0.2.0",
|
||||
"typebox": "1.1.39",
|
||||
"undici": "8.3.0",
|
||||
"ws": "8.21.0"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { OpusError } from "libopus-wasm";
|
||||
import { OpusError, OpusErrorCode } from "libopus-wasm";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
analyzeVoiceReceiveError,
|
||||
@@ -33,7 +33,11 @@ describe("voice receive recovery", () => {
|
||||
});
|
||||
|
||||
it("treats corrupt Opus packets as non-recoverable decode noise", () => {
|
||||
expect(analyzeVoiceReceiveError(new OpusError(-4, "not inspected", "decode"))).toEqual({
|
||||
expect(
|
||||
analyzeVoiceReceiveError(
|
||||
new OpusError(OpusErrorCode.InvalidPacket, "not inspected", "decode"),
|
||||
),
|
||||
).toEqual({
|
||||
message: "not inspected",
|
||||
isAbortLike: false,
|
||||
isDecodeCorruption: true,
|
||||
@@ -42,6 +46,23 @@ describe("voice receive recovery", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("treats structurally equivalent Opus errors as decode corruption", () => {
|
||||
const analysis = analyzeVoiceReceiveError({
|
||||
name: "OpusError",
|
||||
message: "libopus decode failed (-4): corrupted stream",
|
||||
code: OpusErrorCode.InvalidPacket,
|
||||
codeName: "InvalidPacket",
|
||||
operation: "decode",
|
||||
});
|
||||
|
||||
expect(analysis).toMatchObject({
|
||||
isAbortLike: false,
|
||||
isDecodeCorruption: true,
|
||||
shouldAttemptPassthrough: false,
|
||||
countsAsDecryptFailure: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("does not classify corrupt Opus packet text without the Opus error contract", () => {
|
||||
expect(
|
||||
analyzeVoiceReceiveError(new Error("libopus decode failed (-4): corrupted stream")),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { OpusError } from "libopus-wasm";
|
||||
import { OpusErrorCode, isOpusError } from "libopus-wasm";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/ssrf-runtime";
|
||||
|
||||
const DECRYPT_FAILURE_WINDOW_MS = 30_000;
|
||||
@@ -6,7 +6,6 @@ const DECRYPT_FAILURE_RECONNECT_THRESHOLD = 3;
|
||||
const DECRYPT_FAILURE_MARKER = "DecryptionFailed(";
|
||||
const DAVE_PASSTHROUGH_DISABLED_MARKER = "UnencryptedWhenPassthroughDisabled";
|
||||
const WASM_MEMORY_ACCESS_MARKER = "memory access out of bounds";
|
||||
const OPUS_INVALID_PACKET_CODE = -4;
|
||||
|
||||
export const DAVE_RECEIVE_PASSTHROUGH_INITIAL_EXPIRY_SECONDS = 30;
|
||||
export const DAVE_RECEIVE_PASSTHROUGH_REARM_EXPIRY_SECONDS = 15;
|
||||
@@ -85,8 +84,8 @@ function isAbortLikeReceiveError(err: unknown): boolean {
|
||||
|
||||
function isOpusDecodeInvalidPacketError(err: unknown): boolean {
|
||||
return (
|
||||
err instanceof OpusError &&
|
||||
err.code === OPUS_INVALID_PACKET_CODE &&
|
||||
isOpusError(err) &&
|
||||
err.code === OpusErrorCode.InvalidPacket &&
|
||||
(err.operation === "decode" || err.operation === "decodeFloat")
|
||||
);
|
||||
}
|
||||
|
||||
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@@ -678,8 +678,8 @@ importers:
|
||||
specifier: 0.38.48
|
||||
version: 0.38.48
|
||||
libopus-wasm:
|
||||
specifier: 0.1.0
|
||||
version: 0.1.0
|
||||
specifier: 0.2.0
|
||||
version: 0.2.0
|
||||
typebox:
|
||||
specifier: 1.1.39
|
||||
version: 1.1.39
|
||||
@@ -5541,8 +5541,8 @@ packages:
|
||||
resolution: {integrity: sha512-s6WVJyEZrbm6jhBpiKHsGHyePMrVQKJ85wZCFCr9W4QHv6WTjWIrdvTmO9hDEA3bNK0xkrE2DqrHsXMLWuZpQg==}
|
||||
engines: {node: '>=22.0.0'}
|
||||
|
||||
libopus-wasm@0.1.0:
|
||||
resolution: {integrity: sha512-/aurGcAVgy0GcBEUzFaX9pm9qv7zYcy8W5hBXFiK+cyqOXAX4lOS6rlFogkY9CcSIajhjnuXyixsbmziSHCDMQ==}
|
||||
libopus-wasm@0.2.0:
|
||||
resolution: {integrity: sha512-x/2Gu1/C6L3IICY09zyfp984AWiOYjn53u4WfdY3yh+3KTzMN8Xkm77q3lenWMVIk5SnSzjGEkQT+VQMFHLBHQ==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
libsignal@6.0.0:
|
||||
@@ -11150,7 +11150,7 @@ snapshots:
|
||||
|
||||
kysely@0.29.2: {}
|
||||
|
||||
libopus-wasm@0.1.0: {}
|
||||
libopus-wasm@0.2.0: {}
|
||||
|
||||
libsignal@6.0.0:
|
||||
dependencies:
|
||||
|
||||
@@ -17,7 +17,7 @@ minimumReleaseAgeExclude:
|
||||
- "basic-ftp"
|
||||
- "baileys@7.0.0-rc13"
|
||||
- "hono"
|
||||
- "libopus-wasm@0.1.0"
|
||||
- "libopus-wasm@0.2.0"
|
||||
- "libsignal@6.0.0"
|
||||
- "openclaw"
|
||||
- "protobufjs"
|
||||
|
||||
Reference in New Issue
Block a user