From bbb10d0df5cce5127456c2ce342a700e71ea2b09 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 10 May 2026 15:16:56 +0100 Subject: [PATCH] fix(auth): return locked cli sync store --- src/agents/auth-profiles.store-cache.test.ts | 45 ++++++++++++++++++++ src/agents/auth-profiles/store.ts | 2 +- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/agents/auth-profiles.store-cache.test.ts b/src/agents/auth-profiles.store-cache.test.ts index a896722e88d..4499f79988e 100644 --- a/src/agents/auth-profiles.store-cache.test.ts +++ b/src/agents/auth-profiles.store-cache.test.ts @@ -297,4 +297,49 @@ describe("auth profile store cache", () => { expect(openaiProfile?.key).toBe("sk-concurrent"); }); }); + + it("returns the reloaded store when the synced CLI profile changed concurrently", async () => { + await withAgentDirEnv("openclaw-auth-store-external-cli-profile-race-", (agentDir) => { + const profileId = "anthropic:claude-cli"; + const authPath = writeOAuthStore(agentDir, profileId, { + type: "oauth", + provider: "claude-cli", + access: "stale-local-access", + refresh: "stale-local-refresh", + expires: Date.now() - 60_000, + }); + mocks.resolveExternalCliAuthProfiles.mockImplementationOnce(() => { + writeOAuthStore(agentDir, profileId, { + type: "oauth", + provider: "claude-cli", + access: "manual-concurrent-access", + refresh: "manual-concurrent-refresh", + expires: Date.now() + 120_000, + }); + return [ + createPersistedOverlay(profileId, { + type: "oauth", + provider: "claude-cli", + access: "fresh-cli-access", + refresh: "fresh-cli-refresh", + expires: Date.now() + 60_000, + }), + ]; + }); + + const first = ensureAuthProfileStore(agentDir); + const second = ensureAuthProfileStore(agentDir); + const persisted = JSON.parse(fs.readFileSync(authPath, "utf8")) as { + profiles: Record; + }; + + expect((first.profiles[profileId] as OAuthCredential | undefined)?.access).toBe( + "manual-concurrent-access", + ); + expect((second.profiles[profileId] as OAuthCredential | undefined)?.access).toBe( + "manual-concurrent-access", + ); + expect(persisted.profiles[profileId]?.access).toBe("manual-concurrent-access"); + }); + }); }); diff --git a/src/agents/auth-profiles/store.ts b/src/agents/auth-profiles/store.ts index 778eadb68ca..b8e68547088 100644 --- a/src/agents/auth-profiles/store.ts +++ b/src/agents/auth-profiles/store.ts @@ -411,10 +411,10 @@ function maybeSyncPersistedExternalCliAuthProfiles(params: { }); return latestStore; } + return latestStore; } finally { release(); } - return synced; } function shouldKeepProfileInLocalStore(params: {