






















@@ -15,12 +15,10 @@ import {
1515extractAssistantText,
1616type LiveResolvedModel,
1717logLiveCache,
18-resolveLiveDirectModel,
18+resolveLiveDirectModelPool,
19+withLiveDirectModelApiKey,
1920} from "./live-cache-test-support.js";
20-import {
21-isAuthErrorMessage,
22-isBillingErrorMessage,
23-} from "./pi-embedded-helpers/failover-matches.js";
21+import { shouldSkipLiveProviderDrift } from "./live-test-provider-drift.js";
24222523const OPENAI_TIMEOUT_MS = 120_000;
2624const ANTHROPIC_TIMEOUT_MS = 120_000;
@@ -603,53 +601,52 @@ function appendBaselineFindings(target: BaselineFindings, source: BaselineFindin
603601target.warnings.push(...source.warnings);
604602}
605603606-function isAnthropicAccountDrift(error: unknown): boolean {
607-const message = error instanceof Error ? error.message : String(error);
608-return isBillingErrorMessage(message) || isAuthErrorMessage(message);
609-}
610-611604function isAnthropicEmptyCacheProbe(error: unknown): boolean {
612605return error instanceof CacheProbeTextMismatchError && error.text.trim().length === 0;
613606}
614607615-function cloneFixtureWithKey(fixture: LiveResolvedModel, apiKey: string): LiveResolvedModel {
616-return { ...fixture, apiKey };
608+function shouldSkipAnthropicCacheProviderDrift(error: unknown): boolean {
609+return Boolean(
610+shouldSkipLiveProviderDrift({
611+ error,
612+allowAuth: true,
613+allowBilling: true,
614+}),
615+);
617616}
618617619618async function runAnthropicCacheLane(params: {
619+apiKeys: readonly string[];
620620fixture: LiveResolvedModel;
621621lane: CacheLane;
622622pngBase64: string;
623623runToken: string;
624624warnings: string[];
625625}): Promise<{ attempt?: Awaited<ReturnType<typeof runRepeatedLaneWithBaselineRetry>> }> {
626-const keys =
627-params.fixture.apiKeys && params.fixture.apiKeys.length > 0
628- ? params.fixture.apiKeys
629- : [params.fixture.apiKey];
626+const keys = params.apiKeys.length > 0 ? params.apiKeys : [params.fixture.apiKey];
630627let lastError: unknown;
631628for (const [index, apiKey] of keys.entries()) {
632629try {
633630return {
634631attempt: await runRepeatedLaneWithBaselineRetry({
635632lane: params.lane,
636633providerTag: "anthropic",
637-fixture: cloneFixtureWithKey(params.fixture, apiKey),
634+fixture: withLiveDirectModelApiKey(params.fixture, apiKey),
638635runToken: params.runToken,
639636pngBase64: params.pngBase64,
640637}),
641638};
642639} catch (error) {
643640lastError = error;
644-if (isAnthropicAccountDrift(error) && index + 1 < keys.length) {
641+if (shouldSkipAnthropicCacheProviderDrift(error) && index + 1 < keys.length) {
645642logLiveCache(`anthropic ${params.lane} account drift; retrying with next key`);
646643continue;
647644}
648645break;
649646}
650647}
651648652-if (isAnthropicAccountDrift(lastError) || isAnthropicEmptyCacheProbe(lastError)) {
649+if (shouldSkipAnthropicCacheProviderDrift(lastError) || isAnthropicEmptyCacheProbe(lastError)) {
653650const reason = isAnthropicEmptyCacheProbe(lastError) ? "empty response" : "account drift";
654651const warning = `anthropic ${params.lane} skipped: ${reason}`;
655652params.warnings.push(warning);
@@ -671,7 +668,7 @@ async function runAnthropicDisabledCacheLane(params: {
671668sessionId: `live-cache-regression-${params.runToken}-anthropic-disabled`,
672669});
673670} catch (error) {
674-if (isAnthropicAccountDrift(error) || isAnthropicEmptyCacheProbe(error)) {
671+if (shouldSkipAnthropicCacheProviderDrift(error) || isAnthropicEmptyCacheProbe(error)) {
675672const warning = "anthropic disabled skipped: account drift";
676673params.warnings.push(warning);
677674logLiveCache(warning);
@@ -684,7 +681,6 @@ async function runAnthropicDisabledCacheLane(params: {
684681export const __testing = {
685682 assertAgainstBaseline,
686683 evaluateAgainstBaseline,
687- isAnthropicAccountDrift,
688684 resolveCacheProbeMaxTokens,
689685 shouldAcceptEmptyCacheProbe,
690686 shouldRetryCacheProbeText,
@@ -694,13 +690,13 @@ export const __testing = {
694690export async function runLiveCacheRegression(): Promise<LiveCacheRegressionResult> {
695691const pngBase64 = (await fs.readFile(LIVE_TEST_PNG_URL)).toString("base64");
696692const runToken = randomUUID().slice(0, 13);
697-const openai = await resolveLiveDirectModel({
693+const openai = await resolveLiveDirectModelPool({
698694provider: "openai",
699695api: "openai-responses",
700696envVar: "OPENCLAW_LIVE_OPENAI_CACHE_MODEL",
701697preferredModelIds: ["gpt-4.1", "gpt-5.2", "gpt-5.4-mini", "gpt-5.4", "gpt-5.5"],
702698});
703-const anthropic = await resolveLiveDirectModel({
699+const anthropic = await resolveLiveDirectModelPool({
704700provider: "anthropic",
705701api: "anthropic-messages",
706702envVar: "OPENCLAW_LIVE_ANTHROPIC_CACHE_MODEL",
@@ -718,7 +714,7 @@ export async function runLiveCacheRegression(): Promise<LiveCacheRegressionResul
718714const openaiAttempt = await runRepeatedLaneWithBaselineRetry({
719715 lane,
720716providerTag: "openai",
721-fixture: openai,
717+fixture: openai.fixture,
722718 runToken,
723719 pngBase64,
724720});
@@ -738,8 +734,9 @@ export async function runLiveCacheRegression(): Promise<LiveCacheRegressionResul
738734appendBaselineFindings({ regressions, warnings }, openaiAttempt.findings);
739735740736const { attempt: anthropicAttempt } = await runAnthropicCacheLane({
737+apiKeys: anthropic.apiKeys,
741738 lane,
742-fixture: anthropic,
739+fixture: anthropic.fixture,
743740 runToken,
744741 pngBase64,
745742 warnings,
@@ -765,7 +762,7 @@ export async function runLiveCacheRegression(): Promise<LiveCacheRegressionResul
765762}
766763767764const disabled = await runAnthropicDisabledCacheLane({
768-fixture: anthropic,
765+fixture: anthropic.fixture,
769766 runToken,
770767 warnings,
771768});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。