mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-07 21:21:24 +00:00
fix(models): antigravity opus 4.6 availability follow-up (#12845)
* fix(models): antigravity opus 4.6 availability follow-up * chore(format): apply updated oxfmt config to models files * fix(models): retain zai glm-5 forward-compat fallback after extraction * chore(format): apply updated oxfmt config * fix(models): fail fast on unknown auth login provider --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
226
src/agents/model-forward-compat.ts
Normal file
226
src/agents/model-forward-compat.ts
Normal file
@@ -0,0 +1,226 @@
|
||||
import type { Api, Model } from "@mariozechner/pi-ai";
|
||||
import type { ModelRegistry } from "./pi-model-discovery.js";
|
||||
import { DEFAULT_CONTEXT_TOKENS } from "./defaults.js";
|
||||
import { normalizeModelCompat } from "./model-compat.js";
|
||||
import { normalizeProviderId } from "./model-selection.js";
|
||||
|
||||
const OPENAI_CODEX_GPT_53_MODEL_ID = "gpt-5.3-codex";
|
||||
const OPENAI_CODEX_TEMPLATE_MODEL_IDS = ["gpt-5.2-codex"] as const;
|
||||
|
||||
const ANTHROPIC_OPUS_46_MODEL_ID = "claude-opus-4-6";
|
||||
const ANTHROPIC_OPUS_46_DOT_MODEL_ID = "claude-opus-4.6";
|
||||
const ANTHROPIC_OPUS_TEMPLATE_MODEL_IDS = ["claude-opus-4-5", "claude-opus-4.5"] as const;
|
||||
|
||||
const ZAI_GLM5_MODEL_ID = "glm-5";
|
||||
const ZAI_GLM5_TEMPLATE_MODEL_IDS = ["glm-4.7"] as const;
|
||||
|
||||
const ANTIGRAVITY_OPUS_46_MODEL_ID = "claude-opus-4-6";
|
||||
const ANTIGRAVITY_OPUS_46_DOT_MODEL_ID = "claude-opus-4.6";
|
||||
const ANTIGRAVITY_OPUS_TEMPLATE_MODEL_IDS = ["claude-opus-4-5", "claude-opus-4.5"] as const;
|
||||
const ANTIGRAVITY_OPUS_46_THINKING_MODEL_ID = "claude-opus-4-6-thinking";
|
||||
const ANTIGRAVITY_OPUS_46_DOT_THINKING_MODEL_ID = "claude-opus-4.6-thinking";
|
||||
const ANTIGRAVITY_OPUS_THINKING_TEMPLATE_MODEL_IDS = [
|
||||
"claude-opus-4-5-thinking",
|
||||
"claude-opus-4.5-thinking",
|
||||
] as const;
|
||||
|
||||
function resolveOpenAICodexGpt53FallbackModel(
|
||||
provider: string,
|
||||
modelId: string,
|
||||
modelRegistry: ModelRegistry,
|
||||
): Model<Api> | undefined {
|
||||
const normalizedProvider = normalizeProviderId(provider);
|
||||
const trimmedModelId = modelId.trim();
|
||||
if (normalizedProvider !== "openai-codex") {
|
||||
return undefined;
|
||||
}
|
||||
if (trimmedModelId.toLowerCase() !== OPENAI_CODEX_GPT_53_MODEL_ID) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
for (const templateId of OPENAI_CODEX_TEMPLATE_MODEL_IDS) {
|
||||
const template = modelRegistry.find(normalizedProvider, templateId) as Model<Api> | null;
|
||||
if (!template) {
|
||||
continue;
|
||||
}
|
||||
return normalizeModelCompat({
|
||||
...template,
|
||||
id: trimmedModelId,
|
||||
name: trimmedModelId,
|
||||
} as Model<Api>);
|
||||
}
|
||||
|
||||
return normalizeModelCompat({
|
||||
id: trimmedModelId,
|
||||
name: trimmedModelId,
|
||||
api: "openai-codex-responses",
|
||||
provider: normalizedProvider,
|
||||
baseUrl: "https://chatgpt.com/backend-api",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: DEFAULT_CONTEXT_TOKENS,
|
||||
maxTokens: DEFAULT_CONTEXT_TOKENS,
|
||||
} as Model<Api>);
|
||||
}
|
||||
|
||||
function resolveAnthropicOpus46ForwardCompatModel(
|
||||
provider: string,
|
||||
modelId: string,
|
||||
modelRegistry: ModelRegistry,
|
||||
): Model<Api> | undefined {
|
||||
const normalizedProvider = normalizeProviderId(provider);
|
||||
if (normalizedProvider !== "anthropic") {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const trimmedModelId = modelId.trim();
|
||||
const lower = trimmedModelId.toLowerCase();
|
||||
const isOpus46 =
|
||||
lower === ANTHROPIC_OPUS_46_MODEL_ID ||
|
||||
lower === ANTHROPIC_OPUS_46_DOT_MODEL_ID ||
|
||||
lower.startsWith(`${ANTHROPIC_OPUS_46_MODEL_ID}-`) ||
|
||||
lower.startsWith(`${ANTHROPIC_OPUS_46_DOT_MODEL_ID}-`);
|
||||
if (!isOpus46) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const templateIds: string[] = [];
|
||||
if (lower.startsWith(ANTHROPIC_OPUS_46_MODEL_ID)) {
|
||||
templateIds.push(lower.replace(ANTHROPIC_OPUS_46_MODEL_ID, "claude-opus-4-5"));
|
||||
}
|
||||
if (lower.startsWith(ANTHROPIC_OPUS_46_DOT_MODEL_ID)) {
|
||||
templateIds.push(lower.replace(ANTHROPIC_OPUS_46_DOT_MODEL_ID, "claude-opus-4.5"));
|
||||
}
|
||||
templateIds.push(...ANTHROPIC_OPUS_TEMPLATE_MODEL_IDS);
|
||||
|
||||
for (const templateId of [...new Set(templateIds)].filter(Boolean)) {
|
||||
const template = modelRegistry.find(normalizedProvider, templateId) as Model<Api> | null;
|
||||
if (!template) {
|
||||
continue;
|
||||
}
|
||||
return normalizeModelCompat({
|
||||
...template,
|
||||
id: trimmedModelId,
|
||||
name: trimmedModelId,
|
||||
} as Model<Api>);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Z.ai's GLM-5 may not be present in pi-ai's built-in model catalog yet.
|
||||
// When a user configures zai/glm-5 without a models.json entry, clone glm-4.7 as a forward-compat fallback.
|
||||
function resolveZaiGlm5ForwardCompatModel(
|
||||
provider: string,
|
||||
modelId: string,
|
||||
modelRegistry: ModelRegistry,
|
||||
): Model<Api> | undefined {
|
||||
if (normalizeProviderId(provider) !== "zai") {
|
||||
return undefined;
|
||||
}
|
||||
const trimmed = modelId.trim();
|
||||
const lower = trimmed.toLowerCase();
|
||||
if (lower !== ZAI_GLM5_MODEL_ID && !lower.startsWith(`${ZAI_GLM5_MODEL_ID}-`)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
for (const templateId of ZAI_GLM5_TEMPLATE_MODEL_IDS) {
|
||||
const template = modelRegistry.find("zai", templateId) as Model<Api> | null;
|
||||
if (!template) {
|
||||
continue;
|
||||
}
|
||||
return normalizeModelCompat({
|
||||
...template,
|
||||
id: trimmed,
|
||||
name: trimmed,
|
||||
reasoning: true,
|
||||
} as Model<Api>);
|
||||
}
|
||||
|
||||
return normalizeModelCompat({
|
||||
id: trimmed,
|
||||
name: trimmed,
|
||||
api: "openai-completions",
|
||||
provider: "zai",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: DEFAULT_CONTEXT_TOKENS,
|
||||
maxTokens: DEFAULT_CONTEXT_TOKENS,
|
||||
} as Model<Api>);
|
||||
}
|
||||
|
||||
function resolveAntigravityOpus46ForwardCompatModel(
|
||||
provider: string,
|
||||
modelId: string,
|
||||
modelRegistry: ModelRegistry,
|
||||
): Model<Api> | undefined {
|
||||
const normalizedProvider = normalizeProviderId(provider);
|
||||
if (normalizedProvider !== "google-antigravity") {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const trimmedModelId = modelId.trim();
|
||||
const lower = trimmedModelId.toLowerCase();
|
||||
const isOpus46 =
|
||||
lower === ANTIGRAVITY_OPUS_46_MODEL_ID ||
|
||||
lower === ANTIGRAVITY_OPUS_46_DOT_MODEL_ID ||
|
||||
lower.startsWith(`${ANTIGRAVITY_OPUS_46_MODEL_ID}-`) ||
|
||||
lower.startsWith(`${ANTIGRAVITY_OPUS_46_DOT_MODEL_ID}-`);
|
||||
const isOpus46Thinking =
|
||||
lower === ANTIGRAVITY_OPUS_46_THINKING_MODEL_ID ||
|
||||
lower === ANTIGRAVITY_OPUS_46_DOT_THINKING_MODEL_ID ||
|
||||
lower.startsWith(`${ANTIGRAVITY_OPUS_46_THINKING_MODEL_ID}-`) ||
|
||||
lower.startsWith(`${ANTIGRAVITY_OPUS_46_DOT_THINKING_MODEL_ID}-`);
|
||||
if (!isOpus46 && !isOpus46Thinking) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const templateIds: string[] = [];
|
||||
if (lower.startsWith(ANTIGRAVITY_OPUS_46_MODEL_ID)) {
|
||||
templateIds.push(lower.replace(ANTIGRAVITY_OPUS_46_MODEL_ID, "claude-opus-4-5"));
|
||||
}
|
||||
if (lower.startsWith(ANTIGRAVITY_OPUS_46_DOT_MODEL_ID)) {
|
||||
templateIds.push(lower.replace(ANTIGRAVITY_OPUS_46_DOT_MODEL_ID, "claude-opus-4.5"));
|
||||
}
|
||||
if (lower.startsWith(ANTIGRAVITY_OPUS_46_THINKING_MODEL_ID)) {
|
||||
templateIds.push(
|
||||
lower.replace(ANTIGRAVITY_OPUS_46_THINKING_MODEL_ID, "claude-opus-4-5-thinking"),
|
||||
);
|
||||
}
|
||||
if (lower.startsWith(ANTIGRAVITY_OPUS_46_DOT_THINKING_MODEL_ID)) {
|
||||
templateIds.push(
|
||||
lower.replace(ANTIGRAVITY_OPUS_46_DOT_THINKING_MODEL_ID, "claude-opus-4.5-thinking"),
|
||||
);
|
||||
}
|
||||
templateIds.push(...ANTIGRAVITY_OPUS_TEMPLATE_MODEL_IDS);
|
||||
templateIds.push(...ANTIGRAVITY_OPUS_THINKING_TEMPLATE_MODEL_IDS);
|
||||
|
||||
for (const templateId of [...new Set(templateIds)].filter(Boolean)) {
|
||||
const template = modelRegistry.find(normalizedProvider, templateId) as Model<Api> | null;
|
||||
if (!template) {
|
||||
continue;
|
||||
}
|
||||
return normalizeModelCompat({
|
||||
...template,
|
||||
id: trimmedModelId,
|
||||
name: trimmedModelId,
|
||||
} as Model<Api>);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function resolveForwardCompatModel(
|
||||
provider: string,
|
||||
modelId: string,
|
||||
modelRegistry: ModelRegistry,
|
||||
): Model<Api> | undefined {
|
||||
return (
|
||||
resolveOpenAICodexGpt53FallbackModel(provider, modelId, modelRegistry) ??
|
||||
resolveAnthropicOpus46ForwardCompatModel(provider, modelId, modelRegistry) ??
|
||||
resolveZaiGlm5ForwardCompatModel(provider, modelId, modelRegistry) ??
|
||||
resolveAntigravityOpus46ForwardCompatModel(provider, modelId, modelRegistry)
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user