mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-29 21:17:05 +02:00
fix(doctor): migrate legacy OpenAI provider api
This commit is contained in:
@@ -342,6 +342,40 @@ describe("normalizeCompatibilityConfigValues", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("migrates legacy OpenAI provider api values to OpenAI completions", () => {
|
||||
const res = normalizeCompatibilityConfigValues({
|
||||
models: {
|
||||
providers: {
|
||||
openrouter: {
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
api: "openai",
|
||||
models: [
|
||||
{
|
||||
id: "openai/gpt-4o-mini",
|
||||
name: "OpenRouter GPT-4o Mini",
|
||||
api: "openai",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 128_000,
|
||||
maxTokens: 16_384,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as unknown as OpenClawConfig);
|
||||
|
||||
expect(res.config.models?.providers?.openrouter?.api).toBe("openai-completions");
|
||||
expect(res.config.models?.providers?.openrouter?.models?.[0]?.api).toBe("openai-completions");
|
||||
expect(res.changes).toContain(
|
||||
'Moved models.providers.openrouter.api "openai" → "openai-completions".',
|
||||
);
|
||||
expect(res.changes).toContain(
|
||||
'Moved models.providers.openrouter.models[0].api "openai" → "openai-completions".',
|
||||
);
|
||||
});
|
||||
|
||||
it("marks legacy untagged /models add OpenAI Codex metadata rows for doctor repair", () => {
|
||||
const res = normalizeCompatibilityConfigValues({
|
||||
models: {
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
normalizeLegacyCrossContextMessageConfig,
|
||||
normalizeLegacyMediaProviderOptions,
|
||||
normalizeLegacyMistralModelMaxTokens,
|
||||
normalizeLegacyOpenAIModelProviderApi,
|
||||
normalizeLegacyRuntimeModelRefs,
|
||||
normalizeLegacyNanoBananaSkill,
|
||||
normalizeLegacyTalkConfig,
|
||||
@@ -37,6 +38,7 @@ export function normalizeBaseCompatibilityConfigValues(
|
||||
|
||||
next = normalizeLegacyNanoBananaSkill(next, changes);
|
||||
next = normalizeLegacyTalkConfig(next, changes);
|
||||
next = normalizeLegacyOpenAIModelProviderApi(next, changes);
|
||||
next = normalizeLegacyRuntimeModelRefs(next, changes);
|
||||
next = normalizeLegacyCrossContextMessageConfig(next, changes);
|
||||
next = normalizeLegacyMediaProviderOptions(next, changes);
|
||||
|
||||
@@ -390,9 +390,10 @@ export function normalizeLegacyOpenAICodexModelsAddMetadata(
|
||||
return cfg;
|
||||
}
|
||||
|
||||
const rawProviders: Record<string, unknown> = rawModels.providers;
|
||||
let providersChanged = false;
|
||||
const nextProviders = { ...rawModels.providers };
|
||||
for (const [providerId, rawProvider] of Object.entries(rawModels.providers)) {
|
||||
const nextProviders: Record<string, unknown> = { ...rawProviders };
|
||||
for (const [providerId, rawProvider] of Object.entries(rawProviders)) {
|
||||
if (normalizeProviderId(providerId) !== "openai-codex" || !isRecord(rawProvider)) {
|
||||
continue;
|
||||
}
|
||||
@@ -413,7 +414,7 @@ export function normalizeLegacyOpenAICodexModelsAddMetadata(
|
||||
) {
|
||||
providerChanged = true;
|
||||
const safeProviderId = sanitizeForLog(providerId);
|
||||
const safeModelId = sanitizeForLog(model.id);
|
||||
const safeModelId = sanitizeForLog(normalizeOptionalString(model.id) ?? "unknown");
|
||||
changes.push(
|
||||
`Marked models.providers.${safeProviderId}.models.${safeModelId} as /models add metadata so official OpenAI Codex metadata can override it.`,
|
||||
);
|
||||
@@ -446,6 +447,77 @@ export function normalizeLegacyOpenAICodexModelsAddMetadata(
|
||||
};
|
||||
}
|
||||
|
||||
export function normalizeLegacyOpenAIModelProviderApi(
|
||||
cfg: OpenClawConfig,
|
||||
changes: string[],
|
||||
): OpenClawConfig {
|
||||
const rawModels = cfg.models;
|
||||
if (!isRecord(rawModels) || !isRecord(rawModels.providers)) {
|
||||
return cfg;
|
||||
}
|
||||
|
||||
const rawProviders: Record<string, unknown> = rawModels.providers;
|
||||
let providersChanged = false;
|
||||
const nextProviders: Record<string, unknown> = { ...rawProviders };
|
||||
for (const [providerId, rawProvider] of Object.entries(rawProviders)) {
|
||||
if (!isRecord(rawProvider)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let providerChanged = false;
|
||||
const nextProvider: Record<string, unknown> = { ...rawProvider };
|
||||
if (nextProvider.api === "openai") {
|
||||
nextProvider.api = "openai-completions";
|
||||
providerChanged = true;
|
||||
changes.push(
|
||||
`Moved models.providers.${sanitizeForLog(providerId)}.api "openai" → "openai-completions".`,
|
||||
);
|
||||
}
|
||||
|
||||
const rawProviderModels = rawProvider.models;
|
||||
if (Array.isArray(rawProviderModels)) {
|
||||
let modelsChanged = false;
|
||||
const nextModels: unknown[] = [];
|
||||
rawProviderModels.forEach((model, index) => {
|
||||
if (!isRecord(model) || model.api !== "openai") {
|
||||
nextModels.push(model);
|
||||
return;
|
||||
}
|
||||
modelsChanged = true;
|
||||
changes.push(
|
||||
`Moved models.providers.${sanitizeForLog(providerId)}.models[${index}].api "openai" → "openai-completions".`,
|
||||
);
|
||||
nextModels.push({
|
||||
...model,
|
||||
api: "openai-completions",
|
||||
});
|
||||
});
|
||||
if (modelsChanged) {
|
||||
nextProvider.models = nextModels;
|
||||
providerChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!providerChanged) {
|
||||
continue;
|
||||
}
|
||||
nextProviders[providerId] = nextProvider;
|
||||
providersChanged = true;
|
||||
}
|
||||
|
||||
if (!providersChanged) {
|
||||
return cfg;
|
||||
}
|
||||
|
||||
return {
|
||||
...cfg,
|
||||
models: {
|
||||
...rawModels,
|
||||
providers: nextProviders as NonNullable<OpenClawConfig["models"]>["providers"],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function normalizeLegacyNanoBananaSkill(
|
||||
cfg: OpenClawConfig,
|
||||
changes: string[],
|
||||
|
||||
Reference in New Issue
Block a user