From defaffbb937596e3967f24a9f593d03966edde0e Mon Sep 17 00:00:00 2001 From: Shakker Date: Mon, 15 Jun 2026 19:17:30 +0100 Subject: [PATCH] fix: keep CLI auth fallback scoped --- .../command/attempt-execution.cli.test.ts | 82 +++++++++++++++---- src/agents/command/attempt-execution.ts | 2 +- 2 files changed, 65 insertions(+), 19 deletions(-) diff --git a/src/agents/command/attempt-execution.cli.test.ts b/src/agents/command/attempt-execution.cli.test.ts index 277323d75175..35daa1911bf1 100644 --- a/src/agents/command/attempt-execution.cli.test.ts +++ b/src/agents/command/attempt-execution.cli.test.ts @@ -737,26 +737,22 @@ describe("CLI attempt execution", () => { }; const sessionStore: Record = { [sessionKey]: sessionEntry }; await fs.writeFile(storePath, JSON.stringify(sessionStore, null, 2), "utf-8"); - await fs.writeFile( - path.join(tmpDir, "auth-profiles.json"), - JSON.stringify( - { - version: 1, - profiles: { - "google-gemini-cli:user@example.test": { - type: "oauth", - provider: "google-gemini-cli", - access: "access-token", - refresh: "refresh-token", - expires: Date.now() + 3_600_000, - email: "user@example.test", - }, + saveAuthProfileStore( + { + version: 1, + profiles: { + "google-gemini-cli:user@example.test": { + type: "oauth", + provider: "google-gemini-cli", + access: "access-token", + refresh: "refresh-token", + expires: Date.now() + 3_600_000, + email: "user@example.test", }, }, - null, - 2, - ), - "utf-8", + }, + tmpDir, + { filterExternalAuthProfiles: false, syncExternalCli: false }, ); runCliAgentMock.mockResolvedValueOnce(makeCliResult("gemini cli response")); @@ -1319,6 +1315,56 @@ describe("CLI attempt execution", () => { }); }); + it("does not pass auth-order profiles to CLI backends that do not stage them", async () => { + const sessionKey = "agent:main:direct:claude-auth-order"; + const sessionEntry: SessionEntry = { + sessionId: "openclaw-session-claude-auth-order", + updatedAt: Date.now(), + }; + const sessionStore: Record = { [sessionKey]: sessionEntry }; + await fs.writeFile(storePath, JSON.stringify(sessionStore, null, 2), "utf-8"); + runCliAgentMock.mockResolvedValueOnce(makeCliResult("ambient claude cli")); + + await runAgentAttempt({ + providerOverride: "claude-cli", + originalProvider: "claude-cli", + modelOverride: "opus", + cfg: { + auth: { + order: { + "claude-cli": ["claude-cli:work"], + }, + }, + } as OpenClawConfig, + sessionEntry, + sessionId: sessionEntry.sessionId, + sessionKey, + sessionAgentId: "main", + sessionFile: path.join(tmpDir, "session.jsonl"), + workspaceDir: tmpDir, + body: "use ambient cli auth", + isFallbackRetry: false, + resolvedThinkLevel: "medium", + timeoutMs: 1_000, + runId: "run-claude-auth-order", + opts: {} as Parameters[0]["opts"], + runContext: {} as Parameters[0]["runContext"], + spawnedBy: undefined, + messageChannel: undefined, + skillsSnapshot: undefined, + resolvedVerboseLevel: undefined, + agentDir: tmpDir, + onAgentEvent: vi.fn(), + authProfileProvider: "claude-cli", + sessionStore, + storePath, + sessionHasHistory: false, + }); + + expect(runCliAgentMock).toHaveBeenCalledTimes(1); + expect(firstRunCliAgentArg().authProfileId).toBeUndefined(); + }); + it("forwards runtime toolsAllow into CLI attempts so the CLI harness can fail closed", async () => { const sessionKey = "agent:main:direct:claude-tools-allow"; const sessionEntry: SessionEntry = { diff --git a/src/agents/command/attempt-execution.ts b/src/agents/command/attempt-execution.ts index 484c5262bba3..ed3064d6fe83 100644 --- a/src/agents/command/attempt-execution.ts +++ b/src/agents/command/attempt-execution.ts @@ -642,7 +642,7 @@ export function runAgentAttempt(params: { nextCliSessionId === activeCliSessionBinding?.sessionId ? activeCliSessionBinding : undefined, - authProfileId: authProfileId ?? params.cfg.auth?.order?.[cliExecutionProvider]?.[0], + authProfileId, bootstrapPromptWarningSignaturesSeen, bootstrapPromptWarningSignature, images: params.isFallbackRetry ? undefined : params.opts.images,