mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 23:30:44 +00:00
fix: keep usage auth gate runtime-free
This commit is contained in:
@@ -27,6 +27,7 @@ export {
|
||||
export {
|
||||
clearRuntimeAuthProfileStoreSnapshots,
|
||||
ensureAuthProfileStore,
|
||||
ensureAuthProfileStoreWithoutExternalProfiles,
|
||||
hasAnyAuthProfileStoreSource,
|
||||
loadAuthProfileStoreForSecretsRuntime,
|
||||
loadAuthProfileStoreWithoutExternalProfiles,
|
||||
|
||||
@@ -298,23 +298,30 @@ export function loadAuthProfileStoreWithoutExternalProfiles(agentDir?: string):
|
||||
export function ensureAuthProfileStore(
|
||||
agentDir?: string,
|
||||
options?: { allowKeychainPrompt?: boolean },
|
||||
): AuthProfileStore {
|
||||
return overlayExternalAuthProfiles(
|
||||
ensureAuthProfileStoreWithoutExternalProfiles(agentDir, options),
|
||||
{ agentDir },
|
||||
);
|
||||
}
|
||||
|
||||
export function ensureAuthProfileStoreWithoutExternalProfiles(
|
||||
agentDir?: string,
|
||||
options?: { allowKeychainPrompt?: boolean },
|
||||
): AuthProfileStore {
|
||||
const runtimeStore = resolveRuntimeAuthProfileStore(agentDir);
|
||||
if (runtimeStore) {
|
||||
return overlayExternalAuthProfiles(runtimeStore, { agentDir });
|
||||
return runtimeStore;
|
||||
}
|
||||
|
||||
const store = loadAuthProfileStoreForAgent(agentDir, options);
|
||||
const authPath = resolveAuthStorePath(agentDir);
|
||||
const mainAuthPath = resolveAuthStorePath();
|
||||
if (!agentDir || authPath === mainAuthPath) {
|
||||
return overlayExternalAuthProfiles(store, { agentDir });
|
||||
return store;
|
||||
}
|
||||
|
||||
const mainStore = loadAuthProfileStoreForAgent(undefined, options);
|
||||
const merged = mergeAuthProfileStores(mainStore, store);
|
||||
|
||||
return overlayExternalAuthProfiles(merged, { agentDir });
|
||||
return mergeAuthProfileStores(mainStore, store);
|
||||
}
|
||||
|
||||
export function findPersistedAuthProfileCredential(params: {
|
||||
|
||||
@@ -10,11 +10,16 @@ const hasAnyAuthProfileStoreSourceMock = vi.fn(() => false);
|
||||
const ensureAuthProfileStoreMock = vi.fn(() => ({
|
||||
profiles: {},
|
||||
}));
|
||||
const ensureAuthProfileStoreWithoutExternalProfilesMock = vi.fn(() => ({
|
||||
profiles: {},
|
||||
}));
|
||||
const resolveAuthProfileOrderMock = vi.fn((_params: unknown): string[] => []);
|
||||
|
||||
vi.mock("../agents/auth-profiles.js", () => ({
|
||||
dedupeProfileIds: (profileIds: string[]) => [...new Set(profileIds)],
|
||||
ensureAuthProfileStore: () => ensureAuthProfileStoreMock(),
|
||||
ensureAuthProfileStoreWithoutExternalProfiles: () =>
|
||||
ensureAuthProfileStoreWithoutExternalProfilesMock(),
|
||||
hasAnyAuthProfileStoreSource: () => hasAnyAuthProfileStoreSourceMock(),
|
||||
listProfilesForProvider: () => [],
|
||||
resolveApiKeyForProfile: async () => null,
|
||||
@@ -54,6 +59,10 @@ describe("resolveProviderAuths plugin boundary", () => {
|
||||
ensureAuthProfileStoreMock.mockReturnValue({
|
||||
profiles: {},
|
||||
});
|
||||
ensureAuthProfileStoreWithoutExternalProfilesMock.mockClear();
|
||||
ensureAuthProfileStoreWithoutExternalProfilesMock.mockReturnValue({
|
||||
profiles: {},
|
||||
});
|
||||
resolveAuthProfileOrderMock.mockReset();
|
||||
resolveAuthProfileOrderMock.mockReturnValue([]);
|
||||
resolveProviderUsageAuthWithPluginMock.mockReset();
|
||||
@@ -160,7 +169,7 @@ describe("resolveProviderAuths plugin boundary", () => {
|
||||
|
||||
it("keeps auth-profile credential sources provider-specific", async () => {
|
||||
hasAnyAuthProfileStoreSourceMock.mockReturnValue(true);
|
||||
ensureAuthProfileStoreMock.mockReturnValue({
|
||||
ensureAuthProfileStoreWithoutExternalProfilesMock.mockReturnValue({
|
||||
profiles: {
|
||||
"anthropic:default": {
|
||||
type: "api_key",
|
||||
@@ -201,6 +210,25 @@ describe("resolveProviderAuths plugin boundary", () => {
|
||||
provider: "anthropic",
|
||||
}),
|
||||
);
|
||||
expect(ensureAuthProfileStoreMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not overlay external auth profiles while checking the skip gate", async () => {
|
||||
hasAnyAuthProfileStoreSourceMock.mockReturnValue(true);
|
||||
|
||||
await withTempHome(async (homeDir) => {
|
||||
await expect(
|
||||
resolveProviderAuths({
|
||||
providers: ["anthropic"],
|
||||
skipPluginAuthWithoutCredentialSource: true,
|
||||
env: { HOME: homeDir },
|
||||
}),
|
||||
).resolves.toEqual([]);
|
||||
});
|
||||
|
||||
expect(ensureAuthProfileStoreWithoutExternalProfilesMock).toHaveBeenCalledTimes(1);
|
||||
expect(ensureAuthProfileStoreMock).not.toHaveBeenCalled();
|
||||
expect(resolveProviderUsageAuthWithPluginMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("skips plugin usage auth per provider when only another provider has direct credentials", async () => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
dedupeProfileIds,
|
||||
ensureAuthProfileStore,
|
||||
ensureAuthProfileStoreWithoutExternalProfiles,
|
||||
hasAnyAuthProfileStoreSource,
|
||||
listProfilesForProvider,
|
||||
resolveApiKeyForProfile,
|
||||
@@ -230,7 +231,9 @@ function hasAuthProfileCredentialSource(params: {
|
||||
state: UsageAuthState;
|
||||
provider: UsageProviderId;
|
||||
}): boolean {
|
||||
const store = resolveUsageAuthStore(params.state);
|
||||
const store = ensureAuthProfileStoreWithoutExternalProfiles(params.state.agentDir, {
|
||||
allowKeychainPrompt: false,
|
||||
});
|
||||
const order = resolveAuthProfileOrder({
|
||||
cfg: params.state.cfg,
|
||||
store,
|
||||
|
||||
Reference in New Issue
Block a user