From bfc77b0f456145c93d270a28cae651019dd06779 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Mon, 13 Apr 2026 15:58:09 +0100 Subject: [PATCH] perf(agents): keep fallback auth store cold without sources --- src/agents/model-fallback.test.ts | 27 +++++++++++++++++++++++++++ src/agents/model-fallback.ts | 13 +++++++++---- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/agents/model-fallback.test.ts b/src/agents/model-fallback.test.ts index 6d4c48edbb7..4e725454ae0 100644 --- a/src/agents/model-fallback.test.ts +++ b/src/agents/model-fallback.test.ts @@ -7,6 +7,7 @@ import type { OpenClawConfig } from "../config/config.js"; import { resetLogger, setLoggerOverride } from "../logging/logger.js"; import { createWarnLogCapture } from "../logging/test-helpers/warn-log-capture.js"; import { AUTH_STORE_VERSION } from "./auth-profiles/constants.js"; +import * as authProfileStoreModule from "./auth-profiles/store.js"; import { saveAuthProfileStore } from "./auth-profiles/store.js"; import type { AuthProfileStore } from "./auth-profiles/types.js"; import { isAnthropicBillingError } from "./live-auth-keys.js"; @@ -197,6 +198,32 @@ const MODEL_COOLDOWN_MESSAGE = "model_cooldown: All credentials for model gpt-5 const CONNECTION_ERROR_MESSAGE = "Connection error."; describe("runWithModelFallback", () => { + it("skips auth store bootstrap when no auth profile sources exist", async () => { + const hasSourcesSpy = vi + .spyOn(authProfileStoreModule, "hasAnyAuthProfileStoreSource") + .mockReturnValue(false); + const ensureStoreSpy = vi.spyOn(authProfileStoreModule, "ensureAuthProfileStore"); + const run = vi.fn().mockResolvedValueOnce("ok"); + + try { + const result = await runWithModelFallback({ + cfg: makeCfg(), + provider: "openai", + model: "gpt-4.1-mini", + agentDir: "/tmp/openclaw-no-auth-profiles", + run, + }); + + expect(result.result).toBe("ok"); + expect(hasSourcesSpy).toHaveBeenCalledWith("/tmp/openclaw-no-auth-profiles"); + expect(ensureStoreSpy).not.toHaveBeenCalled(); + expect(run).toHaveBeenCalledWith("openai", "gpt-4.1-mini"); + } finally { + hasSourcesSpy.mockRestore(); + ensureStoreSpy.mockRestore(); + } + }); + it("keeps openai gpt-5.3 codex on the openai provider before running", async () => { const cfg = makeCfg(); const run = vi.fn().mockResolvedValueOnce("ok"); diff --git a/src/agents/model-fallback.ts b/src/agents/model-fallback.ts index e094983f00d..118acd695a6 100644 --- a/src/agents/model-fallback.ts +++ b/src/agents/model-fallback.ts @@ -8,7 +8,11 @@ import { createSubsystemLogger } from "../logging/subsystem.js"; import { normalizeOptionalString } from "../shared/string-coerce.js"; import { sanitizeForLog } from "../terminal/ansi.js"; import { resolveAuthProfileOrder } from "./auth-profiles/order.js"; -import { ensureAuthProfileStore, loadAuthProfileStoreForRuntime } from "./auth-profiles/store.js"; +import { + ensureAuthProfileStore, + hasAnyAuthProfileStoreSource, + loadAuthProfileStoreForRuntime, +} from "./auth-profiles/store.js"; import { getSoonestCooldownExpiry, isProfileInCooldown, @@ -640,9 +644,10 @@ export async function runWithModelFallback(params: { model: params.model, fallbacksOverride: params.fallbacksOverride, }); - const authStore = params.cfg - ? ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false }) - : null; + const authStore = + params.cfg && hasAnyAuthProfileStoreSource(params.agentDir) + ? ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false }) + : null; const attempts: FallbackAttempt[] = []; let lastError: unknown; const cooldownProbeUsedProviders = new Set();