Skip to content

Commit 74331f6

Browse files
committed
test(live): tolerate ARM provider drift
1 parent f4a5e57 commit 74331f6

8 files changed

Lines changed: 60 additions & 5 deletions

extensions/google/google.live.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
import { normalizeTranscriptForMatch } from "openclaw/plugin-sdk/provider-test-contracts";
77
import { isLiveTestEnabled } from "openclaw/plugin-sdk/test-env";
88
import { describe, expect, it } from "vitest";
9+
import { hasTrustedFfmpegForLiveVoiceNote } from "../../test/helpers/live-voice-note.js";
910
import plugin from "./index.js";
1011
import { createGeminiWebSearchProvider } from "./src/gemini-web-search-provider.js";
1112

@@ -75,6 +76,10 @@ describeLive("google plugin live", () => {
7576
}, 120_000);
7677

7778
it("transcodes speech to Opus for voice-note targets", async () => {
79+
if (!hasTrustedFfmpegForLiveVoiceNote("google")) {
80+
return;
81+
}
82+
7883
const { speechProviders } = await registerGooglePlugin();
7984
const provider = requireRegisteredProvider(speechProviders, "google");
8085

extensions/minimax/minimax.live.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
} from "openclaw/plugin-sdk/plugin-test-runtime";
66
import { isLiveTestEnabled } from "openclaw/plugin-sdk/test-env";
77
import { describe, expect, it } from "vitest";
8+
import { hasTrustedFfmpegForLiveVoiceNote } from "../../test/helpers/live-voice-note.js";
89
import plugin from "./index.js";
910
import { buildMinimaxSpeechProvider } from "./speech-provider.js";
1011
import { createMiniMaxWebSearchProvider } from "./src/minimax-web-search-provider.js";
@@ -70,6 +71,10 @@ describeTtsLive("minimax tts live", () => {
7071
}, 120_000);
7172

7273
it("synthesizes MiniMax TTS as an Opus voice note", async () => {
74+
if (!hasTrustedFfmpegForLiveVoiceNote("minimax")) {
75+
return;
76+
}
77+
7378
const provider = buildMinimaxSpeechProvider();
7479

7580
const voiceNote = await provider.synthesize({

extensions/moonshot/moonshot.live.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,17 @@ function isTransientKimiSearchError(error: unknown): boolean {
1919
return message.includes("timeout") || message.includes("aborted");
2020
}
2121

22+
function isKimiAuthDrift(error: unknown): boolean {
23+
if (!(error instanceof Error)) {
24+
return false;
25+
}
26+
const message = error.message.toLowerCase();
27+
return (
28+
message.includes("kimi api error (401)") &&
29+
(message.includes("incorrect api key") || message.includes("incorrect_api_key"))
30+
);
31+
}
32+
2233
describeLive("moonshot plugin live", () => {
2334
it("runs Kimi web search through the provider tool", async () => {
2435
const provider = createKimiWebSearchProvider();
@@ -40,6 +51,10 @@ describeLive("moonshot plugin live", () => {
4051
break;
4152
} catch (error) {
4253
lastError = error;
54+
if (isKimiAuthDrift(error)) {
55+
console.warn("[moonshot:live] skip Kimi web search: auth drift");
56+
return;
57+
}
4358
if (!isTransientKimiSearchError(error) || attempt === 1) {
4459
throw error;
4560
}

src/agents/embedded-agent-runner-extraparams.live.test.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { describe, expect, it } from "vitest";
55
import type { OpenClawConfig } from "../config/config.js";
66
import { applyExtraParamsToAgent } from "./embedded-agent-runner.js";
77
import { isLiveTestEnabled } from "./live-test-helpers.js";
8-
import { isLiveBillingDrift } from "./live-test-provider-drift.js";
8+
import { isLiveAuthDrift, isLiveBillingDrift } from "./live-test-provider-drift.js";
99

1010
const OPENAI_KEY = process.env.OPENAI_API_KEY ?? "";
1111
const ANTHROPIC_KEY = process.env.ANTHROPIC_API_KEY ?? "";
@@ -143,9 +143,15 @@ describeAnthropicLive("embedded agent extra params (anthropic live)", () => {
143143
usage?: { service_tier?: string };
144144
};
145145
const errorMessage = json.error?.message ?? `HTTP ${res.status}`;
146-
if (!res.ok && isLiveBillingDrift(errorMessage)) {
147-
console.warn(`[anthropic:live] skip service_tier ${serviceTier}: billing drift`);
148-
return null;
146+
if (!res.ok) {
147+
if (isLiveBillingDrift(errorMessage)) {
148+
console.warn(`[anthropic:live] skip service_tier ${serviceTier}: billing drift`);
149+
return null;
150+
}
151+
if (isLiveAuthDrift(errorMessage)) {
152+
console.warn(`[anthropic:live] skip service_tier ${serviceTier}: auth drift`);
153+
return null;
154+
}
149155
}
150156
expect(res.ok, errorMessage).toBe(true);
151157
return json;

src/agents/live-test-provider-drift.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ describe("live test provider drift", () => {
1818
expect(
1919
isLiveAuthDrift('401 {"error":{"message":"The API key you provided is invalid."}}'),
2020
).toBe(true);
21+
expect(isLiveAuthDrift("invalid x-api-key")).toBe(true);
2122
});
2223

2324
it("classifies API-key rate-limit drift", () => {

src/agents/live-test-provider-drift.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,13 @@ export function liveProviderErrorText(error: unknown): string {
4747

4848
/** Returns whether an error is expected live auth/account drift. */
4949
export function isLiveAuthDrift(error: unknown): boolean {
50-
return isAuthErrorMessage(liveProviderErrorText(error));
50+
const raw = liveProviderErrorText(error);
51+
const message = normalizeLowercaseStringOrEmpty(raw);
52+
return (
53+
isAuthErrorMessage(raw) ||
54+
message.includes("invalid x-api-key") ||
55+
message.includes("incorrect x-api-key")
56+
);
5157
}
5258

5359
/** Returns whether an error is expected live billing/quota drift. */

src/agents/tools/image-tool.providers.live.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
isServerErrorMessage,
2020
} from "../../plugin-sdk/test-env.js";
2121
import { isLiveTestEnabled } from "../live-test-helpers.js";
22+
import { isLiveAuthDrift } from "../live-test-provider-drift.js";
2223
import { createImageTool, testing } from "./image-tool.js";
2324

2425
const OPENAI_API_KEY = process.env.OPENAI_API_KEY?.trim() ?? "";
@@ -115,6 +116,7 @@ function isSkippableLiveError(error: unknown): boolean {
115116
const message = formatLiveError(error);
116117
return (
117118
isBillingErrorMessage(message) ||
119+
isLiveAuthDrift(message) ||
118120
isOverloadedErrorMessage(message) ||
119121
isServerErrorMessage(message) ||
120122
/timed out|operation was aborted/i.test(message)

test/helpers/live-voice-note.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { resolveFfmpegBin } from "openclaw/plugin-sdk/media-runtime";
2+
3+
export function hasTrustedFfmpegForLiveVoiceNote(label: string): boolean {
4+
try {
5+
resolveFfmpegBin();
6+
return true;
7+
} catch (error) {
8+
const message = error instanceof Error ? error.message : String(error);
9+
if (message.includes("ffmpeg not found in trusted system directories")) {
10+
console.warn(`[${label}:live] skip voice-note transcode: ffmpeg unavailable`);
11+
return false;
12+
}
13+
throw error;
14+
}
15+
}

0 commit comments

Comments
 (0)