test: share models config merge helpers

This commit is contained in:
Peter Steinberger 2026-03-14 02:24:58 +00:00
parent 7aedb6d442
commit 8622395c8b
1 changed files with 98 additions and 97 deletions

View File

@ -60,13 +60,31 @@ function createMergeConfigProvider() {
}; };
} }
async function runCustomProviderMergeTest(params: { type MergeSeedProvider = {
seedProvider: { baseUrl: string;
baseUrl: string; apiKey: string;
apiKey: string; api: string;
api: string; models: Array<{ id: string; name: string; input: string[]; api?: string }>;
models: Array<{ id: string; name: string; input: string[]; api?: string }>; };
type MergeConfigApiKeyRef = {
source: "env";
provider: "default";
id: string;
};
function createAgentSeedProvider(overrides: Partial<MergeSeedProvider> = {}): MergeSeedProvider {
return {
baseUrl: "https://agent.example/v1",
apiKey: "AGENT_KEY", // pragma: allowlist secret
api: "openai-responses",
models: [{ id: "agent-model", name: "Agent model", input: ["text"] }],
...overrides,
}; };
}
async function runCustomProviderMergeTest(params: {
seedProvider: MergeSeedProvider;
existingProviderKey?: string; existingProviderKey?: string;
configProviderKey?: string; configProviderKey?: string;
}) { }) {
@ -86,6 +104,56 @@ async function runCustomProviderMergeTest(params: {
}>(); }>();
} }
async function expectCustomProviderMergeResult(params: {
seedProvider?: MergeSeedProvider;
existingProviderKey?: string;
configProviderKey?: string;
expectedApiKey: string;
expectedBaseUrl: string;
}) {
await withTempHome(async () => {
const parsed = await runCustomProviderMergeTest({
seedProvider: params.seedProvider ?? createAgentSeedProvider(),
existingProviderKey: params.existingProviderKey,
configProviderKey: params.configProviderKey,
});
expect(parsed.providers.custom?.apiKey).toBe(params.expectedApiKey);
expect(parsed.providers.custom?.baseUrl).toBe(params.expectedBaseUrl);
});
}
async function expectCustomProviderApiKeyRewrite(params: {
existingApiKey: string;
configuredApiKey: string | MergeConfigApiKeyRef;
expectedApiKey: string;
}) {
await withTempHome(async () => {
await writeAgentModelsJson({
providers: {
custom: createAgentSeedProvider({ apiKey: params.existingApiKey }),
},
});
await ensureOpenClawModelsJson({
models: {
mode: "merge",
providers: {
custom: {
...createMergeConfigProvider(),
apiKey: params.configuredApiKey,
},
},
},
});
const parsed = await readGeneratedModelsJson<{
providers: Record<string, { apiKey?: string; baseUrl?: string }>;
}>();
expect(parsed.providers.custom?.apiKey).toBe(params.expectedApiKey);
expect(parsed.providers.custom?.baseUrl).toBe("https://config.example/v1");
});
}
function createMoonshotConfig(overrides: { function createMoonshotConfig(overrides: {
contextWindow: number; contextWindow: number;
maxTokens: number; maxTokens: number;
@ -301,49 +369,26 @@ describe("models-config", () => {
}); });
it("preserves non-empty agent apiKey but lets explicit config baseUrl win in merge mode", async () => { it("preserves non-empty agent apiKey but lets explicit config baseUrl win in merge mode", async () => {
await withTempHome(async () => { await expectCustomProviderMergeResult({
const parsed = await runCustomProviderMergeTest({ expectedApiKey: "AGENT_KEY",
seedProvider: { expectedBaseUrl: "https://config.example/v1",
baseUrl: "https://agent.example/v1",
apiKey: "AGENT_KEY", // pragma: allowlist secret
api: "openai-responses",
models: [{ id: "agent-model", name: "Agent model", input: ["text"] }],
},
});
expect(parsed.providers.custom?.apiKey).toBe("AGENT_KEY");
expect(parsed.providers.custom?.baseUrl).toBe("https://config.example/v1");
}); });
}); });
it("lets explicit config baseUrl win in merge mode when the config provider key is normalized", async () => { it("lets explicit config baseUrl win in merge mode when the config provider key is normalized", async () => {
await withTempHome(async () => { await expectCustomProviderMergeResult({
const parsed = await runCustomProviderMergeTest({ existingProviderKey: "custom",
seedProvider: { configProviderKey: " custom ",
baseUrl: "https://agent.example/v1", expectedApiKey: "AGENT_KEY",
apiKey: "AGENT_KEY", // pragma: allowlist secret expectedBaseUrl: "https://config.example/v1",
api: "openai-responses",
models: [{ id: "agent-model", name: "Agent model", input: ["text"] }],
},
existingProviderKey: "custom",
configProviderKey: " custom ",
});
expect(parsed.providers.custom?.apiKey).toBe("AGENT_KEY");
expect(parsed.providers.custom?.baseUrl).toBe("https://config.example/v1");
}); });
}); });
it("replaces stale merged baseUrl when the provider api changes", async () => { it("replaces stale merged baseUrl when the provider api changes", async () => {
await withTempHome(async () => { await expectCustomProviderMergeResult({
const parsed = await runCustomProviderMergeTest({ seedProvider: createAgentSeedProvider({ api: "openai-completions" }),
seedProvider: { expectedApiKey: "AGENT_KEY",
baseUrl: "https://agent.example/v1", expectedBaseUrl: "https://config.example/v1",
apiKey: "AGENT_KEY", // pragma: allowlist secret
api: "openai-completions",
models: [{ id: "agent-model", name: "Agent model", input: ["text"] }],
},
});
expect(parsed.providers.custom?.apiKey).toBe("AGENT_KEY");
expect(parsed.providers.custom?.baseUrl).toBe("https://config.example/v1");
}); });
}); });
@ -370,34 +415,14 @@ describe("models-config", () => {
}); });
it("replaces stale merged apiKey when provider is SecretRef-managed in current config", async () => { it("replaces stale merged apiKey when provider is SecretRef-managed in current config", async () => {
await withTempHome(async () => { await expectCustomProviderApiKeyRewrite({
await writeAgentModelsJson({ existingApiKey: "STALE_AGENT_KEY", // pragma: allowlist secret
providers: { configuredApiKey: {
custom: { source: "env",
baseUrl: "https://agent.example/v1", provider: "default",
apiKey: "STALE_AGENT_KEY", // pragma: allowlist secret id: "CUSTOM_PROVIDER_API_KEY", // pragma: allowlist secret
api: "openai-responses", },
models: [{ id: "agent-model", name: "Agent model", input: ["text"] }], expectedApiKey: "CUSTOM_PROVIDER_API_KEY", // pragma: allowlist secret
},
},
});
await ensureOpenClawModelsJson({
models: {
mode: "merge",
providers: {
custom: {
...createMergeConfigProvider(),
apiKey: { source: "env", provider: "default", id: "CUSTOM_PROVIDER_API_KEY" }, // pragma: allowlist secret
},
},
},
});
const parsed = await readGeneratedModelsJson<{
providers: Record<string, { apiKey?: string; baseUrl?: string }>;
}>();
expect(parsed.providers.custom?.apiKey).toBe("CUSTOM_PROVIDER_API_KEY"); // pragma: allowlist secret
expect(parsed.providers.custom?.baseUrl).toBe("https://config.example/v1");
}); });
}); });
@ -449,34 +474,10 @@ describe("models-config", () => {
}); });
it("replaces stale non-env marker when provider transitions back to plaintext config", async () => { it("replaces stale non-env marker when provider transitions back to plaintext config", async () => {
await withTempHome(async () => { await expectCustomProviderApiKeyRewrite({
await writeAgentModelsJson({ existingApiKey: NON_ENV_SECRETREF_MARKER,
providers: { configuredApiKey: "ALLCAPS_SAMPLE", // pragma: allowlist secret
custom: { expectedApiKey: "ALLCAPS_SAMPLE", // pragma: allowlist secret
baseUrl: "https://agent.example/v1",
apiKey: NON_ENV_SECRETREF_MARKER,
api: "openai-responses",
models: [{ id: "agent-model", name: "Agent model", input: ["text"] }],
},
},
});
await ensureOpenClawModelsJson({
models: {
mode: "merge",
providers: {
custom: {
...createMergeConfigProvider(),
apiKey: "ALLCAPS_SAMPLE", // pragma: allowlist secret
},
},
},
});
const parsed = await readGeneratedModelsJson<{
providers: Record<string, { apiKey?: string }>;
}>();
expect(parsed.providers.custom?.apiKey).toBe("ALLCAPS_SAMPLE");
}); });
}); });