fix: honor disabled synthetic auth lookup

This commit is contained in:
Peter Steinberger
2026-05-23 11:13:06 +01:00
parent 4e34ac483c
commit a4a1abbe30
4 changed files with 51 additions and 4 deletions

View File

@@ -126,6 +126,7 @@ vi.mock("../plugins/provider-runtime.js", async () => {
let applyAuthHeaderOverride: typeof import("./model-auth.js").applyAuthHeaderOverride;
let applyLocalNoAuthHeaderOverride: typeof import("./model-auth.js").applyLocalNoAuthHeaderOverride;
let createRuntimeProviderAuthLookup: typeof import("./model-auth.js").createRuntimeProviderAuthLookup;
let formatMissingAuthError: typeof import("./model-auth.js").formatMissingAuthError;
let hasUsableCustomProviderApiKey: typeof import("./model-auth.js").hasUsableCustomProviderApiKey;
let hasSyntheticLocalProviderAuthConfig: typeof import("./model-auth.js").hasSyntheticLocalProviderAuthConfig;
@@ -146,6 +147,7 @@ beforeAll(async () => {
({
applyAuthHeaderOverride,
applyLocalNoAuthHeaderOverride,
createRuntimeProviderAuthLookup,
formatMissingAuthError,
hasSyntheticLocalProviderAuthConfig,
getApiKeyForModel,
@@ -166,6 +168,17 @@ afterEach(() => {
clearRuntimeConfigSnapshot();
});
describe("createRuntimeProviderAuthLookup", () => {
it("omits synthetic auth refs when plugin synthetic auth is disabled", () => {
expect(
createRuntimeProviderAuthLookup({
includePluginSyntheticAuth: false,
env: {},
}).syntheticAuthProviderRefs,
).toBeUndefined();
});
});
async function withoutEnv<T>(key: string, fn: () => Promise<T>): Promise<T> {
const previous = process.env[key];
delete process.env[key];

View File

@@ -106,6 +106,7 @@ export function createRuntimeProviderAuthLookup(params: {
cfg?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
includePluginSyntheticAuth?: boolean;
}): RuntimeProviderAuthLookup {
const env = params.env ?? process.env;
const lookupParams = {
@@ -113,14 +114,17 @@ export function createRuntimeProviderAuthLookup(params: {
workspaceDir: params.workspaceDir,
env,
};
const syntheticAuthProviderRefs = resolveRuntimeSyntheticAuthProviderRefState(lookupParams);
const syntheticAuthProviderRefs =
params.includePluginSyntheticAuth === false
? undefined
: resolveRuntimeSyntheticAuthProviderRefState(lookupParams);
return {
envApiKey: {
aliasMap: resolveProviderAuthAliasMap(lookupParams),
candidateMap: resolveProviderEnvApiKeyCandidates(lookupParams),
authEvidenceMap: resolveProviderEnvAuthEvidence(lookupParams),
},
syntheticAuthProviderRefs: syntheticAuthProviderRefs.complete
syntheticAuthProviderRefs: syntheticAuthProviderRefs?.complete
? syntheticAuthProviderRefs.refs
: undefined,
};

View File

@@ -63,8 +63,12 @@ vi.mock("./agent-scope-config.js", () => ({
resolveDefaultAgentId: () => "default",
}));
const { clearCurrentProviderAuthState, hasAuthForModelProvider, warmCurrentProviderAuthState } =
await import("./model-provider-auth.js");
const {
clearCurrentProviderAuthState,
createProviderAuthChecker,
hasAuthForModelProvider,
warmCurrentProviderAuthState,
} = await import("./model-provider-auth.js");
describe("prepared provider auth state", () => {
afterEach(() => {
@@ -147,6 +151,31 @@ describe("prepared provider auth state", () => {
expect(modelAuthMocks.hasRuntimeAvailableProviderAuth).toHaveBeenCalledTimes(2);
});
it("does not prepare synthetic auth refs when plugin synthetic auth is disabled", async () => {
const cfg = {} as OpenClawConfig;
modelAuthMocks.hasRuntimeAvailableProviderAuth.mockReturnValue(false);
const hasAuth = createProviderAuthChecker({
cfg,
allowPluginSyntheticAuth: false,
discoverExternalCliAuth: false,
});
await expect(hasAuth("openai")).resolves.toBe(false);
expect(modelAuthMocks.createRuntimeProviderAuthLookup).toHaveBeenCalledWith({
cfg,
workspaceDir: undefined,
env: undefined,
includePluginSyntheticAuth: false,
});
const runtimeLookup =
modelAuthMocks.hasRuntimeAvailableProviderAuth.mock.calls[0]?.[0].runtimeLookup;
expect(runtimeLookup).toBe(
modelAuthMocks.createRuntimeProviderAuthLookup.mock.results[0]?.value,
);
});
it("hasAuthForModelProvider uses the prepared answer for equivalent runtime config clones", async () => {
const cfg = { gateway: { port: 18789 } } as OpenClawConfig;
const clonedCfg = structuredClone(cfg);

View File

@@ -188,6 +188,7 @@ export function createProviderAuthChecker(params: {
cfg: params.cfg,
workspaceDir: params.workspaceDir,
env: params.env,
includePluginSyntheticAuth: params.allowPluginSyntheticAuth !== false,
})),
});
authCache.set(key, value);