diff --git a/src/agents/cli-auth-epoch.test.ts b/src/agents/cli-auth-epoch.test.ts index 97be9acf190..62d0b411abd 100644 --- a/src/agents/cli-auth-epoch.test.ts +++ b/src/agents/cli-auth-epoch.test.ts @@ -47,6 +47,71 @@ describe("resolveCliAuthEpoch", () => { ).resolves.toBeUndefined(); }); + it("loads auth-profile epochs from the selected agent directory", async () => { + const stores: Record = { + "/agents/work/agent": { + version: 1, + profiles: { + "google-gemini-cli:default": { + type: "oauth", + provider: "google-gemini-cli", + access: "work-access", + refresh: "work-refresh", + expires: 1, + email: "work@example.test", + projectId: "work-project", + }, + }, + }, + "/agents/personal/agent": { + version: 1, + profiles: { + "google-gemini-cli:default": { + type: "oauth", + provider: "google-gemini-cli", + access: "personal-access", + refresh: "personal-refresh", + expires: 1, + email: "personal@example.test", + projectId: "personal-project", + }, + }, + }, + }; + const loadAuthProfileStoreForRuntime = vi.fn((agentDir?: string) => { + return stores[agentDir ?? ""] ?? { version: 1, profiles: {} }; + }); + setCliAuthEpochTestDeps({ + readGeminiCliCredentialsCached: () => null, + loadAuthProfileStoreForRuntime, + }); + + const work = await resolveCliAuthEpoch({ + provider: "google-gemini-cli", + agentDir: "/agents/work/agent", + authProfileId: "google-gemini-cli:default", + skipLocalCredential: true, + }); + const personal = await resolveCliAuthEpoch({ + provider: "google-gemini-cli", + agentDir: "/agents/personal/agent", + authProfileId: "google-gemini-cli:default", + skipLocalCredential: true, + }); + + expectCliAuthEpoch(work); + expectCliAuthEpoch(personal); + expect(work).not.toBe(personal); + expect(loadAuthProfileStoreForRuntime).toHaveBeenCalledWith("/agents/work/agent", { + readOnly: true, + allowKeychainPrompt: false, + }); + expect(loadAuthProfileStoreForRuntime).toHaveBeenCalledWith("/agents/personal/agent", { + readOnly: true, + allowKeychainPrompt: false, + }); + }); + it("keeps identity-less claude cli oauth epochs stable across token changes", async () => { let access = "access-a"; let refresh = "refresh-a"; diff --git a/src/agents/cli-auth-epoch.ts b/src/agents/cli-auth-epoch.ts index 871e2be9e96..dfdac2d959f 100644 --- a/src/agents/cli-auth-epoch.ts +++ b/src/agents/cli-auth-epoch.ts @@ -208,6 +208,7 @@ function getAuthProfileCredential( /** Resolves the stable auth epoch hash for a CLI runtime/provider session. */ export async function resolveCliAuthEpoch(params: { provider: string; + agentDir?: string; authProfileId?: string; skipLocalCredential?: boolean; }): Promise { @@ -223,7 +224,7 @@ export async function resolveCliAuthEpoch(params: { } if (authProfileId) { - const store = cliAuthEpochDeps.loadAuthProfileStoreForRuntime(undefined, { + const store = cliAuthEpochDeps.loadAuthProfileStoreForRuntime(params.agentDir, { readOnly: true, allowKeychainPrompt: false, }); diff --git a/src/agents/cli-runner/prepare.ts b/src/agents/cli-runner/prepare.ts index 427633531eb..41870f3a80e 100644 --- a/src/agents/cli-runner/prepare.ts +++ b/src/agents/cli-runner/prepare.ts @@ -485,6 +485,7 @@ export async function prepareCliRunContext( }); const authEpoch = await resolveCliAuthEpoch({ provider: params.provider, + agentDir, authProfileId: effectiveAuthProfileId, skipLocalCredential: skipLocalCredentialEpoch, });