mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 17:40:44 +00: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", () => {
|
it("marks legacy untagged /models add OpenAI Codex metadata rows for doctor repair", () => {
|
||||||
const res = normalizeCompatibilityConfigValues({
|
const res = normalizeCompatibilityConfigValues({
|
||||||
models: {
|
models: {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
normalizeLegacyCrossContextMessageConfig,
|
normalizeLegacyCrossContextMessageConfig,
|
||||||
normalizeLegacyMediaProviderOptions,
|
normalizeLegacyMediaProviderOptions,
|
||||||
normalizeLegacyMistralModelMaxTokens,
|
normalizeLegacyMistralModelMaxTokens,
|
||||||
|
normalizeLegacyOpenAIModelProviderApi,
|
||||||
normalizeLegacyRuntimeModelRefs,
|
normalizeLegacyRuntimeModelRefs,
|
||||||
normalizeLegacyNanoBananaSkill,
|
normalizeLegacyNanoBananaSkill,
|
||||||
normalizeLegacyTalkConfig,
|
normalizeLegacyTalkConfig,
|
||||||
@@ -37,6 +38,7 @@ export function normalizeBaseCompatibilityConfigValues(
|
|||||||
|
|
||||||
next = normalizeLegacyNanoBananaSkill(next, changes);
|
next = normalizeLegacyNanoBananaSkill(next, changes);
|
||||||
next = normalizeLegacyTalkConfig(next, changes);
|
next = normalizeLegacyTalkConfig(next, changes);
|
||||||
|
next = normalizeLegacyOpenAIModelProviderApi(next, changes);
|
||||||
next = normalizeLegacyRuntimeModelRefs(next, changes);
|
next = normalizeLegacyRuntimeModelRefs(next, changes);
|
||||||
next = normalizeLegacyCrossContextMessageConfig(next, changes);
|
next = normalizeLegacyCrossContextMessageConfig(next, changes);
|
||||||
next = normalizeLegacyMediaProviderOptions(next, changes);
|
next = normalizeLegacyMediaProviderOptions(next, changes);
|
||||||
|
|||||||
@@ -390,9 +390,10 @@ export function normalizeLegacyOpenAICodexModelsAddMetadata(
|
|||||||
return cfg;
|
return cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const rawProviders: Record<string, unknown> = rawModels.providers;
|
||||||
let providersChanged = false;
|
let providersChanged = false;
|
||||||
const nextProviders = { ...rawModels.providers };
|
const nextProviders: Record<string, unknown> = { ...rawProviders };
|
||||||
for (const [providerId, rawProvider] of Object.entries(rawModels.providers)) {
|
for (const [providerId, rawProvider] of Object.entries(rawProviders)) {
|
||||||
if (normalizeProviderId(providerId) !== "openai-codex" || !isRecord(rawProvider)) {
|
if (normalizeProviderId(providerId) !== "openai-codex" || !isRecord(rawProvider)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -413,7 +414,7 @@ export function normalizeLegacyOpenAICodexModelsAddMetadata(
|
|||||||
) {
|
) {
|
||||||
providerChanged = true;
|
providerChanged = true;
|
||||||
const safeProviderId = sanitizeForLog(providerId);
|
const safeProviderId = sanitizeForLog(providerId);
|
||||||
const safeModelId = sanitizeForLog(model.id);
|
const safeModelId = sanitizeForLog(normalizeOptionalString(model.id) ?? "unknown");
|
||||||
changes.push(
|
changes.push(
|
||||||
`Marked models.providers.${safeProviderId}.models.${safeModelId} as /models add metadata so official OpenAI Codex metadata can override it.`,
|
`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(
|
export function normalizeLegacyNanoBananaSkill(
|
||||||
cfg: OpenClawConfig,
|
cfg: OpenClawConfig,
|
||||||
changes: string[],
|
changes: string[],
|
||||||
|
|||||||
Reference in New Issue
Block a user