




















@@ -28,6 +28,20 @@ const {
2828 formatProviderAuthProfileApiKeyWithPluginMock,
2929} = getOAuthProviderRuntimeMocks();
303031+function expectPersistedOpenAICodexProfileWithoutInlineTokens(
32+credential: AuthProfileStore["profiles"][string],
33+metadata: Record<string, unknown> = {},
34+): void {
35+expect(credential).toMatchObject({
36+type: "oauth",
37+provider: "openai-codex",
38+ ...metadata,
39+});
40+expect(credential).not.toHaveProperty("access");
41+expect(credential).not.toHaveProperty("refresh");
42+expect(credential).not.toHaveProperty("idToken");
43+}
44+3145function requireOAuthCredential(store: AuthProfileStore, profileId: string): OAuthCredential {
3246const profile = store.profiles[profileId];
3347if (!profile || profile.type !== "oauth") {
@@ -36,7 +50,7 @@ function requireOAuthCredential(store: AuthProfileStore, profileId: string): OAu
3650return profile;
3751}
385239-vi.mock("@earendil-works/pi-ai/oauth", () => ({
53+vi.mock("@mariozechner/pi-ai/oauth", () => ({
4054getOAuthProviders: () => [{ id: "anthropic" }, { id: "openai-codex" }],
4155getOAuthApiKey: vi.fn(async (provider: string, credentials: Record<string, OAuthCredential>) => {
4256const credential = credentials[provider];
@@ -85,7 +99,7 @@ describe("resolveApiKeyForProfile OAuth refresh mirror-to-main (#26322)", () =>
8599await removeOAuthTestTempRoot(tempRoot);
86100});
8710188-it("mirrors refreshed credentials into the main store so peers skip refresh", async () => {
102+it("mirrors refreshed Codex OAuth metadata into the main store without inline tokens", async () => {
89103const profileId = "openai-codex:default";
90104const provider = "openai-codex";
91105const accountId = "acct-shared";
@@ -116,15 +130,17 @@ describe("resolveApiKeyForProfile OAuth refresh mirror-to-main (#26322)", () =>
116130117131expect(result?.apiKey).toBe("sub-refreshed-access");
118132119-// Main store should now carry the refreshed credential, so a peer agent
120-// starting fresh will adopt rather than race.
133+// Main store should now carry refreshed metadata, so a peer agent
134+// starting fresh can resolve the runtime credential without token races.
121135const mainRaw = JSON.parse(
122136await fs.readFile(path.join(mainAgentDir, "auth-profiles.json"), "utf8"),
123137) as AuthProfileStore;
124-const mainCredential = requireOAuthCredential(mainRaw, profileId);
125-expect(mainCredential.access).toBe("sub-refreshed-access");
126-expect(mainCredential.refresh).toBe("sub-refreshed-refresh");
127-expect(mainCredential.expires).toBe(freshExpiry);
138+expectPersistedOpenAICodexProfileWithoutInlineTokens(mainRaw.profiles[profileId], {
139+expires: freshExpiry,
140+ accountId,
141+});
142+expect(JSON.stringify(mainRaw)).not.toContain("sub-refreshed-access");
143+expect(JSON.stringify(mainRaw)).not.toContain("sub-refreshed-refresh");
128144});
129145130146it("does not mirror when refresh was performed from the main agent itself", async () => {
@@ -161,10 +177,11 @@ describe("resolveApiKeyForProfile OAuth refresh mirror-to-main (#26322)", () =>
161177const mainRaw = JSON.parse(
162178await fs.readFile(path.join(mainAgentDir, "auth-profiles.json"), "utf8"),
163179) as AuthProfileStore;
164-const mainCredential = requireOAuthCredential(mainRaw, profileId);
165-expect(mainCredential.access).toBe("main-refreshed-access");
166-expect(mainCredential.refresh).toBe("main-refreshed-refresh");
167-expect(mainCredential.expires).toBe(freshExpiry);
180+expectPersistedOpenAICodexProfileWithoutInlineTokens(mainRaw.profiles[profileId], {
181+expires: freshExpiry,
182+});
183+expect(JSON.stringify(mainRaw)).not.toContain("main-refreshed-access");
184+expect(JSON.stringify(mainRaw)).not.toContain("main-refreshed-refresh");
168185expect(refreshProviderOAuthCredentialWithPluginMock).toHaveBeenCalledTimes(1);
169186});
170187@@ -332,17 +349,22 @@ describe("resolveApiKeyForProfile OAuth refresh mirror-to-main (#26322)", () =>
332349const subRaw = JSON.parse(
333350await fs.readFile(path.join(subAgentDir, "auth-profiles.json"), "utf8"),
334351) as AuthProfileStore;
335-const subCredential = requireOAuthCredential(subRaw, profileId);
336-expect(subCredential.access).toBe("local-stale-access");
337-expect(subCredential.refresh).toBe("local-stale-refresh");
352+expectPersistedOpenAICodexProfileWithoutInlineTokens(subRaw.profiles[profileId], {
353+expires: now - 120_000,
354+ accountId,
355+});
356+expect(JSON.stringify(subRaw)).not.toContain("local-stale-access");
357+expect(JSON.stringify(subRaw)).not.toContain("local-stale-refresh");
338358339359const mainRaw = JSON.parse(
340360await fs.readFile(path.join(mainAgentDir, "auth-profiles.json"), "utf8"),
341361) as AuthProfileStore;
342-const mainCredential = requireOAuthCredential(mainRaw, profileId);
343-expect(mainCredential.access).toBe("main-owner-refreshed-access");
344-expect(mainCredential.refresh).toBe("main-owner-refreshed-refresh");
345-expect(mainCredential.expires).toBe(freshExpiry);
362+expectPersistedOpenAICodexProfileWithoutInlineTokens(mainRaw.profiles[profileId], {
363+expires: freshExpiry,
364+ accountId,
365+});
366+expect(JSON.stringify(mainRaw)).not.toContain("main-owner-refreshed-access");
367+expect(JSON.stringify(mainRaw)).not.toContain("main-owner-refreshed-refresh");
346368});
347369348370it("inherits main-agent credentials via the catch-block fallback when refresh throws after main becomes fresh", async () => {
@@ -410,7 +432,10 @@ describe("resolveApiKeyForProfile OAuth refresh mirror-to-main (#26322)", () =>
410432const subRaw = JSON.parse(
411433await fs.readFile(path.join(subAgentDir, "auth-profiles.json"), "utf8"),
412434) as AuthProfileStore;
413-expect(requireOAuthCredential(subRaw, profileId).access).toBe("cached-access-token");
435+expectPersistedOpenAICodexProfileWithoutInlineTokens(subRaw.profiles[profileId], {
436+accountId: "acct-shared",
437+});
438+expect(JSON.stringify(subRaw)).not.toContain("cached-access-token");
414439});
415440416441it("mirrors refreshed credentials produced by the plugin-refresh path", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。