refactor(agents): simplify provider key normalization (#108950)

Co-authored-by: Pick-cat <huang.ting3@xydigit.com>
This commit is contained in:
Peter Steinberger
2026-07-16 04:36:15 -07:00
committed by GitHub
parent 990e8d24b0
commit 7c262eaae7
2 changed files with 27 additions and 12 deletions

View File

@@ -242,6 +242,19 @@ describe("models-config merge helpers", () => {
expect(merged.openai?.baseUrl).toBe("https://canonical.example/v1");
});
it("keeps canonical providers at the canonical key's position", () => {
const merged = mergeProviders({
explicit: {
OpenAI: createConfigProvider({ baseUrl: "https://variant.example/v1" }),
anthropic: createConfigProvider({ baseUrl: "https://anthropic.example/v1" }),
openai: createConfigProvider({ baseUrl: "https://canonical.example/v1" }),
},
});
expect(Object.keys(merged)).toEqual(["anthropic", "openai"]);
expect(merged.openai?.baseUrl).toBe("https://canonical.example/v1");
});
it("keeps the later provider when no collision key uses canonical spelling", () => {
const merged = mergeProviders({
explicit: {

View File

@@ -4,24 +4,26 @@ import { normalizeProviderId } from "@openclaw/model-catalog-core/provider-id";
export function normalizeProviderMapKeys<T>(
providers: Record<string, T> | null | undefined,
): Record<string, T> {
const entries = Object.entries(providers ?? {});
const canonicalKeys = new Set<string>();
for (const [key] of entries) {
const providerKey = normalizeProviderId(key);
if (providerKey && key === providerKey) {
canonicalKeys.add(providerKey);
}
}
const normalized: Record<string, T> = {};
for (const [key, value] of entries) {
const canonicalKeys = new Set<string>();
for (const [key, value] of Object.entries(providers ?? {})) {
const providerKey = normalizeProviderId(key);
if (!providerKey || (canonicalKeys.has(providerKey) && key !== providerKey)) {
if (!providerKey) {
continue;
}
if (key === providerKey) {
canonicalKeys.add(providerKey);
// A prior alias inserted this key at the alias's position. Reinsert it so
// canonical spelling also controls deterministic provider order.
delete normalized[providerKey];
normalized[providerKey] = value;
continue;
}
// Exact canonical spelling wins over aliases regardless of object order.
// Without one, the later variant wins, matching existing trim-collision behavior.
normalized[providerKey] = value;
if (!canonicalKeys.has(providerKey)) {
normalized[providerKey] = value;
}
}
return normalized;
}