

























@@ -205,7 +205,7 @@ describe("cli credentials", () => {
205205it.each([
206206{
207207name: "caches Claude Code CLI credentials within the TTL window",
208-allowKeychainPromptSecondRead: false,
208+allowKeychainPromptSecondRead: true,
209209advanceMs: 0,
210210expectedCalls: 1,
211211expectSameObject: true,
@@ -240,6 +240,62 @@ describe("cli credentials", () => {
240240},
241241);
242242243+it("does not let no-keychain Claude cache misses poison keychain reads", async () => {
244+const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-claude-cache-"));
245+vi.setSystemTime(new Date("2025-01-01T00:00:00Z"));
246+247+const withoutKeychain = readClaudeCliCredentialsCached({
248+allowKeychainPrompt: false,
249+ttlMs: CLI_CREDENTIALS_CACHE_TTL_MS,
250+platform: "darwin",
251+homeDir: tempDir,
252+execSync: execSyncMock,
253+});
254+255+expect(withoutKeychain).toBeNull();
256+expect(execSyncMock).not.toHaveBeenCalled();
257+258+mockClaudeCliCredentialRead();
259+const withKeychain = readClaudeCliCredentialsCached({
260+allowKeychainPrompt: true,
261+ttlMs: CLI_CREDENTIALS_CACHE_TTL_MS,
262+platform: "darwin",
263+homeDir: tempDir,
264+execSync: execSyncMock,
265+});
266+267+expect(withKeychain).toMatchObject({
268+type: "oauth",
269+provider: "anthropic",
270+refresh: "cached-refresh",
271+});
272+expect(execSyncMock).toHaveBeenCalledTimes(1);
273+});
274+275+it("reuses cached Claude keychain credentials for no-prompt reads", async () => {
276+const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-claude-cache-"));
277+vi.setSystemTime(new Date("2025-01-01T00:00:00Z"));
278+mockClaudeCliCredentialRead();
279+280+const withKeychain = readClaudeCliCredentialsCached({
281+allowKeychainPrompt: true,
282+ttlMs: CLI_CREDENTIALS_CACHE_TTL_MS,
283+platform: "darwin",
284+homeDir: tempDir,
285+execSync: execSyncMock,
286+});
287+const withoutPrompt = readClaudeCliCredentialsCached({
288+allowKeychainPrompt: false,
289+ttlMs: CLI_CREDENTIALS_CACHE_TTL_MS,
290+platform: "darwin",
291+homeDir: tempDir,
292+execSync: execSyncMock,
293+});
294+295+expect(withoutPrompt).toEqual(withKeychain);
296+expect(execSyncMock).toHaveBeenCalledTimes(1);
297+});
298+243299it("reads Codex credentials from keychain when available", async () => {
244300const tempHome = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-codex-"));
245301process.env.CODEX_HOME = tempHome;
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。