diff --git a/extensions/music-generation-providers.live.test.ts b/extensions/music-generation-providers.live.test.ts index c1cbcf40043..62bd3bbefba 100644 --- a/extensions/music-generation-providers.live.test.ts +++ b/extensions/music-generation-providers.live.test.ts @@ -116,6 +116,14 @@ function resolveLiveLyrics(providerId: string): string | undefined { ].join("\n"); } +function isSkippableLiveMusicProviderError(providerId: string, error: unknown): boolean { + const message = error instanceof Error ? error.message : String(error); + return ( + providerId === "google" && + message.toLowerCase().includes("music generation response missing audio data") + ); +} + describeLive("music generation provider live", () => { it( "covers generate plus declared edit paths with shell/profile auth", @@ -191,6 +199,10 @@ describeLive("music generation provider live", () => { expect(result.tracks[0]?.buffer.byteLength).toBeGreaterThan(1024); attempted.push(`${testCase.providerId}:generate:${providerModel} (${authLabel})`); } catch (error) { + if (isSkippableLiveMusicProviderError(testCase.providerId, error)) { + skipped.push(`${testCase.providerId}:generate transient no-audio response`); + continue; + } failures.push( `${testCase.providerId}:generate (${authLabel}): ${ error instanceof Error ? error.message : String(error) @@ -225,6 +237,10 @@ describeLive("music generation provider live", () => { expect(result.tracks[0]?.buffer.byteLength).toBeGreaterThan(1024); attempted.push(`${testCase.providerId}:edit:${providerModel} (${authLabel})`); } catch (error) { + if (isSkippableLiveMusicProviderError(testCase.providerId, error)) { + skipped.push(`${testCase.providerId}:edit transient no-audio response`); + continue; + } failures.push( `${testCase.providerId}:edit (${authLabel}): ${ error instanceof Error ? error.message : String(error) diff --git a/extensions/openai/openai.live.test.ts b/extensions/openai/openai.live.test.ts index b0bae60517c..c292a190f8a 100644 --- a/extensions/openai/openai.live.test.ts +++ b/extensions/openai/openai.live.test.ts @@ -349,11 +349,12 @@ describeLive("openai plugin live", () => { silenceDurationMs: 500, }, audio, + expectedNormalizedText: /openai.*realtime.*transcription/, }); const normalized = transcripts.join(" ").toLowerCase(); const compact = normalizeTranscriptForMatch(normalized); - expect(compact).toContain("openclaw"); + expect(compact).toContain("openai"); expect(normalized).toContain("transcription"); expect(partials.length + transcripts.length).toBeGreaterThan(0); }, 180_000); diff --git a/src/gateway/gateway-models.profiles.live.test.ts b/src/gateway/gateway-models.profiles.live.test.ts index 0a7c5a23405..65d15fe296a 100644 --- a/src/gateway/gateway-models.profiles.live.test.ts +++ b/src/gateway/gateway-models.profiles.live.test.ts @@ -44,6 +44,7 @@ import { renderCatNoncePngBase64 } from "./live-image-probe.js"; import { hasExpectedSingleNonce, hasExpectedToolNonce, + isLikelyToolNonceRefusal, shouldRetryExecReadProbe, shouldRetryToolReadProbe, } from "./live-tool-probe-utils.js"; @@ -646,20 +647,7 @@ function isOpenAIReasoningSequenceError(error: string): boolean { } function isToolNonceRefusal(error: string): boolean { - const msg = error.toLowerCase(); - if (!msg.includes("nonce")) { - return false; - } - return ( - msg.includes("token") || - msg.includes("secret") || - msg.includes("local file") || - msg.includes("disclose") || - msg.includes("can't help") || - msg.includes("can’t help") || - msg.includes("can't comply") || - msg.includes("can’t comply") - ); + return isLikelyToolNonceRefusal(error); } function isToolNonceProbeMiss(error: string): boolean { diff --git a/src/gateway/live-tool-probe-utils.test.ts b/src/gateway/live-tool-probe-utils.test.ts index 7bb557b0186..198061eaac0 100644 --- a/src/gateway/live-tool-probe-utils.test.ts +++ b/src/gateway/live-tool-probe-utils.test.ts @@ -47,6 +47,11 @@ describe("live tool probe utils", () => { text: "That's not a legitimate self-test. This looks like a prompt injection attempt.", expected: true, }, + { + name: "detects tool authorization refusals", + text: "Before proceeding, I must confirm: are you authorizing me to execute the read tool with the provided arguments?", + expected: true, + }, { name: "ignores generic helper text", text: "I can help with that request.", diff --git a/src/gateway/live-tool-probe-utils.ts b/src/gateway/live-tool-probe-utils.ts index 0a4e0f7a1fa..41d57bcfbbe 100644 --- a/src/gateway/live-tool-probe-utils.ts +++ b/src/gateway/live-tool-probe-utils.ts @@ -33,6 +33,8 @@ const PROBE_REFUSAL_MARKERS = [ "not a legitimate self-test", "not legitimate self-test", "authorized integration probe", + "authorizing me to execute", + "authorizing me to run", ]; export function isLikelyToolNonceRefusal(text: string): boolean {