From de1e527e14eea74bbf9b19d87eb721ee6741bccf Mon Sep 17 00:00:00 2001 From: Gustavo Madeira Santana Date: Mon, 23 Feb 2026 20:38:18 -0500 Subject: [PATCH] revert: keep model-catalog behavior unchanged --- src/agents/model-catalog.test.ts | 149 ------------------------------- src/agents/model-catalog.ts | 106 +--------------------- 2 files changed, 4 insertions(+), 251 deletions(-) diff --git a/src/agents/model-catalog.test.ts b/src/agents/model-catalog.test.ts index 532d7dbcb30..791947ad8fa 100644 --- a/src/agents/model-catalog.test.ts +++ b/src/agents/model-catalog.test.ts @@ -103,153 +103,4 @@ describe("loadModelCatalog", () => { expect(spark?.name).toBe("gpt-5.3-codex-spark"); expect(spark?.reasoning).toBe(true); }); - - it("includes configured provider models from models.json when registry omits them", async () => { - const cfg = { - models: { - providers: { - kilocode: { - baseUrl: "https://api.kilo.ai/api/gateway/", - api: "openai-completions", - models: [ - { - id: "anthropic/claude-opus-4.6", - name: "Claude Opus 4.6", - reasoning: true, - input: ["text", "image"], - contextWindow: 200000, - maxTokens: 8192, - cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, - }, - { - id: "openai/gpt-5.2", - name: "GPT-5.2", - reasoning: true, - input: ["text"], - contextWindow: 400000, - maxTokens: 8192, - cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, - }, - ], - }, - }, - }, - } satisfies OpenClawConfig; - - __setModelCatalogImportForTest( - async () => - ({ - AuthStorage: class {}, - ModelRegistry: class { - getAll() { - return [{ id: "gpt-4.1", name: "GPT-4.1", provider: "openai" }]; - } - }, - }) as unknown as PiSdkModule, - ); - - const result = await loadModelCatalog({ config: cfg }); - expect(result).toContainEqual( - expect.objectContaining({ - provider: "kilocode", - id: "anthropic/claude-opus-4.6", - }), - ); - expect(result).toContainEqual( - expect.objectContaining({ - provider: "kilocode", - id: "openai/gpt-5.2", - }), - ); - }); - - it("normalizes configured provider aliases in merged catalog entries", async () => { - const cfg = { - models: { - providers: { - "z-ai": { - baseUrl: "https://api.z.ai/api/paas/v4/", - api: "openai-completions", - models: [ - { - id: "glm-5:free", - name: "GLM-5 (Free)", - reasoning: true, - input: ["text"], - contextWindow: 202800, - maxTokens: 131072, - cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, - }, - ], - }, - }, - }, - } satisfies OpenClawConfig; - - __setModelCatalogImportForTest( - async () => - ({ - AuthStorage: class {}, - ModelRegistry: class { - getAll() { - return []; - } - }, - }) as unknown as PiSdkModule, - ); - - const result = await loadModelCatalog({ config: cfg }); - expect(result).toContainEqual( - expect.objectContaining({ - provider: "zai", - id: "glm-5:free", - }), - ); - }); - - it("dedupes discovered and configured entries using normalized provider aliases", async () => { - const cfg = { - models: { - providers: { - "z-ai": { - baseUrl: "https://api.z.ai/api/paas/v4/", - api: "openai-completions", - models: [ - { - id: "glm-5:free", - name: "GLM-5 (Free)", - reasoning: true, - input: ["text"], - contextWindow: 202800, - maxTokens: 131072, - cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, - }, - ], - }, - }, - }, - } satisfies OpenClawConfig; - - __setModelCatalogImportForTest( - async () => - ({ - AuthStorage: class {}, - ModelRegistry: class { - getAll() { - return [ - { - id: "glm-5:free", - name: "GLM-5 (Free)", - provider: "zai", - }, - ]; - } - }, - }) as unknown as PiSdkModule, - ); - - const result = await loadModelCatalog({ config: cfg }); - const matches = result.filter((entry) => entry.provider === "zai" && entry.id === "glm-5:free"); - expect(matches).toHaveLength(1); - }); }); diff --git a/src/agents/model-catalog.ts b/src/agents/model-catalog.ts index c3252d26fe7..beda4dc5848 100644 --- a/src/agents/model-catalog.ts +++ b/src/agents/model-catalog.ts @@ -1,8 +1,6 @@ -import path from "node:path"; import { type OpenClawConfig, loadConfig } from "../config/config.js"; import { createSubsystemLogger } from "../logging/subsystem.js"; import { resolveOpenClawAgentDir } from "./agent-paths.js"; -import { normalizeProviderId } from "./model-selection.js"; import { ensureOpenClawModelsJson } from "./models-config.js"; const log = createSubsystemLogger("model-catalog"); @@ -25,14 +23,6 @@ type DiscoveredModel = { input?: Array<"text" | "image">; }; -type ConfigModelEntry = { - id?: unknown; - name?: unknown; - contextWindow?: unknown; - reasoning?: unknown; - input?: unknown; -}; - type PiSdkModule = typeof import("./pi-model-discovery.js"); let modelCatalogPromise: Promise | null = null; @@ -88,91 +78,6 @@ function createAuthStorage(AuthStorageLike: unknown, path: string) { return new (AuthStorageLike as { new (path: string): unknown })(path); } -function toPositiveNumber(value: unknown): number | undefined { - return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : undefined; -} - -function normalizeInput(modalities: unknown): Array<"text" | "image"> | undefined { - if (!Array.isArray(modalities) || modalities.length === 0) { - return undefined; - } - const hasImage = modalities.some((value) => String(value ?? "").toLowerCase() === "image"); - return hasImage ? ["text", "image"] : ["text"]; -} - -function normalizeCatalogProvider(value: unknown): string { - if (typeof value !== "string") { - return ""; - } - const trimmed = value.trim(); - if (!trimmed) { - return ""; - } - return normalizeProviderId(trimmed); -} - -function modelCatalogMergeKey(entry: Pick): string { - const provider = normalizeCatalogProvider(entry.provider); - const id = String(entry.id ?? "") - .trim() - .toLowerCase(); - return `${provider}/${id}`; -} - -function readConfiguredModelsFromConfig(cfg: OpenClawConfig): ModelCatalogEntry[] { - const providers = cfg.models?.providers; - if (!providers) { - return []; - } - const entries: ModelCatalogEntry[] = []; - for (const [providerIdRaw, providerValue] of Object.entries(providers)) { - const provider = normalizeCatalogProvider(providerIdRaw); - if (!provider || !providerValue) { - continue; - } - const providerModels = (providerValue as { models?: unknown }).models; - if (!Array.isArray(providerModels)) { - continue; - } - for (const modelValue of providerModels) { - if (!modelValue || typeof modelValue !== "object") { - continue; - } - const model = modelValue as ConfigModelEntry; - if (typeof model.id !== "string") { - continue; - } - const id = model.id.trim(); - if (!id) { - continue; - } - const name = typeof model.name === "string" && model.name.trim() ? model.name.trim() : id; - const contextWindow = toPositiveNumber(model.contextWindow); - const reasoning = typeof model.reasoning === "boolean" ? model.reasoning : undefined; - const input = normalizeInput(model.input); - entries.push({ id, name, provider, contextWindow, reasoning, input }); - } - } - return entries; -} - -function mergeMissingCatalogEntries( - discoveredModels: ModelCatalogEntry[], - configuredModels: ModelCatalogEntry[], -): ModelCatalogEntry[] { - const seen = new Set(discoveredModels.map((entry) => modelCatalogMergeKey(entry))); - const merged = [...discoveredModels]; - for (const entry of configuredModels) { - const key = modelCatalogMergeKey(entry); - if (seen.has(key)) { - continue; - } - seen.add(key); - merged.push(entry); - } - return merged; -} - export async function loadModelCatalog(params?: { config?: OpenClawConfig; useCache?: boolean; @@ -206,7 +111,8 @@ export async function loadModelCatalog(params?: { // will keep failing until restart). const piSdk = await importPiSdk(); const agentDir = resolveOpenClawAgentDir(); - const authStorage = createAuthStorage(piSdk.AuthStorage, path.join(agentDir, "auth.json")); + const { join } = await import("node:path"); + const authStorage = createAuthStorage(piSdk.AuthStorage, join(agentDir, "auth.json")); const registry = new (piSdk.ModelRegistry as unknown as { new ( authStorage: unknown, @@ -216,14 +122,14 @@ export async function loadModelCatalog(params?: { | { getAll: () => Array; }; - })(authStorage, path.join(agentDir, "models.json")); + })(authStorage, join(agentDir, "models.json")); const entries = Array.isArray(registry) ? registry : registry.getAll(); for (const entry of entries) { const id = String(entry?.id ?? "").trim(); if (!id) { continue; } - const provider = normalizeCatalogProvider(entry?.provider); + const provider = String(entry?.provider ?? "").trim(); if (!provider) { continue; } @@ -236,10 +142,6 @@ export async function loadModelCatalog(params?: { const input = Array.isArray(entry?.input) ? entry.input : undefined; models.push({ id, name, provider, contextWindow, reasoning, input }); } - const configuredModels = readConfiguredModelsFromConfig(cfg); - const mergedModels = mergeMissingCatalogEntries(models, configuredModels); - models.length = 0; - models.push(...mergedModels); applyOpenAICodexSparkFallback(models); if (models.length === 0) {