





















@@ -6,7 +6,11 @@ import { resolveOAuthDir } from "../../config/paths.js";
66import { AUTH_STORE_VERSION } from "./constants.js";
77import { legacyOAuthSidecarTestUtils } from "./legacy-oauth-sidecar.js";
88import { resolveAuthStorePath } from "./paths.js";
9-import { coercePersistedAuthProfileStore, loadPersistedAuthProfileStore } from "./persisted.js";
9+import {
10+coercePersistedAuthProfileStore,
11+loadPersistedAuthProfileStore,
12+mergeAuthProfileStores,
13+} from "./persisted.js";
10141115function withEnvValue(key: string, value: string | undefined): () => void {
1216const previous = process.env[key];
@@ -212,4 +216,139 @@ describe("persisted auth profile boundary", () => {
212216fs.rmSync(stateDir, { recursive: true, force: true });
213217}
214218});
219+220+it("lets authoritative runtime external metadata remove stale base profiles", () => {
221+const merged = mergeAuthProfileStores(
222+{
223+version: AUTH_STORE_VERSION,
224+runtimeExternalProfileIds: ["anthropic:claude-cli"],
225+runtimeExternalProfileIdsAuthoritative: true,
226+profiles: {
227+"anthropic:claude-cli": {
228+type: "oauth",
229+provider: "anthropic",
230+access: "stale-access",
231+refresh: "stale-refresh",
232+expires: 1,
233+},
234+},
235+order: {
236+anthropic: ["anthropic:claude-cli"],
237+},
238+lastGood: {
239+anthropic: "anthropic:claude-cli",
240+},
241+},
242+{
243+version: AUTH_STORE_VERSION,
244+runtimeExternalProfileIds: [],
245+runtimeExternalProfileIdsAuthoritative: true,
246+profiles: {},
247+},
248+);
249+250+expect(merged.runtimeExternalProfileIds).toEqual([]);
251+expect(merged.runtimeExternalProfileIdsAuthoritative).toBe(true);
252+expect(merged.profiles["anthropic:claude-cli"]).toBeUndefined();
253+expect(merged.order?.anthropic).toBeUndefined();
254+expect(merged.lastGood?.anthropic).toBeUndefined();
255+});
256+257+it("keeps override profiles when authoritative metadata removes base runtime external state", () => {
258+const profileId = "anthropic:claude-cli";
259+const merged = mergeAuthProfileStores(
260+{
261+version: AUTH_STORE_VERSION,
262+runtimeExternalProfileIds: [profileId],
263+runtimeExternalProfileIdsAuthoritative: true,
264+profiles: {
265+[profileId]: {
266+type: "oauth",
267+provider: "anthropic",
268+access: "stale-access",
269+refresh: "stale-refresh",
270+expires: 1,
271+},
272+},
273+order: {
274+anthropic: [profileId],
275+},
276+lastGood: {
277+anthropic: profileId,
278+},
279+},
280+{
281+version: AUTH_STORE_VERSION,
282+runtimeExternalProfileIds: [],
283+runtimeExternalProfileIdsAuthoritative: true,
284+profiles: {
285+[profileId]: {
286+type: "api_key",
287+provider: "anthropic",
288+key: "sk-local",
289+},
290+},
291+order: {
292+anthropic: [profileId],
293+},
294+lastGood: {
295+anthropic: profileId,
296+},
297+},
298+);
299+300+expect(merged.runtimeExternalProfileIds).toEqual([]);
301+expect(merged.runtimeExternalProfileIdsAuthoritative).toBe(true);
302+expect(merged.profiles[profileId]).toMatchObject({
303+type: "api_key",
304+provider: "anthropic",
305+key: "sk-local",
306+});
307+expect(merged.order?.anthropic).toEqual([profileId]);
308+expect(merged.lastGood?.anthropic).toBe(profileId);
309+});
310+311+it("preserves inherited base runtime external profiles during agent-store merges", () => {
312+const profileId = "anthropic:claude-cli";
313+const merged = mergeAuthProfileStores(
314+{
315+version: AUTH_STORE_VERSION,
316+runtimeExternalProfileIds: [profileId],
317+runtimeExternalProfileIdsAuthoritative: true,
318+profiles: {
319+[profileId]: {
320+type: "oauth",
321+provider: "anthropic",
322+access: "main-access",
323+refresh: "main-refresh",
324+expires: 1,
325+},
326+},
327+order: {
328+anthropic: [profileId],
329+},
330+lastGood: {
331+anthropic: profileId,
332+},
333+},
334+{
335+version: AUTH_STORE_VERSION,
336+runtimeExternalProfileIds: [],
337+runtimeExternalProfileIdsAuthoritative: true,
338+profiles: {},
339+},
340+{ preserveBaseRuntimeExternalProfiles: true },
341+);
342+343+expect(merged.runtimeExternalProfileIds).toEqual([profileId]);
344+expect(merged.runtimeExternalProfileIdsAuthoritative).toBe(true);
345+expect(merged.profiles[profileId]).toMatchObject({
346+type: "oauth",
347+provider: "anthropic",
348+access: "main-access",
349+refresh: "main-refresh",
350+});
351+expect(merged.order?.anthropic).toEqual([profileId]);
352+expect(merged.lastGood?.anthropic).toBe(profileId);
353+});
215354});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。