refactor: reuse provider auth lookup maps

This commit is contained in:
Shakker
2026-04-30 00:06:47 +01:00
parent e327c96ce6
commit 6662dcf209
6 changed files with 37 additions and 21 deletions

View File

@@ -20,14 +20,22 @@ export function resolveProviderEnvAuthEvidence(
return resolveProviderAuthEvidence(params);
}
export function resolveProviderEnvAuthLookupKeys(params?: ProviderEnvVarLookupParams): string[] {
const envCandidateMap = resolveProviderEnvApiKeyCandidates(params);
const authEvidenceMap = resolveProviderEnvAuthEvidence(params);
export function listProviderEnvAuthLookupKeys(params: {
envCandidateMap: Readonly<Record<string, readonly string[]>>;
authEvidenceMap: Readonly<Record<string, readonly ProviderAuthEvidence[]>>;
}): string[] {
return Array.from(
new Set([...Object.keys(envCandidateMap), ...Object.keys(authEvidenceMap)]),
new Set([...Object.keys(params.envCandidateMap), ...Object.keys(params.authEvidenceMap)]),
).toSorted((a, b) => a.localeCompare(b));
}
export function resolveProviderEnvAuthLookupKeys(params?: ProviderEnvVarLookupParams): string[] {
return listProviderEnvAuthLookupKeys({
envCandidateMap: resolveProviderEnvApiKeyCandidates(params),
authEvidenceMap: resolveProviderEnvAuthEvidence(params),
});
}
export const PROVIDER_ENV_API_KEY_CANDIDATES = resolveProviderEnvApiKeyCandidates();
export function listKnownProviderEnvApiKeyNames(): string[] {

View File

@@ -2,9 +2,9 @@ import fs from "node:fs";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { isRecord } from "../utils.js";
import {
listProviderEnvAuthLookupKeys,
resolveProviderEnvApiKeyCandidates,
resolveProviderEnvAuthEvidence,
resolveProviderEnvAuthLookupKeys,
} from "./model-auth-env-vars.js";
import { resolveEnvApiKey } from "./model-auth-env.js";
import type { PiCredentialMap } from "./pi-auth-credentials.js";
@@ -31,7 +31,10 @@ export function addEnvBackedPiCredentials(
// pi-coding-agent hides providers from its registry when auth storage lacks
// a matching credential entry. Mirror env-backed provider auth here so
// live/model discovery sees the same providers runtime auth can use.
for (const provider of resolveProviderEnvAuthLookupKeys(lookupParams)) {
for (const provider of listProviderEnvAuthLookupKeys({
envCandidateMap: candidateMap,
authEvidenceMap,
})) {
if (next[provider]) {
continue;
}

View File

@@ -9,6 +9,7 @@ import {
} from "./pi-auth-discovery-core.js";
vi.mock("./model-auth-env-vars.js", () => ({
listProviderEnvAuthLookupKeys: () => ["mistral", "workspace-cloud"],
resolveProviderEnvApiKeyCandidates: () => ({
mistral: ["MISTRAL_API_KEY"],
}),
@@ -21,7 +22,6 @@ vi.mock("./model-auth-env-vars.js", () => ({
},
],
}),
resolveProviderEnvAuthLookupKeys: () => ["mistral", "workspace-cloud"],
}));
vi.mock("./model-auth-env.js", () => ({

View File

@@ -1,8 +1,8 @@
import type { AuthProfileStore } from "../../agents/auth-profiles/types.js";
import {
listProviderEnvAuthLookupKeys,
resolveProviderEnvAuthEvidence,
resolveProviderEnvApiKeyCandidates,
resolveProviderEnvAuthLookupKeys,
} from "../../agents/model-auth-env-vars.js";
import { resolveEnvApiKey } from "../../agents/model-auth-env.js";
import { resolveAwsSdkEnvVarName } from "../../agents/model-auth-runtime-shared.js";
@@ -27,10 +27,6 @@ export type CreateModelListAuthIndexParams = {
syntheticAuthProviderRefs?: readonly string[];
};
export const EMPTY_MODEL_LIST_AUTH_INDEX: ModelListAuthIndex = {
hasProviderAuth: () => false,
};
function normalizeAuthProvider(
provider: string,
aliasMap: Readonly<Record<string, string>>,
@@ -90,12 +86,13 @@ export function createModelListAuthIndex(
addProvider(credential.provider);
}
for (const provider of resolveProviderEnvAuthLookupKeys(lookupParams)) {
for (const provider of listProviderEnvAuthLookupKeys({ envCandidateMap, authEvidenceMap })) {
if (
resolveEnvApiKey(provider, env, {
aliasMap,
candidateMap: envCandidateMap,
authEvidenceMap,
config: params.cfg,
workspaceDir: params.workspaceDir,
})
) {
@@ -131,8 +128,16 @@ export function createModelListAuthIndex(
if (cached !== undefined) {
return cached;
}
const hasPrecomputedCandidates = Object.hasOwn(envCandidateMap, normalized);
const hasPrecomputedEvidence = Object.hasOwn(authEvidenceMap, normalized);
const hasAuth = Boolean(
resolveEnvApiKey(provider, env, { aliasMap, candidateMap: envCandidateMap }),
resolveEnvApiKey(provider, env, {
aliasMap,
candidateMap: hasPrecomputedCandidates ? envCandidateMap : undefined,
authEvidenceMap: hasPrecomputedEvidence ? authEvidenceMap : undefined,
config: params.cfg,
workspaceDir: params.workspaceDir,
}),
);
envProviderAuthCache.set(normalized, hasAuth);
if (hasAuth) {

View File

@@ -17,9 +17,9 @@ import { ensureAuthProfileStoreWithoutExternalProfiles as ensureAuthProfileStore
import type { AuthProfileCredential } from "../../agents/auth-profiles/types.js";
import { resolveProfileUnusableUntilForDisplay } from "../../agents/auth-profiles/usage.js";
import {
listProviderEnvAuthLookupKeys,
resolveProviderEnvApiKeyCandidates,
resolveProviderEnvAuthEvidence,
resolveProviderEnvAuthLookupKeys,
} from "../../agents/model-auth-env-vars.js";
import { resolveEnvApiKey } from "../../agents/model-auth.js";
import {
@@ -257,7 +257,7 @@ export async function modelsStatusCommand(
};
const envCandidateMap = resolveProviderEnvApiKeyCandidates(envLookupParams);
const authEvidenceMap = resolveProviderEnvAuthEvidence(envLookupParams);
for (const provider of resolveProviderEnvAuthLookupKeys(envLookupParams)) {
for (const provider of listProviderEnvAuthLookupKeys({ envCandidateMap, authEvidenceMap })) {
if (
resolveEnvApiKey(provider, process.env, {
config: cfg,

View File

@@ -92,7 +92,7 @@ const mocks = vi.hoisted(() => {
fal: ["FAL_KEY"],
}),
resolveProviderEnvAuthEvidence: vi.fn().mockReturnValue({}),
resolveProviderEnvAuthLookupKeys: vi
listProviderEnvAuthLookupKeys: vi
.fn()
.mockImplementation(() => [
"anthropic",
@@ -206,9 +206,9 @@ vi.mock("../../agents/model-auth.js", () => ({
getCustomProviderApiKey: mocks.getCustomProviderApiKey,
}));
vi.mock("../../agents/model-auth-env-vars.js", () => ({
listProviderEnvAuthLookupKeys: mocks.listProviderEnvAuthLookupKeys,
resolveProviderEnvApiKeyCandidates: mocks.resolveProviderEnvApiKeyCandidates,
resolveProviderEnvAuthEvidence: mocks.resolveProviderEnvAuthEvidence,
resolveProviderEnvAuthLookupKeys: mocks.resolveProviderEnvAuthLookupKeys,
listKnownProviderEnvApiKeyNames: mocks.listKnownProviderEnvApiKeyNames,
}));
vi.mock("../../agents/model-selection-cli.js", () => ({
@@ -543,11 +543,11 @@ describe("modelsStatusCommand auth overview", () => {
it("includes auth-evidence-only providers in the auth overview", async () => {
const localRuntime = createRuntime();
const originalKeysImpl = mocks.resolveProviderEnvAuthLookupKeys.getMockImplementation();
const originalKeysImpl = mocks.listProviderEnvAuthLookupKeys.getMockImplementation();
const originalEvidenceImpl = mocks.resolveProviderEnvAuthEvidence.getMockImplementation();
const originalEnvImpl = mocks.resolveEnvApiKey.getMockImplementation();
mocks.resolveProviderEnvAuthLookupKeys.mockReturnValue(["workspace-cloud"]);
mocks.listProviderEnvAuthLookupKeys.mockReturnValue(["workspace-cloud"]);
mocks.resolveProviderEnvAuthEvidence.mockReturnValue({
"workspace-cloud": [
{
@@ -581,7 +581,7 @@ describe("modelsStatusCommand auth overview", () => {
);
} finally {
if (originalKeysImpl) {
mocks.resolveProviderEnvAuthLookupKeys.mockImplementation(originalKeysImpl);
mocks.listProviderEnvAuthLookupKeys.mockImplementation(originalKeysImpl);
}
if (originalEvidenceImpl) {
mocks.resolveProviderEnvAuthEvidence.mockImplementation(originalEvidenceImpl);