mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
refactor(agents): extract provider model normalization
This commit is contained in:
@@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
- [x] Extract `models list` row/supplement helpers.
|
- [x] Extract `models list` row/supplement helpers.
|
||||||
- [x] Split `models list` forward-compat tests by concern.
|
- [x] Split `models list` forward-compat tests by concern.
|
||||||
- [ ] Extract provider transport normalization from `pi-embedded-runner/model.ts`.
|
- [x] Extract provider transport normalization from `pi-embedded-runner/model.ts`.
|
||||||
- [ ] Split `ensureOpenClawModelsJson()` into planning + IO layers.
|
- [ ] Split `ensureOpenClawModelsJson()` into planning + IO layers.
|
||||||
- [ ] Split provider discovery helpers out of `models-config.providers.ts`.
|
- [ ] Split provider discovery helpers out of `models-config.providers.ts`.
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import type { Api, Model } from "@mariozechner/pi-ai";
|
||||||
|
import { normalizeModelCompat } from "../model-compat.js";
|
||||||
|
import { normalizeProviderId } from "../model-selection.js";
|
||||||
|
|
||||||
|
const OPENAI_CODEX_BASE_URL = "https://chatgpt.com/backend-api";
|
||||||
|
|
||||||
|
function isOpenAIApiBaseUrl(baseUrl?: string): boolean {
|
||||||
|
const trimmed = baseUrl?.trim();
|
||||||
|
if (!trimmed) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return /^https?:\/\/api\.openai\.com(?:\/v1)?\/?$/i.test(trimmed);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isOpenAICodexBaseUrl(baseUrl?: string): boolean {
|
||||||
|
const trimmed = baseUrl?.trim();
|
||||||
|
if (!trimmed) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return /^https?:\/\/chatgpt\.com\/backend-api\/?$/i.test(trimmed);
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeOpenAICodexTransport(params: {
|
||||||
|
provider: string;
|
||||||
|
model: Model<Api>;
|
||||||
|
}): Model<Api> {
|
||||||
|
if (normalizeProviderId(params.provider) !== "openai-codex") {
|
||||||
|
return params.model;
|
||||||
|
}
|
||||||
|
|
||||||
|
const useCodexTransport =
|
||||||
|
!params.model.baseUrl ||
|
||||||
|
isOpenAIApiBaseUrl(params.model.baseUrl) ||
|
||||||
|
isOpenAICodexBaseUrl(params.model.baseUrl);
|
||||||
|
|
||||||
|
const nextApi =
|
||||||
|
useCodexTransport && params.model.api === "openai-responses"
|
||||||
|
? ("openai-codex-responses" as const)
|
||||||
|
: params.model.api;
|
||||||
|
const nextBaseUrl =
|
||||||
|
nextApi === "openai-codex-responses" &&
|
||||||
|
(!params.model.baseUrl || isOpenAIApiBaseUrl(params.model.baseUrl))
|
||||||
|
? OPENAI_CODEX_BASE_URL
|
||||||
|
: params.model.baseUrl;
|
||||||
|
|
||||||
|
if (nextApi === params.model.api && nextBaseUrl === params.model.baseUrl) {
|
||||||
|
return params.model;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...params.model,
|
||||||
|
api: nextApi,
|
||||||
|
baseUrl: nextBaseUrl,
|
||||||
|
} as Model<Api>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalizeResolvedProviderModel(params: {
|
||||||
|
provider: string;
|
||||||
|
model: Model<Api>;
|
||||||
|
}): Model<Api> {
|
||||||
|
return normalizeModelCompat(normalizeOpenAICodexTransport(params));
|
||||||
|
}
|
||||||
@@ -6,10 +6,10 @@ import { resolveOpenClawAgentDir } from "../agent-paths.js";
|
|||||||
import { DEFAULT_CONTEXT_TOKENS } from "../defaults.js";
|
import { DEFAULT_CONTEXT_TOKENS } from "../defaults.js";
|
||||||
import { buildModelAliasLines } from "../model-alias-lines.js";
|
import { buildModelAliasLines } from "../model-alias-lines.js";
|
||||||
import { isSecretRefHeaderValueMarker } from "../model-auth-markers.js";
|
import { isSecretRefHeaderValueMarker } from "../model-auth-markers.js";
|
||||||
import { normalizeModelCompat } from "../model-compat.js";
|
|
||||||
import { resolveForwardCompatModel } from "../model-forward-compat.js";
|
import { resolveForwardCompatModel } from "../model-forward-compat.js";
|
||||||
import { findNormalizedProviderValue, normalizeProviderId } from "../model-selection.js";
|
import { findNormalizedProviderValue, normalizeProviderId } from "../model-selection.js";
|
||||||
import { discoverAuthStorage, discoverModels } from "../pi-model-discovery.js";
|
import { discoverAuthStorage, discoverModels } from "../pi-model-discovery.js";
|
||||||
|
import { normalizeResolvedProviderModel } from "./model.provider-normalization.js";
|
||||||
|
|
||||||
type InlineModelEntry = ModelDefinitionConfig & {
|
type InlineModelEntry = ModelDefinitionConfig & {
|
||||||
provider: string;
|
provider: string;
|
||||||
@@ -23,8 +23,6 @@ type InlineProviderConfig = {
|
|||||||
headers?: unknown;
|
headers?: unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
const OPENAI_CODEX_BASE_URL = "https://chatgpt.com/backend-api";
|
|
||||||
|
|
||||||
function sanitizeModelHeaders(
|
function sanitizeModelHeaders(
|
||||||
headers: unknown,
|
headers: unknown,
|
||||||
opts?: { stripSecretRefMarkers?: boolean },
|
opts?: { stripSecretRefMarkers?: boolean },
|
||||||
@@ -45,58 +43,8 @@ function sanitizeModelHeaders(
|
|||||||
return Object.keys(next).length > 0 ? next : undefined;
|
return Object.keys(next).length > 0 ? next : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isOpenAIApiBaseUrl(baseUrl?: string): boolean {
|
|
||||||
const trimmed = baseUrl?.trim();
|
|
||||||
if (!trimmed) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return /^https?:\/\/api\.openai\.com(?:\/v1)?\/?$/i.test(trimmed);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isOpenAICodexBaseUrl(baseUrl?: string): boolean {
|
|
||||||
const trimmed = baseUrl?.trim();
|
|
||||||
if (!trimmed) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return /^https?:\/\/chatgpt\.com\/backend-api\/?$/i.test(trimmed);
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeOpenAICodexTransport(params: {
|
|
||||||
provider: string;
|
|
||||||
model: Model<Api>;
|
|
||||||
}): Model<Api> {
|
|
||||||
if (normalizeProviderId(params.provider) !== "openai-codex") {
|
|
||||||
return params.model;
|
|
||||||
}
|
|
||||||
|
|
||||||
const useCodexTransport =
|
|
||||||
!params.model.baseUrl ||
|
|
||||||
isOpenAIApiBaseUrl(params.model.baseUrl) ||
|
|
||||||
isOpenAICodexBaseUrl(params.model.baseUrl);
|
|
||||||
|
|
||||||
const nextApi =
|
|
||||||
useCodexTransport && params.model.api === "openai-responses"
|
|
||||||
? ("openai-codex-responses" as const)
|
|
||||||
: params.model.api;
|
|
||||||
const nextBaseUrl =
|
|
||||||
nextApi === "openai-codex-responses" &&
|
|
||||||
(!params.model.baseUrl || isOpenAIApiBaseUrl(params.model.baseUrl))
|
|
||||||
? OPENAI_CODEX_BASE_URL
|
|
||||||
: params.model.baseUrl;
|
|
||||||
|
|
||||||
if (nextApi === params.model.api && nextBaseUrl === params.model.baseUrl) {
|
|
||||||
return params.model;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...params.model,
|
|
||||||
api: nextApi,
|
|
||||||
baseUrl: nextBaseUrl,
|
|
||||||
} as Model<Api>;
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeResolvedModel(params: { provider: string; model: Model<Api> }): Model<Api> {
|
function normalizeResolvedModel(params: { provider: string; model: Model<Api> }): Model<Api> {
|
||||||
return normalizeModelCompat(normalizeOpenAICodexTransport(params));
|
return normalizeResolvedProviderModel(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { buildModelAliasLines };
|
export { buildModelAliasLines };
|
||||||
|
|||||||
Reference in New Issue
Block a user