






















@@ -3,6 +3,8 @@ import {
33normalizeAgentModelMapForConfig,
44normalizeAgentModelRefForConfig,
55} from "../config/model-input.js";
6+import { normalizeProviderConfigForConfigDefaults } from "../config/provider-policy.js";
7+import type { ModelProviderConfig } from "../config/types.models.js";
68import type { OpenClawConfig } from "../config/types.openclaw.js";
79import {
810normalizeLowercaseStringOrEmpty,
@@ -119,10 +121,94 @@ function normalizeAgentModelMapForWrite(value: unknown): unknown {
119121return normalizeAgentModelMapForConfig(value);
120122}
121123124+const GOOGLE_CONFIG_MODEL_PROVIDERS = new Set(["google", "google-gemini-cli", "google-vertex"]);
125+126+function normalizeProviderCatalogModelIdForWrite(provider: string, modelId: string): string {
127+const trimmed = modelId.trim();
128+if (!trimmed) {
129+return trimmed;
130+}
131+132+const slash = trimmed.indexOf("/");
133+if (slash > 0 && slash < trimmed.length - 1) {
134+return normalizeAgentModelRefForConfig(trimmed);
135+}
136+137+const providerId = normalizeProviderId(provider);
138+if (!GOOGLE_CONFIG_MODEL_PROVIDERS.has(providerId)) {
139+return trimmed;
140+}
141+142+const normalizedQualified = normalizeAgentModelRefForConfig(`${providerId}/${trimmed}`);
143+const prefix = `${providerId}/`;
144+return normalizedQualified.startsWith(prefix)
145+ ? normalizedQualified.slice(prefix.length)
146+ : normalizedQualified;
147+}
148+149+function normalizeProviderCatalogModelIdsForWrite(
150+provider: string,
151+providerConfig: ModelProviderConfig,
152+): ModelProviderConfig {
153+const models = providerConfig.models;
154+if (!Array.isArray(models) || models.length === 0) {
155+return providerConfig;
156+}
157+158+let mutated = false;
159+const nextModels = models.map((model) => {
160+const nextId = normalizeProviderCatalogModelIdForWrite(provider, model.id);
161+if (nextId === model.id) {
162+return model;
163+}
164+mutated = true;
165+return Object.assign({}, model, { id: nextId });
166+});
167+168+return mutated ? { ...providerConfig, models: nextModels } : providerConfig;
169+}
170+171+function normalizeModelProviderConfigsForWrite(cfg: OpenClawConfig): OpenClawConfig {
172+const providers = cfg.models?.providers;
173+if (!providers) {
174+return cfg;
175+}
176+177+let mutated = false;
178+const nextProviders = { ...providers };
179+for (const [provider, providerConfig] of Object.entries(providers)) {
180+const normalizedProviderConfig = normalizeProviderCatalogModelIdsForWrite(
181+provider,
182+normalizeProviderConfigForConfigDefaults({
183+ provider,
184+ providerConfig,
185+}),
186+);
187+if (normalizedProviderConfig === providerConfig) {
188+continue;
189+}
190+nextProviders[provider] = normalizedProviderConfig;
191+mutated = true;
192+}
193+194+if (!mutated) {
195+return cfg;
196+}
197+198+return {
199+ ...cfg,
200+models: {
201+ ...cfg.models,
202+providers: nextProviders,
203+},
204+};
205+}
206+122207function normalizeConfigModelRefsForWrite(cfg: OpenClawConfig): OpenClawConfig {
123-const defaults = cfg.agents?.defaults;
208+const providerNormalized = normalizeModelProviderConfigsForWrite(cfg);
209+const defaults = providerNormalized.agents?.defaults;
124210if (!defaults) {
125-return cfg;
211+return providerNormalized;
126212}
127213128214const nextDefaults: NonNullable<NonNullable<OpenClawConfig["agents"]>["defaults"]> = {
@@ -136,9 +222,9 @@ function normalizeConfigModelRefsForWrite(cfg: OpenClawConfig): OpenClawConfig {
136222}
137223138224return {
139- ...cfg,
225+ ...providerNormalized,
140226agents: {
141- ...cfg.agents,
227+ ...providerNormalized.agents,
142228defaults: nextDefaults,
143229},
144230};
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。