1 line
1.5 MiB
Plaintext
1 line
1.5 MiB
Plaintext
{"repo": "bharat2808/codex-universal-proxy", "files": {"test/model-discovery.test.js": {"3b65cc0144db5b7508dd93aadc3f8fe063d73171": {"t": 1785746016.7677941, "n": 65732, "h": "4b15a52f2ea958d3", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\nconst { assertPrivateDirectoryMode, assertPrivateFileMode } = require('./helpers/file-mode');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeReasoningLevels,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst {\n cacheIdentity,\n withProviderCache,\n writeCache,\n} = require('../src/model-discovery/file-cache');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst anthropic = require('../src/model-discovery/providers/anthropic');\nconst openai = require('../src/model-discovery/providers/openai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('reasoning normalization preserves every effort accepted by the Codex model cache', () => {\n assert.deepEqual(\n normalizeReasoningLevels(['ultra', 'max', 'xhigh', 'high', 'medium', 'low']),\n ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'],\n );\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('Vertex AI OpenAI endpoints resolve as Google without probing', async () => {\n let fetchCalls = 0;\n const result = await resolveProvider({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n fetchImpl: async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n },\n });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'canonical-url');\n assert.equal(fetchCalls, 0);\n});\n\ntest('Google provider aliases resolve explicitly without probing', async () => {\n let fetches = 0;\n const fetchImpl = async () => {\n fetches += 1;\n throw new Error('must not fetch');\n };\n\n for (const provider of ['aistudio', 'gemini', 'vertexai', 'vertex-ai']) {\n const result = await resolveProvider({ provider, fetchImpl });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetches, 0);\n});\n\ntest('Vertex Google discovery classifies only explicitly supplied Gemini models', async () => {\n const result = await google.discover({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n suppliedModels: ['google/gemini-2.5-flash', 'google/gemini-3.1-flash-image'],\n fetchImpl: async () => {\n throw new Error('Vertex discovery must not call the Developer API catalog');\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'google/gemini-2.5-flash',\n 'google/gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.complete, false);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching strips provider authentication headers on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({\n url: String(url),\n apiKey: options.headers['x-api-key'],\n version: options.headers['anthropic-version'],\n });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"data\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://api.anthropic.com/v1/models',\n provider: 'anthropic',\n authHeaders: {\n 'x-api-key': 'anthropic-secret',\n 'anthropic-version': '2023-06-01',\n },\n fetchImpl,\n });\n\n assert.deepEqual(result, { data: [] });\n assert.deepEqual(calls, [\n {\n url: 'https://api.anthropic.com/v1/models',\n apiKey: 'anthropic-secret',\n version: '2023-06-01',\n },\n {\n url: 'https://cdn.example/catalog.json',\n apiKey: undefined,\n version: undefined,\n },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return { models: [model], origin: 'live', complete: true };\n });\n assert.equal(first.state, 'refreshed');\n assert.equal(first.origin, 'live');\n assert.equal(first.complete, true);\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(fresh.origin, 'live');\n assert.equal(fresh.complete, true);\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.state, 'stale');\n assert.equal(stale.origin, 'live');\n assert.equal(stale.complete, true);\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assertPrivateDirectoryMode(path.join(cacheDir, 'nvidia'));\n assertPrivateFileMode(path.join(cacheDir, 'nvidia', files[0]));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, ['https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json']);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.slice(0, 2).map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n reasoning: {\n supported_efforts: ['xhigh', 'high', 'medium', 'low', 'none'],\n default_effort: 'medium',\n default_enabled: false,\n supports_max_tokens: true,\n mandatory: false,\n },\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, ['none', 'low', 'medium', 'high', 'xhigh']);\n assert.equal(rich.defaultReasoningLevel, 'medium');\n assert.equal(rich.reasoningDefaultEnabled, false);\n assert.equal(rich.reasoningSupportsMaxTokens, true);\n assert.equal(rich.reasoningMandatory, false);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n defaultReasoningLevel: 'provider-catalog',\n reasoningDefaultEnabled: 'provider-catalog',\n reasoningSupportsMaxTokens: 'provider-catalog',\n reasoningMandatory: 'provider-catalog',\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its complete owned snapshot', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.models.length, 345);\n assert.ok(result.models.some((model) => model.id === 'openrouter/auto'));\n assert.ok(result.models.some((model) => model.id === 'moonshotai/kimi-k2.6'));\n assert.equal(result.fallback.state, 'bundled');\n});\n\ntest('OpenRouter reasoning metadata distinguishes all-efforts from no exposed effort selector', () => {\n const allEfforts = openrouter.parseRow({\n id: 'vendor/all-efforts',\n architecture: { modality: 'text->text' },\n reasoning: {\n supported_efforts: null,\n default_effort: 'medium',\n default_enabled: true,\n mandatory: false,\n },\n });\n assert.deepEqual(allEfforts.reasoningLevels, [\n 'none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max',\n ]);\n assert.equal(allEfforts.defaultReasoningLevel, 'medium');\n\n const noSelector = openrouter.parseRow({\n id: 'vendor/no-selector',\n architecture: { modality: 'text->text' },\n reasoning: {\n default_enabled: true,\n mandatory: true,\n },\n });\n assert.equal(noSelector.reasoning, true);\n assert.equal(noSelector.reasoningLevels, null);\n assert.equal(noSelector.defaultReasoningLevel, null);\n assert.equal(noSelector.reasoningDefaultEnabled, true);\n assert.equal(noSelector.reasoningMandatory, true);\n});\n\ntest('Anthropic discovery enriches exact models from official compatibility documentation', () => {\n const model = anthropic.parseRow({\n id: 'claude-sonnet-5',\n type: 'model',\n display_name: 'Claude Sonnet 5',\n created_at: '2026-07-01T00:00:00Z',\n max_input_tokens: 1000000,\n max_tokens: 128000,\n capabilities: {\n image_input: { supported: true },\n thinking: {\n supported: true,\n types: {\n adaptive: { supported: true },\n enabled: { supported: true },\n },\n },\n effort: {\n supported: true,\n low: { supported: true },\n medium: { supported: true },\n high: { supported: true },\n xhigh: { supported: false },\n max: { supported: true },\n },\n future_capability: { supported: true },\n },\n });\n\n assert.deepEqual(model, {\n id: 'claude-sonnet-5',\n displayName: 'Claude Sonnet 5',\n contextWindow: 1000000,\n maxOutputTokens: 128000,\n inputModalities: ['text', 'image'],\n outputModalities: ['text'],\n reasoning: true,\n reasoningLevels: ['low', 'medium', 'high', 'max'],\n defaultReasoningLevel: 'high',\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: true,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n defaultReasoningLevel: 'provider-catalog',\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: 'provider-catalog',\n },\n providerMetadata: {\n createdAt: '2026-07-01T00:00:00Z',\n type: 'model',\n },\n source: 'anthropic-catalog',\n });\n});\n\ntest('Anthropic documentation enrichment does not guess capabilities for unknown future ids', () => {\n const model = anthropic.parseRow({\n id: 'claude-future-example',\n type: 'model',\n display_name: 'Claude Future Example',\n max_input_tokens: 1000000,\n max_tokens: 128000,\n capabilities: {},\n });\n\n assert.equal(model.inputModalities, null);\n assert.equal(model.outputModalities, null);\n assert.equal(model.reasoningLevels, null);\n assert.equal(model.defaultReasoningLevel, null);\n assert.equal(model.toolCalling, null);\n});\n\ntest('Anthropic discovery authenticates and follows model pagination in provider order', async () => {\n const calls = [];\n const pages = [\n {\n data: [\n { id: 'claude-first', type: 'model', display_name: 'Claude First' },\n { id: 'claude-shared', type: 'model', display_name: 'Claude Shared' },\n ],\n first_id: 'claude-first',\n last_id: 'claude-shared',\n has_more: true,\n },\n {\n data: [\n { id: 'claude-shared', type: 'model', display_name: 'Duplicate' },\n { id: 'claude-last', type: 'model', display_name: 'Claude Last' },\n ],\n first_id: 'claude-shared',\n last_id: 'claude-last',\n has_more: false,\n },\n ];\n const result = await anthropic.discover({\n apiKey: 'anthropic-secret',\n fetchImpl: async (url, options) => {\n calls.push({\n url: String(url),\n apiKey: options.headers['x-api-key'],\n version: options.headers['anthropic-version'],\n });\n return new Response(JSON.stringify(pages[calls.length - 1]));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'claude-first',\n 'claude-shared',\n 'claude-last',\n ]);\n assert.equal(result.origin, 'live');\n assert.equal(result.complete, true);\n assert.deepEqual(calls, [\n {\n url: 'https://api.anthropic.com/v1/models?limit=1000',\n apiKey: 'anthropic-secret',\n version: '2023-06-01',\n },\n {\n url: 'https://api.anthropic.com/v1/models?limit=1000&after_id=claude-shared',\n apiKey: 'anthropic-secret',\n version: '2023-06-01',\n },\n ]);\n});\n\ntest('public Anthropic discovery enriches documented metadata in an existing fresh cache', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'anthropic-model-cache-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const cachedModel = {\n ...normalizeSuppliedModels(['claude-sonnet-5'])[0],\n displayName: 'Claude Sonnet 5',\n contextWindow: 1000000,\n maxOutputTokens: 128000,\n inputModalities: ['text', 'image'],\n reasoning: true,\n reasoningLevels: ['low', 'medium', 'high', 'xhigh', 'max'],\n metadataSources: {\n ...normalizeSuppliedModels(['claude-sonnet-5'])[0].metadataSources,\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n },\n source: 'anthropic-catalog',\n };\n const cacheOptions = {\n provider: 'anthropic',\n endpoint: anthropic.ENDPOINT,\n apiKey: 'anthropic-secret',\n cacheDir,\n };\n writeCache(\n cacheOptions,\n cacheIdentity(cacheOptions),\n [cachedModel],\n 1000,\n { origin: 'live', complete: true },\n );\n\n const result = await discoverModels({\n provider: 'anthropic',\n baseUrl: anthropic.BASE_URL,\n apiKey: 'anthropic-secret',\n cacheDir,\n now: () => 1001,\n fetchImpl: async () => {\n throw new Error('fresh cache must avoid network access');\n },\n });\n\n assert.equal(result.cache.state, 'fresh');\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.equal(result.models[0].defaultReasoningLevel, 'high');\n assert.equal(result.models[0].toolCalling, true);\n});\n\ntest('Anthropic discovery rejects cursor loops and falls back to its bundled catalog', async () => {\n let calls = 0;\n const result = await anthropic.discover({\n apiKey: 'anthropic-secret',\n fetchImpl: async () => {\n calls += 1;\n return new Response(JSON.stringify({\n data: [{ id: `claude-page-${calls}`, type: 'model' }],\n last_id: 'repeated-cursor',\n has_more: true,\n }));\n },\n });\n\n assert.equal(calls, 2);\n assert.equal(result.origin, 'bundled');\n assert.equal(result.complete, false);\n assert.equal(result.fallback.state, 'bundled');\n assert.ok(result.models.length > 0);\n});\n\ntest('OpenAI discovery preserves provider metadata and leaves unknown capabilities unset', () => {\n const model = openai.parseRow({\n id: 'gpt-example',\n object: 'model',\n created: 1785196800,\n owned_by: 'openai',\n });\n\n assert.deepEqual(model, {\n id: 'gpt-example',\n displayName: 'gpt-example',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n providerMetadata: {\n created: 1785196800,\n object: 'model',\n ownedBy: 'openai',\n },\n source: 'openai-catalog',\n });\n});\n\ntest('OpenAI catalog normalization applies the live-tested reasoning effort matrix', () => {\n const models = openai.normalizeModels([\n openai.parseRow({ id: 'o3' }),\n openai.parseRow({ id: 'gpt-5.6-sol' }),\n openai.parseRow({ id: 'gpt-5-pro' }),\n openai.parseRow({ id: 'gpt-4' }),\n openai.parseRow({ id: 'future-openai-model' }),\n ]);\n\n assert.deepEqual(models.map((model) => ({\n id: model.id,\n reasoning: model.reasoning,\n levels: model.reasoningLevels,\n defaultLevel: model.defaultReasoningLevel,\n })), [\n {\n id: 'o3',\n reasoning: true,\n levels: ['low', 'medium', 'high'],\n defaultLevel: 'medium',\n },\n {\n id: 'gpt-5.6-sol',\n reasoning: true,\n levels: ['none', 'low', 'medium', 'high', 'xhigh', 'max'],\n defaultLevel: 'low',\n },\n {\n id: 'gpt-5-pro',\n reasoning: true,\n levels: ['high'],\n defaultLevel: 'high',\n },\n {\n id: 'gpt-4',\n reasoning: false,\n levels: null,\n defaultLevel: null,\n },\n {\n id: 'future-openai-model',\n reasoning: false,\n levels: null,\n defaultLevel: null,\n },\n ]);\n assert.equal(models[0].metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(models[3].metadataSources.reasoning, 'provider-catalog');\n});\n\ntest('OpenAI discovery excludes proven-incompatible models while retaining newly introduced models', async () => {\n const ids = [\n 'gpt-4.1-mini',\n 'gpt-5.6-sol',\n 'text-embedding-example',\n 'ft:text-embedding-example:organization:suffix:id',\n 'vendor/embeddings-v2',\n 'whisper-1',\n 'gpt-image-2',\n 'tts-1',\n 'omni-moderation-latest',\n 'gpt-realtime-2.1',\n 'gpt-audio',\n 'gpt-5-chat-latest',\n 'ft:gpt-4.1-mini:organization:suffix:id',\n 'future-openai-model',\n 'ft:future-openai-model:organization:suffix:id',\n ];\n const calls = [];\n const result = await openai.discover({\n apiKey: 'openai-secret',\n fetchImpl: async (url, options) => {\n calls.push({\n url: String(url),\n authorization: options.headers.Authorization,\n });\n return new Response(JSON.stringify({\n object: 'list',\n data: ids.concat('gpt-4.1-mini').map((id) => ({\n id,\n object: 'model',\n created: 1785196800,\n owned_by: 'openai',\n })),\n }));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gpt-4.1-mini',\n 'gpt-5.6-sol',\n 'ft:gpt-4.1-mini:organization:suffix:id',\n 'future-openai-model',\n 'ft:future-openai-model:organization:suffix:id',\n ]);\n assert.equal(result.origin, 'live');\n assert.equal(result.complete, true);\n assert.deepEqual(calls, [{\n url: 'https://api.openai.com/v1/models',\n authorization: 'Bearer openai-secret',\n }]);\n});\n\ntest('OpenAI discovery falls back to its bundled Codex model-cache catalog', async () => {\n const result = await openai.discover({\n apiKey: 'openai-secret',\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.origin, 'bundled');\n assert.equal(result.complete, false);\n assert.equal(result.fallback.state, 'bundled');\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gpt-5.4',\n 'gpt-5.4-mini',\n 'gpt-5.5',\n 'gpt-5.6-luna',\n 'gpt-5.6-sol',\n 'gpt-5.6-terra',\n ]);\n});\n\ntest('public OpenAI discovery filters non-Codex rows from an existing fresh cache', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openai-model-cache-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const cacheOptions = {\n provider: 'openai',\n endpoint: openai.ENDPOINT,\n apiKey: 'openai-secret',\n cacheDir,\n };\n writeCache(\n cacheOptions,\n cacheIdentity(cacheOptions),\n [\n openai.parseRow({ id: 'gpt-4.1-mini' }),\n openai.parseRow({ id: 'text-embedding-example' }),\n openai.parseRow({ id: 'whisper-1' }),\n openai.parseRow({ id: 'gpt-audio' }),\n openai.parseRow({ id: 'gpt-image-2' }),\n ],\n 1000,\n { origin: 'live', complete: true },\n );\n\n const result = await discoverModels({\n provider: 'openai',\n baseUrl: openai.BASE_URL,\n apiKey: 'openai-secret',\n cacheDir,\n now: () => 1001,\n fetchImpl: async () => {\n throw new Error('fresh cache must avoid network access');\n },\n });\n\n assert.equal(result.cache.state, 'fresh');\n assert.deepEqual(result.models.map((model) => model.id), ['gpt-4.1-mini']);\n});\n\ntest('Anthropic and OpenAI treat empty successful inventories as bundled fallbacks', async () => {\n const anthropicResult = await anthropic.discover({\n fetchImpl: async () => new Response(JSON.stringify({\n data: [],\n has_more: false,\n })),\n });\n const openaiResult = await openai.discover({\n fetchImpl: async () => new Response(JSON.stringify({\n object: 'list',\n data: [],\n })),\n });\n\n assert.equal(anthropicResult.origin, 'bundled');\n assert.equal(anthropicResult.fallback.state, 'bundled');\n assert.equal(openaiResult.origin, 'bundled');\n assert.equal(openaiResult.fallback.state, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n {\n name: 'command-a-plus-05-2026',\n is_deprecated: false,\n features: ['reasoning', 'vision', 'tools'],\n },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 436000);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n assert.equal(result.models[0].metadataSources.reasoning, 'provider-catalog');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches exact live ids from the owned snapshot without metadata network calls', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-owned-enrich-'));\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-a-plus-05-2026' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command A+');\n assert.equal(result.models[0].contextWindow, 436000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: null,\n expectedSource: null,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n expectedSource: 'provider-catalog',\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-v4-pro',\n expectedContext: 1048576,\n expectedSource: 'openrouter-catalog',\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, entry.expectedSource);\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('a provider without an owned cache rejects a malformed successful payload', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n await assert.rejects(zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async () => new Response('{\"unexpected\":true}'),\n }), /model list/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async () => new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] })),\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cache.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery classifies generateContent Gemini image models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/gemini-3.1-flash-image',\n displayName: 'Gemini 3.1 Flash Image',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 65536,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gemini-3.1-pro',\n 'gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('xAI compatibility filtering requires no separate metadata request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-owned-filter-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, xai.ENDPOINT);\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.deepEqual(result.warnings, []);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('xAI discovery enriches sparse live rows with exact bundled modalities', async () => {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n fetchImpl: async () => new Response(JSON.stringify({\n data: [\n { id: 'grok-4.5' },\n { id: 'grok-4.20-0309-reasoning' },\n { id: 'grok-imagine-image' },\n { id: 'grok-imagine-video-1.5' },\n ],\n })),\n });\n\n assert.deepEqual(result.models.map((model) => [\n model.id,\n model.inputModalities,\n model.outputModalities,\n model.reasoningLevels,\n model.defaultReasoningLevel,\n ]), [\n ['grok-4.5', ['text', 'image'], ['text'], ['low', 'medium', 'high'], 'high'],\n ['grok-4.20-0309-reasoning', ['text', 'image'], ['text'], null, null],\n ['grok-imagine-image', ['text', 'image'], ['image'], null, null],\n ['grok-imagine-video-1.5', ['image'], ['video'], null, null],\n ]);\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n defaultReasoningLevel: 'HIGH',\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.defaultReasoningLevel, 'high');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(model.metadataSources.defaultReasoningLevel, 'provider-catalog');\n});\n\ntest('xAI discovery filters unsupported multi-agent models locally', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) =>\n model.id.endsWith(':cloud') || /^gemma4:[^:]+-cloud$/u.test(model.id)));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery reads its cloud candidates without a catalog network request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-local-snapshot-'));\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama live discovery retains cloud enrichment but displays the exact model id', async () => {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'gemma4:31b-cloud' }] },\n fetchImpl: async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'gemma4:31b-cloud');\n return new Response(JSON.stringify({\n model_info: { 'gemma4.context_length': 262144 },\n capabilities: ['completion', 'thinking', 'tools', 'vision'],\n }));\n },\n });\n\n const gemma4 = result.models.find((model) => model.id === 'gemma4:31b-cloud');\n assert.equal(gemma4.displayName, 'gemma4:31b-cloud');\n assert.deepEqual(gemma4.reasoningLevels, ['none', 'low', 'medium', 'high', 'max']);\n assert.equal(gemma4.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(gemma4.contextWindow, 262144);\n assert.deepEqual(gemma4.inputModalities, ['text', 'image']);\n assert.ok(result.models.every((model) => model.displayName === model.id));\n});\n\ntest('Ollama live discovery applies reasoning controls to the full Gemma 4 family', async () => {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: {\n models: [\n { name: 'gemma4:e2b' },\n { name: 'gemma4:12b-it-q4_K_M' },\n { name: 'gemma4:26b-a4b-it-q8_0' },\n ],\n },\n fetchImpl: async (_url, options) => {\n const id = JSON.parse(options.body).name;\n return new Response(JSON.stringify({\n model_info: { 'gemma4.context_length': id === 'gemma4:e2b' ? 131072 : 262144 },\n capabilities: ['completion', 'thinking', 'tools', 'vision'],\n }));\n },\n });\n\n for (const id of [\n 'gemma4:e2b',\n 'gemma4:12b-it-q4_K_M',\n 'gemma4:26b-a4b-it-q8_0',\n ]) {\n const model = result.models.find((entry) => entry.id === id);\n assert.deepEqual(model.reasoningLevels, ['none', 'low', 'medium', 'high', 'max']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cache.state, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cache.state, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.equal(refreshed.models[0].id, 'nvidia/featured');\n assert.equal(refreshed.models.at(-1).id, 'private/model');\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cache.state, 'fresh');\n assert.equal(calls, 1);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n inventoryComplete: true,\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/provider-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "a3fed196639fe50ba7f34a7ce46299c5eebe9069": {"t": 1785758803.8783658, "n": 65732, "h": "4b15a52f2ea958d3", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\nconst { assertPrivateDirectoryMode, assertPrivateFileMode } = require('./helpers/file-mode');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeReasoningLevels,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst {\n cacheIdentity,\n withProviderCache,\n writeCache,\n} = require('../src/model-discovery/file-cache');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst anthropic = require('../src/model-discovery/providers/anthropic');\nconst openai = require('../src/model-discovery/providers/openai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('reasoning normalization preserves every effort accepted by the Codex model cache', () => {\n assert.deepEqual(\n normalizeReasoningLevels(['ultra', 'max', 'xhigh', 'high', 'medium', 'low']),\n ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'],\n );\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('Vertex AI OpenAI endpoints resolve as Google without probing', async () => {\n let fetchCalls = 0;\n const result = await resolveProvider({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n fetchImpl: async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n },\n });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'canonical-url');\n assert.equal(fetchCalls, 0);\n});\n\ntest('Google provider aliases resolve explicitly without probing', async () => {\n let fetches = 0;\n const fetchImpl = async () => {\n fetches += 1;\n throw new Error('must not fetch');\n };\n\n for (const provider of ['aistudio', 'gemini', 'vertexai', 'vertex-ai']) {\n const result = await resolveProvider({ provider, fetchImpl });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetches, 0);\n});\n\ntest('Vertex Google discovery classifies only explicitly supplied Gemini models', async () => {\n const result = await google.discover({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n suppliedModels: ['google/gemini-2.5-flash', 'google/gemini-3.1-flash-image'],\n fetchImpl: async () => {\n throw new Error('Vertex discovery must not call the Developer API catalog');\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'google/gemini-2.5-flash',\n 'google/gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.complete, false);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching strips provider authentication headers on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({\n url: String(url),\n apiKey: options.headers['x-api-key'],\n version: options.headers['anthropic-version'],\n });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"data\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://api.anthropic.com/v1/models',\n provider: 'anthropic',\n authHeaders: {\n 'x-api-key': 'anthropic-secret',\n 'anthropic-version': '2023-06-01',\n },\n fetchImpl,\n });\n\n assert.deepEqual(result, { data: [] });\n assert.deepEqual(calls, [\n {\n url: 'https://api.anthropic.com/v1/models',\n apiKey: 'anthropic-secret',\n version: '2023-06-01',\n },\n {\n url: 'https://cdn.example/catalog.json',\n apiKey: undefined,\n version: undefined,\n },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return { models: [model], origin: 'live', complete: true };\n });\n assert.equal(first.state, 'refreshed');\n assert.equal(first.origin, 'live');\n assert.equal(first.complete, true);\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(fresh.origin, 'live');\n assert.equal(fresh.complete, true);\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.state, 'stale');\n assert.equal(stale.origin, 'live');\n assert.equal(stale.complete, true);\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assertPrivateDirectoryMode(path.join(cacheDir, 'nvidia'));\n assertPrivateFileMode(path.join(cacheDir, 'nvidia', files[0]));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, ['https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json']);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.slice(0, 2).map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n reasoning: {\n supported_efforts: ['xhigh', 'high', 'medium', 'low', 'none'],\n default_effort: 'medium',\n default_enabled: false,\n supports_max_tokens: true,\n mandatory: false,\n },\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, ['none', 'low', 'medium', 'high', 'xhigh']);\n assert.equal(rich.defaultReasoningLevel, 'medium');\n assert.equal(rich.reasoningDefaultEnabled, false);\n assert.equal(rich.reasoningSupportsMaxTokens, true);\n assert.equal(rich.reasoningMandatory, false);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n defaultReasoningLevel: 'provider-catalog',\n reasoningDefaultEnabled: 'provider-catalog',\n reasoningSupportsMaxTokens: 'provider-catalog',\n reasoningMandatory: 'provider-catalog',\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its complete owned snapshot', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.models.length, 345);\n assert.ok(result.models.some((model) => model.id === 'openrouter/auto'));\n assert.ok(result.models.some((model) => model.id === 'moonshotai/kimi-k2.6'));\n assert.equal(result.fallback.state, 'bundled');\n});\n\ntest('OpenRouter reasoning metadata distinguishes all-efforts from no exposed effort selector', () => {\n const allEfforts = openrouter.parseRow({\n id: 'vendor/all-efforts',\n architecture: { modality: 'text->text' },\n reasoning: {\n supported_efforts: null,\n default_effort: 'medium',\n default_enabled: true,\n mandatory: false,\n },\n });\n assert.deepEqual(allEfforts.reasoningLevels, [\n 'none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max',\n ]);\n assert.equal(allEfforts.defaultReasoningLevel, 'medium');\n\n const noSelector = openrouter.parseRow({\n id: 'vendor/no-selector',\n architecture: { modality: 'text->text' },\n reasoning: {\n default_enabled: true,\n mandatory: true,\n },\n });\n assert.equal(noSelector.reasoning, true);\n assert.equal(noSelector.reasoningLevels, null);\n assert.equal(noSelector.defaultReasoningLevel, null);\n assert.equal(noSelector.reasoningDefaultEnabled, true);\n assert.equal(noSelector.reasoningMandatory, true);\n});\n\ntest('Anthropic discovery enriches exact models from official compatibility documentation', () => {\n const model = anthropic.parseRow({\n id: 'claude-sonnet-5',\n type: 'model',\n display_name: 'Claude Sonnet 5',\n created_at: '2026-07-01T00:00:00Z',\n max_input_tokens: 1000000,\n max_tokens: 128000,\n capabilities: {\n image_input: { supported: true },\n thinking: {\n supported: true,\n types: {\n adaptive: { supported: true },\n enabled: { supported: true },\n },\n },\n effort: {\n supported: true,\n low: { supported: true },\n medium: { supported: true },\n high: { supported: true },\n xhigh: { supported: false },\n max: { supported: true },\n },\n future_capability: { supported: true },\n },\n });\n\n assert.deepEqual(model, {\n id: 'claude-sonnet-5',\n displayName: 'Claude Sonnet 5',\n contextWindow: 1000000,\n maxOutputTokens: 128000,\n inputModalities: ['text', 'image'],\n outputModalities: ['text'],\n reasoning: true,\n reasoningLevels: ['low', 'medium', 'high', 'max'],\n defaultReasoningLevel: 'high',\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: true,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n defaultReasoningLevel: 'provider-catalog',\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: 'provider-catalog',\n },\n providerMetadata: {\n createdAt: '2026-07-01T00:00:00Z',\n type: 'model',\n },\n source: 'anthropic-catalog',\n });\n});\n\ntest('Anthropic documentation enrichment does not guess capabilities for unknown future ids', () => {\n const model = anthropic.parseRow({\n id: 'claude-future-example',\n type: 'model',\n display_name: 'Claude Future Example',\n max_input_tokens: 1000000,\n max_tokens: 128000,\n capabilities: {},\n });\n\n assert.equal(model.inputModalities, null);\n assert.equal(model.outputModalities, null);\n assert.equal(model.reasoningLevels, null);\n assert.equal(model.defaultReasoningLevel, null);\n assert.equal(model.toolCalling, null);\n});\n\ntest('Anthropic discovery authenticates and follows model pagination in provider order', async () => {\n const calls = [];\n const pages = [\n {\n data: [\n { id: 'claude-first', type: 'model', display_name: 'Claude First' },\n { id: 'claude-shared', type: 'model', display_name: 'Claude Shared' },\n ],\n first_id: 'claude-first',\n last_id: 'claude-shared',\n has_more: true,\n },\n {\n data: [\n { id: 'claude-shared', type: 'model', display_name: 'Duplicate' },\n { id: 'claude-last', type: 'model', display_name: 'Claude Last' },\n ],\n first_id: 'claude-shared',\n last_id: 'claude-last',\n has_more: false,\n },\n ];\n const result = await anthropic.discover({\n apiKey: 'anthropic-secret',\n fetchImpl: async (url, options) => {\n calls.push({\n url: String(url),\n apiKey: options.headers['x-api-key'],\n version: options.headers['anthropic-version'],\n });\n return new Response(JSON.stringify(pages[calls.length - 1]));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'claude-first',\n 'claude-shared',\n 'claude-last',\n ]);\n assert.equal(result.origin, 'live');\n assert.equal(result.complete, true);\n assert.deepEqual(calls, [\n {\n url: 'https://api.anthropic.com/v1/models?limit=1000',\n apiKey: 'anthropic-secret',\n version: '2023-06-01',\n },\n {\n url: 'https://api.anthropic.com/v1/models?limit=1000&after_id=claude-shared',\n apiKey: 'anthropic-secret',\n version: '2023-06-01',\n },\n ]);\n});\n\ntest('public Anthropic discovery enriches documented metadata in an existing fresh cache', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'anthropic-model-cache-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const cachedModel = {\n ...normalizeSuppliedModels(['claude-sonnet-5'])[0],\n displayName: 'Claude Sonnet 5',\n contextWindow: 1000000,\n maxOutputTokens: 128000,\n inputModalities: ['text', 'image'],\n reasoning: true,\n reasoningLevels: ['low', 'medium', 'high', 'xhigh', 'max'],\n metadataSources: {\n ...normalizeSuppliedModels(['claude-sonnet-5'])[0].metadataSources,\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n },\n source: 'anthropic-catalog',\n };\n const cacheOptions = {\n provider: 'anthropic',\n endpoint: anthropic.ENDPOINT,\n apiKey: 'anthropic-secret',\n cacheDir,\n };\n writeCache(\n cacheOptions,\n cacheIdentity(cacheOptions),\n [cachedModel],\n 1000,\n { origin: 'live', complete: true },\n );\n\n const result = await discoverModels({\n provider: 'anthropic',\n baseUrl: anthropic.BASE_URL,\n apiKey: 'anthropic-secret',\n cacheDir,\n now: () => 1001,\n fetchImpl: async () => {\n throw new Error('fresh cache must avoid network access');\n },\n });\n\n assert.equal(result.cache.state, 'fresh');\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.equal(result.models[0].defaultReasoningLevel, 'high');\n assert.equal(result.models[0].toolCalling, true);\n});\n\ntest('Anthropic discovery rejects cursor loops and falls back to its bundled catalog', async () => {\n let calls = 0;\n const result = await anthropic.discover({\n apiKey: 'anthropic-secret',\n fetchImpl: async () => {\n calls += 1;\n return new Response(JSON.stringify({\n data: [{ id: `claude-page-${calls}`, type: 'model' }],\n last_id: 'repeated-cursor',\n has_more: true,\n }));\n },\n });\n\n assert.equal(calls, 2);\n assert.equal(result.origin, 'bundled');\n assert.equal(result.complete, false);\n assert.equal(result.fallback.state, 'bundled');\n assert.ok(result.models.length > 0);\n});\n\ntest('OpenAI discovery preserves provider metadata and leaves unknown capabilities unset', () => {\n const model = openai.parseRow({\n id: 'gpt-example',\n object: 'model',\n created: 1785196800,\n owned_by: 'openai',\n });\n\n assert.deepEqual(model, {\n id: 'gpt-example',\n displayName: 'gpt-example',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n providerMetadata: {\n created: 1785196800,\n object: 'model',\n ownedBy: 'openai',\n },\n source: 'openai-catalog',\n });\n});\n\ntest('OpenAI catalog normalization applies the live-tested reasoning effort matrix', () => {\n const models = openai.normalizeModels([\n openai.parseRow({ id: 'o3' }),\n openai.parseRow({ id: 'gpt-5.6-sol' }),\n openai.parseRow({ id: 'gpt-5-pro' }),\n openai.parseRow({ id: 'gpt-4' }),\n openai.parseRow({ id: 'future-openai-model' }),\n ]);\n\n assert.deepEqual(models.map((model) => ({\n id: model.id,\n reasoning: model.reasoning,\n levels: model.reasoningLevels,\n defaultLevel: model.defaultReasoningLevel,\n })), [\n {\n id: 'o3',\n reasoning: true,\n levels: ['low', 'medium', 'high'],\n defaultLevel: 'medium',\n },\n {\n id: 'gpt-5.6-sol',\n reasoning: true,\n levels: ['none', 'low', 'medium', 'high', 'xhigh', 'max'],\n defaultLevel: 'low',\n },\n {\n id: 'gpt-5-pro',\n reasoning: true,\n levels: ['high'],\n defaultLevel: 'high',\n },\n {\n id: 'gpt-4',\n reasoning: false,\n levels: null,\n defaultLevel: null,\n },\n {\n id: 'future-openai-model',\n reasoning: false,\n levels: null,\n defaultLevel: null,\n },\n ]);\n assert.equal(models[0].metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(models[3].metadataSources.reasoning, 'provider-catalog');\n});\n\ntest('OpenAI discovery excludes proven-incompatible models while retaining newly introduced models', async () => {\n const ids = [\n 'gpt-4.1-mini',\n 'gpt-5.6-sol',\n 'text-embedding-example',\n 'ft:text-embedding-example:organization:suffix:id',\n 'vendor/embeddings-v2',\n 'whisper-1',\n 'gpt-image-2',\n 'tts-1',\n 'omni-moderation-latest',\n 'gpt-realtime-2.1',\n 'gpt-audio',\n 'gpt-5-chat-latest',\n 'ft:gpt-4.1-mini:organization:suffix:id',\n 'future-openai-model',\n 'ft:future-openai-model:organization:suffix:id',\n ];\n const calls = [];\n const result = await openai.discover({\n apiKey: 'openai-secret',\n fetchImpl: async (url, options) => {\n calls.push({\n url: String(url),\n authorization: options.headers.Authorization,\n });\n return new Response(JSON.stringify({\n object: 'list',\n data: ids.concat('gpt-4.1-mini').map((id) => ({\n id,\n object: 'model',\n created: 1785196800,\n owned_by: 'openai',\n })),\n }));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gpt-4.1-mini',\n 'gpt-5.6-sol',\n 'ft:gpt-4.1-mini:organization:suffix:id',\n 'future-openai-model',\n 'ft:future-openai-model:organization:suffix:id',\n ]);\n assert.equal(result.origin, 'live');\n assert.equal(result.complete, true);\n assert.deepEqual(calls, [{\n url: 'https://api.openai.com/v1/models',\n authorization: 'Bearer openai-secret',\n }]);\n});\n\ntest('OpenAI discovery falls back to its bundled Codex model-cache catalog', async () => {\n const result = await openai.discover({\n apiKey: 'openai-secret',\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.origin, 'bundled');\n assert.equal(result.complete, false);\n assert.equal(result.fallback.state, 'bundled');\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gpt-5.4',\n 'gpt-5.4-mini',\n 'gpt-5.5',\n 'gpt-5.6-luna',\n 'gpt-5.6-sol',\n 'gpt-5.6-terra',\n ]);\n});\n\ntest('public OpenAI discovery filters non-Codex rows from an existing fresh cache', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openai-model-cache-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const cacheOptions = {\n provider: 'openai',\n endpoint: openai.ENDPOINT,\n apiKey: 'openai-secret',\n cacheDir,\n };\n writeCache(\n cacheOptions,\n cacheIdentity(cacheOptions),\n [\n openai.parseRow({ id: 'gpt-4.1-mini' }),\n openai.parseRow({ id: 'text-embedding-example' }),\n openai.parseRow({ id: 'whisper-1' }),\n openai.parseRow({ id: 'gpt-audio' }),\n openai.parseRow({ id: 'gpt-image-2' }),\n ],\n 1000,\n { origin: 'live', complete: true },\n );\n\n const result = await discoverModels({\n provider: 'openai',\n baseUrl: openai.BASE_URL,\n apiKey: 'openai-secret',\n cacheDir,\n now: () => 1001,\n fetchImpl: async () => {\n throw new Error('fresh cache must avoid network access');\n },\n });\n\n assert.equal(result.cache.state, 'fresh');\n assert.deepEqual(result.models.map((model) => model.id), ['gpt-4.1-mini']);\n});\n\ntest('Anthropic and OpenAI treat empty successful inventories as bundled fallbacks', async () => {\n const anthropicResult = await anthropic.discover({\n fetchImpl: async () => new Response(JSON.stringify({\n data: [],\n has_more: false,\n })),\n });\n const openaiResult = await openai.discover({\n fetchImpl: async () => new Response(JSON.stringify({\n object: 'list',\n data: [],\n })),\n });\n\n assert.equal(anthropicResult.origin, 'bundled');\n assert.equal(anthropicResult.fallback.state, 'bundled');\n assert.equal(openaiResult.origin, 'bundled');\n assert.equal(openaiResult.fallback.state, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n {\n name: 'command-a-plus-05-2026',\n is_deprecated: false,\n features: ['reasoning', 'vision', 'tools'],\n },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 436000);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n assert.equal(result.models[0].metadataSources.reasoning, 'provider-catalog');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches exact live ids from the owned snapshot without metadata network calls', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-owned-enrich-'));\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-a-plus-05-2026' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command A+');\n assert.equal(result.models[0].contextWindow, 436000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: null,\n expectedSource: null,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n expectedSource: 'provider-catalog',\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-v4-pro',\n expectedContext: 1048576,\n expectedSource: 'openrouter-catalog',\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, entry.expectedSource);\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('a provider without an owned cache rejects a malformed successful payload', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n await assert.rejects(zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async () => new Response('{\"unexpected\":true}'),\n }), /model list/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async () => new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] })),\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cache.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery classifies generateContent Gemini image models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/gemini-3.1-flash-image',\n displayName: 'Gemini 3.1 Flash Image',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 65536,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gemini-3.1-pro',\n 'gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('xAI compatibility filtering requires no separate metadata request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-owned-filter-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, xai.ENDPOINT);\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.deepEqual(result.warnings, []);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('xAI discovery enriches sparse live rows with exact bundled modalities', async () => {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n fetchImpl: async () => new Response(JSON.stringify({\n data: [\n { id: 'grok-4.5' },\n { id: 'grok-4.20-0309-reasoning' },\n { id: 'grok-imagine-image' },\n { id: 'grok-imagine-video-1.5' },\n ],\n })),\n });\n\n assert.deepEqual(result.models.map((model) => [\n model.id,\n model.inputModalities,\n model.outputModalities,\n model.reasoningLevels,\n model.defaultReasoningLevel,\n ]), [\n ['grok-4.5', ['text', 'image'], ['text'], ['low', 'medium', 'high'], 'high'],\n ['grok-4.20-0309-reasoning', ['text', 'image'], ['text'], null, null],\n ['grok-imagine-image', ['text', 'image'], ['image'], null, null],\n ['grok-imagine-video-1.5', ['image'], ['video'], null, null],\n ]);\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n defaultReasoningLevel: 'HIGH',\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.defaultReasoningLevel, 'high');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(model.metadataSources.defaultReasoningLevel, 'provider-catalog');\n});\n\ntest('xAI discovery filters unsupported multi-agent models locally', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) =>\n model.id.endsWith(':cloud') || /^gemma4:[^:]+-cloud$/u.test(model.id)));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery reads its cloud candidates without a catalog network request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-local-snapshot-'));\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama live discovery retains cloud enrichment but displays the exact model id', async () => {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'gemma4:31b-cloud' }] },\n fetchImpl: async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'gemma4:31b-cloud');\n return new Response(JSON.stringify({\n model_info: { 'gemma4.context_length': 262144 },\n capabilities: ['completion', 'thinking', 'tools', 'vision'],\n }));\n },\n });\n\n const gemma4 = result.models.find((model) => model.id === 'gemma4:31b-cloud');\n assert.equal(gemma4.displayName, 'gemma4:31b-cloud');\n assert.deepEqual(gemma4.reasoningLevels, ['none', 'low', 'medium', 'high', 'max']);\n assert.equal(gemma4.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(gemma4.contextWindow, 262144);\n assert.deepEqual(gemma4.inputModalities, ['text', 'image']);\n assert.ok(result.models.every((model) => model.displayName === model.id));\n});\n\ntest('Ollama live discovery applies reasoning controls to the full Gemma 4 family', async () => {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: {\n models: [\n { name: 'gemma4:e2b' },\n { name: 'gemma4:12b-it-q4_K_M' },\n { name: 'gemma4:26b-a4b-it-q8_0' },\n ],\n },\n fetchImpl: async (_url, options) => {\n const id = JSON.parse(options.body).name;\n return new Response(JSON.stringify({\n model_info: { 'gemma4.context_length': id === 'gemma4:e2b' ? 131072 : 262144 },\n capabilities: ['completion', 'thinking', 'tools', 'vision'],\n }));\n },\n });\n\n for (const id of [\n 'gemma4:e2b',\n 'gemma4:12b-it-q4_K_M',\n 'gemma4:26b-a4b-it-q8_0',\n ]) {\n const model = result.models.find((entry) => entry.id === id);\n assert.deepEqual(model.reasoningLevels, ['none', 'low', 'medium', 'high', 'max']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cache.state, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cache.state, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.equal(refreshed.models[0].id, 'nvidia/featured');\n assert.equal(refreshed.models.at(-1).id, 'private/model');\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cache.state, 'fresh');\n assert.equal(calls, 1);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n inventoryComplete: true,\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/provider-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "b79359506f2ba35778b574c3bdb9051d22e9dbe2": {"t": 1785758805.3880901, "n": 65524, "h": "0b94983438e413b0", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\nconst { assertPrivateDirectoryMode, assertPrivateFileMode } = require('./helpers/file-mode');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeReasoningLevels,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst {\n cacheIdentity,\n withProviderCache,\n writeCache,\n} = require('../src/model-discovery/file-cache');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst anthropic = require('../src/model-discovery/providers/anthropic');\nconst openai = require('../src/model-discovery/providers/openai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('reasoning normalization preserves every effort accepted by the Codex model cache', () => {\n assert.deepEqual(\n normalizeReasoningLevels(['ultra', 'max', 'xhigh', 'high', 'medium', 'low']),\n ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'],\n );\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('Vertex AI OpenAI endpoints resolve as Google without probing', async () => {\n let fetchCalls = 0;\n const result = await resolveProvider({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n fetchImpl: async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n },\n });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'canonical-url');\n assert.equal(fetchCalls, 0);\n});\n\ntest('Google provider aliases resolve explicitly without probing', async () => {\n let fetches = 0;\n const fetchImpl = async () => {\n fetches += 1;\n throw new Error('must not fetch');\n };\n\n for (const provider of ['aistudio', 'gemini', 'vertexai', 'vertex-ai']) {\n const result = await resolveProvider({ provider, fetchImpl });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetches, 0);\n});\n\ntest('Vertex Google discovery classifies only explicitly supplied Gemini models', async () => {\n const result = await google.discover({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n suppliedModels: ['google/gemini-2.5-flash', 'google/gemini-3.1-flash-image'],\n fetchImpl: async () => {\n throw new Error('Vertex discovery must not call the Developer API catalog');\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'google/gemini-2.5-flash',\n 'google/gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.complete, false);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching strips provider authentication headers on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({\n url: String(url),\n apiKey: options.headers['x-api-key'],\n version: options.headers['anthropic-version'],\n });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"data\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://api.anthropic.com/v1/models',\n provider: 'anthropic',\n authHeaders: {\n 'x-api-key': 'anthropic-secret',\n 'anthropic-version': '2023-06-01',\n },\n fetchImpl,\n });\n\n assert.deepEqual(result, { data: [] });\n assert.deepEqual(calls, [\n {\n url: 'https://api.anthropic.com/v1/models',\n apiKey: 'anthropic-secret',\n version: '2023-06-01',\n },\n {\n url: 'https://cdn.example/catalog.json',\n apiKey: undefined,\n version: undefined,\n },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return { models: [model], origin: 'live', complete: true };\n });\n assert.equal(first.state, 'refreshed');\n assert.equal(first.origin, 'live');\n assert.equal(first.complete, true);\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(fresh.origin, 'live');\n assert.equal(fresh.complete, true);\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.state, 'stale');\n assert.equal(stale.origin, 'live');\n assert.equal(stale.complete, true);\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assertPrivateDirectoryMode(path.join(cacheDir, 'nvidia'));\n assertPrivateFileMode(path.join(cacheDir, 'nvidia', files[0]));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, ['https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json']);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.slice(0, 2).map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n reasoning: {\n supported_efforts: ['xhigh', 'high', 'medium', 'low', 'none'],\n default_effort: 'medium',\n default_enabled: false,\n supports_max_tokens: true,\n mandatory: false,\n },\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, ['none', 'low', 'medium', 'high', 'xhigh']);\n assert.equal(rich.defaultReasoningLevel, 'medium');\n assert.equal(rich.reasoningDefaultEnabled, false);\n assert.equal(rich.reasoningSupportsMaxTokens, true);\n assert.equal(rich.reasoningMandatory, false);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n defaultReasoningLevel: 'provider-catalog',\n reasoningDefaultEnabled: 'provider-catalog',\n reasoningSupportsMaxTokens: 'provider-catalog',\n reasoningMandatory: 'provider-catalog',\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its complete owned snapshot', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.models.length, 345);\n assert.ok(result.models.some((model) => model.id === 'openrouter/auto'));\n assert.ok(result.models.some((model) => model.id === 'moonshotai/kimi-k2.6'));\n assert.equal(result.fallback.state, 'bundled');\n});\n\ntest('OpenRouter reasoning metadata distinguishes all-efforts from no exposed effort selector', () => {\n const allEfforts = openrouter.parseRow({\n id: 'vendor/all-efforts',\n architecture: { modality: 'text->text' },\n reasoning: {\n supported_efforts: null,\n default_effort: 'medium',\n default_enabled: true,\n mandatory: false,\n },\n });\n assert.deepEqual(allEfforts.reasoningLevels, [\n 'none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max',\n ]);\n assert.equal(allEfforts.defaultReasoningLevel, 'medium');\n\n const noSelector = openrouter.parseRow({\n id: 'vendor/no-selector',\n architecture: { modality: 'text->text' },\n reasoning: {\n default_enabled: true,\n mandatory: true,\n },\n });\n assert.equal(noSelector.reasoning, true);\n assert.equal(noSelector.reasoningLevels, null);\n assert.equal(noSelector.defaultReasoningLevel, null);\n assert.equal(noSelector.reasoningDefaultEnabled, true);\n assert.equal(noSelector.reasoningMandatory, true);\n});\n\ntest('Anthropic discovery enriches exact models from official compatibility documentation', () => {\n const model = anthropic.parseRow({\n id: 'claude-sonnet-5',\n type: 'model',\n display_name: 'Claude Sonnet 5',\n created_at: '2026-07-01T00:00:00Z',\n max_input_tokens: 1000000,\n max_tokens: 128000,\n capabilities: {\n image_input: { supported: true },\n thinking: {\n supported: true,\n types: {\n adaptive: { supported: true },\n enabled: { supported: true },\n },\n },\n effort: {\n supported: true,\n low: { supported: true },\n medium: { supported: true },\n high: { supported: true },\n xhigh: { supported: false },\n max: { supported: true },\n },\n future_capability: { supported: true },\n },\n });\n\n assert.deepEqual(model, {\n id: 'claude-sonnet-5',\n displayName: 'Claude Sonnet 5',\n contextWindow: 1000000,\n maxOutputTokens: 128000,\n inputModalities: ['text', 'image'],\n outputModalities: ['text'],\n reasoning: true,\n reasoningLevels: ['low', 'medium', 'high', 'max'],\n defaultReasoningLevel: 'high',\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: true,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n defaultReasoningLevel: 'provider-catalog',\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: 'provider-catalog',\n },\n providerMetadata: {\n createdAt: '2026-07-01T00:00:00Z',\n type: 'model',\n },\n source: 'anthropic-catalog',\n });\n});\n\ntest('Anthropic documentation enrichment does not guess capabilities for unknown future ids', () => {\n const model = anthropic.parseRow({\n id: 'claude-future-example',\n type: 'model',\n display_name: 'Claude Future Example',\n max_input_tokens: 1000000,\n max_tokens: 128000,\n capabilities: {},\n });\n\n assert.equal(model.inputModalities, null);\n assert.equal(model.outputModalities, null);\n assert.equal(model.reasoningLevels, null);\n assert.equal(model.defaultReasoningLevel, null);\n assert.equal(model.toolCalling, null);\n});\n\ntest('Anthropic discovery authenticates and follows model pagination in provider order', async () => {\n const calls = [];\n const pages = [\n {\n data: [\n { id: 'claude-first', type: 'model', display_name: 'Claude First' },\n { id: 'claude-shared', type: 'model', display_name: 'Claude Shared' },\n ],\n first_id: 'claude-first',\n last_id: 'claude-shared',\n has_more: true,\n },\n {\n data: [\n { id: 'claude-shared', type: 'model', display_name: 'Duplicate' },\n { id: 'claude-last', type: 'model', display_name: 'Claude Last' },\n ],\n first_id: 'claude-shared',\n last_id: 'claude-last',\n has_more: false,\n },\n ];\n const result = await anthropic.discover({\n apiKey: 'anthropic-secret',\n fetchImpl: async (url, options) => {\n calls.push({\n url: String(url),\n apiKey: options.headers['x-api-key'],\n version: options.headers['anthropic-version'],\n });\n return new Response(JSON.stringify(pages[calls.length - 1]));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'claude-first',\n 'claude-shared',\n 'claude-last',\n ]);\n assert.equal(result.origin, 'live');\n assert.equal(result.complete, true);\n assert.deepEqual(calls, [\n {\n url: 'https://api.anthropic.com/v1/models?limit=1000',\n apiKey: 'anthropic-secret',\n version: '2023-06-01',\n },\n {\n url: 'https://api.anthropic.com/v1/models?limit=1000&after_id=claude-shared',\n apiKey: 'anthropic-secret',\n version: '2023-06-01',\n },\n ]);\n});\n\ntest('public Anthropic discovery enriches documented metadata in an existing fresh cache', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'anthropic-model-cache-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const cachedModel = {\n ...normalizeSuppliedModels(['claude-sonnet-5'])[0],\n displayName: 'Claude Sonnet 5',\n contextWindow: 1000000,\n maxOutputTokens: 128000,\n inputModalities: ['text', 'image'],\n reasoning: true,\n reasoningLevels: ['low', 'medium', 'high', 'xhigh', 'max'],\n metadataSources: {\n ...normalizeSuppliedModels(['claude-sonnet-5'])[0].metadataSources,\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n },\n source: 'anthropic-catalog',\n };\n const cacheOptions = {\n provider: 'anthropic',\n endpoint: anthropic.ENDPOINT,\n apiKey: 'anthropic-secret',\n cacheDir,\n };\n writeCache(\n cacheOptions,\n cacheIdentity(cacheOptions),\n [cachedModel],\n 1000,\n { origin: 'live', complete: true },\n );\n\n const result = await discoverModels({\n provider: 'anthropic',\n baseUrl: anthropic.BASE_URL,\n apiKey: 'anthropic-secret',\n cacheDir,\n now: () => 1001,\n fetchImpl: async () => {\n throw new Error('fresh cache must avoid network access');\n },\n });\n\n assert.equal(result.cache.state, 'fresh');\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.equal(result.models[0].defaultReasoningLevel, 'high');\n assert.equal(result.models[0].toolCalling, true);\n});\n\ntest('Anthropic discovery rejects cursor loops and falls back to its bundled catalog', async () => {\n let calls = 0;\n const result = await anthropic.discover({\n apiKey: 'anthropic-secret',\n fetchImpl: async () => {\n calls += 1;\n return new Response(JSON.stringify({\n data: [{ id: `claude-page-${calls}`, type: 'model' }],\n last_id: 'repeated-cursor',\n has_more: true,\n }));\n },\n });\n\n assert.equal(calls, 2);\n assert.equal(result.origin, 'bundled');\n assert.equal(result.complete, false);\n assert.equal(result.fallback.state, 'bundled');\n assert.ok(result.models.length > 0);\n});\n\ntest('OpenAI discovery preserves provider metadata and leaves unknown capabilities unset', () => {\n const model = openai.parseRow({\n id: 'gpt-example',\n object: 'model',\n created: 1785196800,\n owned_by: 'openai',\n });\n\n assert.deepEqual(model, {\n id: 'gpt-example',\n displayName: 'gpt-example',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n providerMetadata: {\n created: 1785196800,\n object: 'model',\n ownedBy: 'openai',\n },\n source: 'openai-catalog',\n });\n});\n\ntest('OpenAI catalog normalization applies the live-tested reasoning effort matrix', () => {\n const models = openai.normalizeModels([\n openai.parseRow({ id: 'o3' }),\n openai.parseRow({ id: 'gpt-5.6-sol' }),\n openai.parseRow({ id: 'gpt-5-pro' }),\n openai.parseRow({ id: 'gpt-4' }),\n openai.parseRow({ id: 'future-openai-model' }),\n ]);\n\n assert.deepEqual(models.map((model) => ({\n id: model.id,\n reasoning: model.reasoning,\n levels: model.reasoningLevels,\n defaultLevel: model.defaultReasoningLevel,\n })), [\n {\n id: 'o3',\n reasoning: true,\n levels: ['low', 'medium', 'high'],\n defaultLevel: 'medium',\n },\n {\n id: 'gpt-5.6-sol',\n reasoning: true,\n levels: ['none', 'low', 'medium', 'high', 'xhigh', 'max'],\n defaultLevel: 'low',\n },\n {\n id: 'gpt-5-pro',\n reasoning: true,\n levels: ['high'],\n defaultLevel: 'high',\n },\n {\n id: 'gpt-4',\n reasoning: false,\n levels: null,\n defaultLevel: null,\n },\n {\n id: 'future-openai-model',\n reasoning: false,\n levels: null,\n defaultLevel: null,\n },\n ]);\n assert.equal(models[0].metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(models[3].metadataSources.reasoning, 'provider-catalog');\n});\n\ntest('OpenAI discovery excludes embedding and Whisper models while retaining every other purpose in provider order', async () => {\n const ids = [\n 'gpt-example',\n 'text-embedding-example',\n 'ft:text-embedding-example:organization:suffix:id',\n 'vendor/embeddings-v2',\n 'whisper-1',\n 'gpt-image-example',\n 'tts-example',\n 'omni-moderation-example',\n 'ft:gpt-example:organization:suffix:id',\n 'embedded-knowledge-gpt-example',\n ];\n const calls = [];\n const result = await openai.discover({\n apiKey: 'openai-secret',\n fetchImpl: async (url, options) => {\n calls.push({\n url: String(url),\n authorization: options.headers.Authorization,\n });\n return new Response(JSON.stringify({\n object: 'list',\n data: ids.concat('gpt-example').map((id) => ({\n id,\n object: 'model',\n created: 1785196800,\n owned_by: 'openai',\n })),\n }));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gpt-example',\n 'gpt-image-example',\n 'tts-example',\n 'omni-moderation-example',\n 'ft:gpt-example:organization:suffix:id',\n 'embedded-knowledge-gpt-example',\n ]);\n assert.equal(result.origin, 'live');\n assert.equal(result.complete, true);\n assert.deepEqual(calls, [{\n url: 'https://api.openai.com/v1/models',\n authorization: 'Bearer openai-secret',\n }]);\n});\n\ntest('OpenAI discovery falls back to its bundled Codex model-cache catalog', async () => {\n const result = await openai.discover({\n apiKey: 'openai-secret',\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.origin, 'bundled');\n assert.equal(result.complete, false);\n assert.equal(result.fallback.state, 'bundled');\n assert.ok(result.models.some((model) => model.id === 'gpt-5.6-sol'));\n assert.ok(result.models.every((model) => !model.id.includes('embedding')));\n});\n\ntest('public OpenAI discovery filters embedding rows from an existing fresh cache', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openai-model-cache-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const cacheOptions = {\n provider: 'openai',\n endpoint: openai.ENDPOINT,\n apiKey: 'openai-secret',\n cacheDir,\n };\n writeCache(\n cacheOptions,\n cacheIdentity(cacheOptions),\n [\n openai.parseRow({ id: 'gpt-example' }),\n openai.parseRow({ id: 'text-embedding-example' }),\n openai.parseRow({ id: 'whisper-1' }),\n ],\n 1000,\n { origin: 'live', complete: true },\n );\n\n const result = await discoverModels({\n provider: 'openai',\n baseUrl: openai.BASE_URL,\n apiKey: 'openai-secret',\n cacheDir,\n now: () => 1001,\n fetchImpl: async () => {\n throw new Error('fresh cache must avoid network access');\n },\n });\n\n assert.equal(result.cache.state, 'fresh');\n assert.deepEqual(result.models.map((model) => model.id), ['gpt-example']);\n});\n\ntest('Anthropic and OpenAI treat empty successful inventories as bundled fallbacks', async () => {\n const anthropicResult = await anthropic.discover({\n fetchImpl: async () => new Response(JSON.stringify({\n data: [],\n has_more: false,\n })),\n });\n const openaiResult = await openai.discover({\n fetchImpl: async () => new Response(JSON.stringify({\n object: 'list',\n data: [],\n })),\n });\n\n assert.equal(anthropicResult.origin, 'bundled');\n assert.equal(anthropicResult.fallback.state, 'bundled');\n assert.equal(openaiResult.origin, 'bundled');\n assert.equal(openaiResult.fallback.state, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n {\n name: 'command-a-plus-05-2026',\n is_deprecated: false,\n features: ['reasoning', 'vision', 'tools'],\n },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 436000);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n assert.equal(result.models[0].metadataSources.reasoning, 'provider-catalog');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches exact live ids from the owned snapshot without metadata network calls', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-owned-enrich-'));\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-a-plus-05-2026' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command A+');\n assert.equal(result.models[0].contextWindow, 436000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: null,\n expectedSource: null,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n expectedSource: 'provider-catalog',\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-v4-pro',\n expectedContext: 1048576,\n expectedSource: 'openrouter-catalog',\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, entry.expectedSource);\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('a provider without an owned cache rejects a malformed successful payload', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n await assert.rejects(zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async () => new Response('{\"unexpected\":true}'),\n }), /model list/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async () => new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] })),\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cache.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery classifies generateContent Gemini image models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/gemini-3.1-flash-image',\n displayName: 'Gemini 3.1 Flash Image',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 65536,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gemini-3.1-pro',\n 'gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('xAI compatibility filtering requires no separate metadata request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-owned-filter-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, xai.ENDPOINT);\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.deepEqual(result.warnings, []);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('xAI discovery enriches sparse live rows with exact bundled modalities', async () => {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n fetchImpl: async () => new Response(JSON.stringify({\n data: [\n { id: 'grok-4.5' },\n { id: 'grok-4.20-0309-reasoning' },\n { id: 'grok-imagine-image' },\n { id: 'grok-imagine-video-1.5' },\n ],\n })),\n });\n\n assert.deepEqual(result.models.map((model) => [\n model.id,\n model.inputModalities,\n model.outputModalities,\n model.reasoningLevels,\n model.defaultReasoningLevel,\n ]), [\n ['grok-4.5', ['text', 'image'], ['text'], ['low', 'medium', 'high'], 'high'],\n ['grok-4.20-0309-reasoning', ['text', 'image'], ['text'], null, null],\n ['grok-imagine-image', ['text', 'image'], ['image'], null, null],\n ['grok-imagine-video-1.5', ['image'], ['video'], null, null],\n ]);\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n defaultReasoningLevel: 'HIGH',\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.defaultReasoningLevel, 'high');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(model.metadataSources.defaultReasoningLevel, 'provider-catalog');\n});\n\ntest('xAI discovery filters unsupported multi-agent models locally', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) =>\n model.id.endsWith(':cloud') || /^gemma4:[^:]+-cloud$/u.test(model.id)));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery reads its cloud candidates without a catalog network request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-local-snapshot-'));\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama live discovery retains cloud enrichment but displays the exact model id', async () => {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'gemma4:31b-cloud' }] },\n fetchImpl: async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'gemma4:31b-cloud');\n return new Response(JSON.stringify({\n model_info: { 'gemma4.context_length': 262144 },\n capabilities: ['completion', 'thinking', 'tools', 'vision'],\n }));\n },\n });\n\n const gemma4 = result.models.find((model) => model.id === 'gemma4:31b-cloud');\n assert.equal(gemma4.displayName, 'gemma4:31b-cloud');\n assert.deepEqual(gemma4.reasoningLevels, ['none', 'low', 'medium', 'high', 'max']);\n assert.equal(gemma4.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(gemma4.contextWindow, 262144);\n assert.deepEqual(gemma4.inputModalities, ['text', 'image']);\n assert.ok(result.models.every((model) => model.displayName === model.id));\n});\n\ntest('Ollama live discovery applies reasoning controls to the full Gemma 4 family', async () => {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: {\n models: [\n { name: 'gemma4:e2b' },\n { name: 'gemma4:12b-it-q4_K_M' },\n { name: 'gemma4:26b-a4b-it-q8_0' },\n ],\n },\n fetchImpl: async (_url, options) => {\n const id = JSON.parse(options.body).name;\n return new Response(JSON.stringify({\n model_info: { 'gemma4.context_length': id === 'gemma4:e2b' ? 131072 : 262144 },\n capabilities: ['completion', 'thinking', 'tools', 'vision'],\n }));\n },\n });\n\n for (const id of [\n 'gemma4:e2b',\n 'gemma4:12b-it-q4_K_M',\n 'gemma4:26b-a4b-it-q8_0',\n ]) {\n const model = result.models.find((entry) => entry.id === id);\n assert.deepEqual(model.reasoningLevels, ['none', 'low', 'medium', 'high', 'max']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cache.state, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cache.state, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.equal(refreshed.models[0].id, 'nvidia/featured');\n assert.equal(refreshed.models.at(-1).id, 'private/model');\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cache.state, 'fresh');\n assert.equal(calls, 1);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n inventoryComplete: true,\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/provider-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "1c259f15de942157c21feab91262dc9e8b986018": {"t": 1785758807.2155695, "n": 64141, "h": "20bfabce2a62c3e0", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\nconst { assertPrivateDirectoryMode, assertPrivateFileMode } = require('./helpers/file-mode');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeReasoningLevels,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst {\n cacheIdentity,\n withProviderCache,\n writeCache,\n} = require('../src/model-discovery/file-cache');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst anthropic = require('../src/model-discovery/providers/anthropic');\nconst openai = require('../src/model-discovery/providers/openai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('reasoning normalization preserves every effort accepted by the Codex model cache', () => {\n assert.deepEqual(\n normalizeReasoningLevels(['ultra', 'max', 'xhigh', 'high', 'medium', 'low']),\n ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'],\n );\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('Vertex AI OpenAI endpoints resolve as Google without probing', async () => {\n let fetchCalls = 0;\n const result = await resolveProvider({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n fetchImpl: async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n },\n });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'canonical-url');\n assert.equal(fetchCalls, 0);\n});\n\ntest('Google provider aliases resolve explicitly without probing', async () => {\n let fetches = 0;\n const fetchImpl = async () => {\n fetches += 1;\n throw new Error('must not fetch');\n };\n\n for (const provider of ['aistudio', 'gemini', 'vertexai', 'vertex-ai']) {\n const result = await resolveProvider({ provider, fetchImpl });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetches, 0);\n});\n\ntest('Vertex Google discovery classifies only explicitly supplied Gemini models', async () => {\n const result = await google.discover({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n suppliedModels: ['google/gemini-2.5-flash', 'google/gemini-3.1-flash-image'],\n fetchImpl: async () => {\n throw new Error('Vertex discovery must not call the Developer API catalog');\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'google/gemini-2.5-flash',\n 'google/gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.complete, false);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching strips provider authentication headers on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({\n url: String(url),\n apiKey: options.headers['x-api-key'],\n version: options.headers['anthropic-version'],\n });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"data\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://api.anthropic.com/v1/models',\n provider: 'anthropic',\n authHeaders: {\n 'x-api-key': 'anthropic-secret',\n 'anthropic-version': '2023-06-01',\n },\n fetchImpl,\n });\n\n assert.deepEqual(result, { data: [] });\n assert.deepEqual(calls, [\n {\n url: 'https://api.anthropic.com/v1/models',\n apiKey: 'anthropic-secret',\n version: '2023-06-01',\n },\n {\n url: 'https://cdn.example/catalog.json',\n apiKey: undefined,\n version: undefined,\n },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return { models: [model], origin: 'live', complete: true };\n });\n assert.equal(first.state, 'refreshed');\n assert.equal(first.origin, 'live');\n assert.equal(first.complete, true);\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(fresh.origin, 'live');\n assert.equal(fresh.complete, true);\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.state, 'stale');\n assert.equal(stale.origin, 'live');\n assert.equal(stale.complete, true);\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assertPrivateDirectoryMode(path.join(cacheDir, 'nvidia'));\n assertPrivateFileMode(path.join(cacheDir, 'nvidia', files[0]));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, ['https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json']);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.slice(0, 2).map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n reasoning: {\n supported_efforts: ['xhigh', 'high', 'medium', 'low', 'none'],\n default_effort: 'medium',\n default_enabled: false,\n supports_max_tokens: true,\n mandatory: false,\n },\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, ['none', 'low', 'medium', 'high', 'xhigh']);\n assert.equal(rich.defaultReasoningLevel, 'medium');\n assert.equal(rich.reasoningDefaultEnabled, false);\n assert.equal(rich.reasoningSupportsMaxTokens, true);\n assert.equal(rich.reasoningMandatory, false);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n defaultReasoningLevel: 'provider-catalog',\n reasoningDefaultEnabled: 'provider-catalog',\n reasoningSupportsMaxTokens: 'provider-catalog',\n reasoningMandatory: 'provider-catalog',\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its complete owned snapshot', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.models.length, 345);\n assert.ok(result.models.some((model) => model.id === 'openrouter/auto'));\n assert.ok(result.models.some((model) => model.id === 'moonshotai/kimi-k2.6'));\n assert.equal(result.fallback.state, 'bundled');\n});\n\ntest('OpenRouter reasoning metadata distinguishes all-efforts from no exposed effort selector', () => {\n const allEfforts = openrouter.parseRow({\n id: 'vendor/all-efforts',\n architecture: { modality: 'text->text' },\n reasoning: {\n supported_efforts: null,\n default_effort: 'medium',\n default_enabled: true,\n mandatory: false,\n },\n });\n assert.deepEqual(allEfforts.reasoningLevels, [\n 'none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max',\n ]);\n assert.equal(allEfforts.defaultReasoningLevel, 'medium');\n\n const noSelector = openrouter.parseRow({\n id: 'vendor/no-selector',\n architecture: { modality: 'text->text' },\n reasoning: {\n default_enabled: true,\n mandatory: true,\n },\n });\n assert.equal(noSelector.reasoning, true);\n assert.equal(noSelector.reasoningLevels, null);\n assert.equal(noSelector.defaultReasoningLevel, null);\n assert.equal(noSelector.reasoningDefaultEnabled, true);\n assert.equal(noSelector.reasoningMandatory, true);\n});\n\ntest('Anthropic discovery enriches exact models from official compatibility documentation', () => {\n const model = anthropic.parseRow({\n id: 'claude-sonnet-5',\n type: 'model',\n display_name: 'Claude Sonnet 5',\n created_at: '2026-07-01T00:00:00Z',\n max_input_tokens: 1000000,\n max_tokens: 128000,\n capabilities: {\n image_input: { supported: true },\n thinking: {\n supported: true,\n types: {\n adaptive: { supported: true },\n enabled: { supported: true },\n },\n },\n effort: {\n supported: true,\n low: { supported: true },\n medium: { supported: true },\n high: { supported: true },\n xhigh: { supported: false },\n max: { supported: true },\n },\n future_capability: { supported: true },\n },\n });\n\n assert.deepEqual(model, {\n id: 'claude-sonnet-5',\n displayName: 'Claude Sonnet 5',\n contextWindow: 1000000,\n maxOutputTokens: 128000,\n inputModalities: ['text', 'image'],\n outputModalities: ['text'],\n reasoning: true,\n reasoningLevels: ['low', 'medium', 'high', 'max'],\n defaultReasoningLevel: 'high',\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: true,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n defaultReasoningLevel: 'provider-catalog',\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: 'provider-catalog',\n },\n providerMetadata: {\n createdAt: '2026-07-01T00:00:00Z',\n type: 'model',\n },\n source: 'anthropic-catalog',\n });\n});\n\ntest('Anthropic documentation enrichment does not guess capabilities for unknown future ids', () => {\n const model = anthropic.parseRow({\n id: 'claude-future-example',\n type: 'model',\n display_name: 'Claude Future Example',\n max_input_tokens: 1000000,\n max_tokens: 128000,\n capabilities: {},\n });\n\n assert.equal(model.inputModalities, null);\n assert.equal(model.outputModalities, null);\n assert.equal(model.reasoningLevels, null);\n assert.equal(model.defaultReasoningLevel, null);\n assert.equal(model.toolCalling, null);\n});\n\ntest('Anthropic discovery authenticates and follows model pagination in provider order', async () => {\n const calls = [];\n const pages = [\n {\n data: [\n { id: 'claude-first', type: 'model', display_name: 'Claude First' },\n { id: 'claude-shared', type: 'model', display_name: 'Claude Shared' },\n ],\n first_id: 'claude-first',\n last_id: 'claude-shared',\n has_more: true,\n },\n {\n data: [\n { id: 'claude-shared', type: 'model', display_name: 'Duplicate' },\n { id: 'claude-last', type: 'model', display_name: 'Claude Last' },\n ],\n first_id: 'claude-shared',\n last_id: 'claude-last',\n has_more: false,\n },\n ];\n const result = await anthropic.discover({\n apiKey: 'anthropic-secret',\n fetchImpl: async (url, options) => {\n calls.push({\n url: String(url),\n apiKey: options.headers['x-api-key'],\n version: options.headers['anthropic-version'],\n });\n return new Response(JSON.stringify(pages[calls.length - 1]));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'claude-first',\n 'claude-shared',\n 'claude-last',\n ]);\n assert.equal(result.origin, 'live');\n assert.equal(result.complete, true);\n assert.deepEqual(calls, [\n {\n url: 'https://api.anthropic.com/v1/models?limit=1000',\n apiKey: 'anthropic-secret',\n version: '2023-06-01',\n },\n {\n url: 'https://api.anthropic.com/v1/models?limit=1000&after_id=claude-shared',\n apiKey: 'anthropic-secret',\n version: '2023-06-01',\n },\n ]);\n});\n\ntest('public Anthropic discovery enriches documented metadata in an existing fresh cache', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'anthropic-model-cache-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const cachedModel = {\n ...normalizeSuppliedModels(['claude-sonnet-5'])[0],\n displayName: 'Claude Sonnet 5',\n contextWindow: 1000000,\n maxOutputTokens: 128000,\n inputModalities: ['text', 'image'],\n reasoning: true,\n reasoningLevels: ['low', 'medium', 'high', 'xhigh', 'max'],\n metadataSources: {\n ...normalizeSuppliedModels(['claude-sonnet-5'])[0].metadataSources,\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n },\n source: 'anthropic-catalog',\n };\n const cacheOptions = {\n provider: 'anthropic',\n endpoint: anthropic.ENDPOINT,\n apiKey: 'anthropic-secret',\n cacheDir,\n };\n writeCache(\n cacheOptions,\n cacheIdentity(cacheOptions),\n [cachedModel],\n 1000,\n { origin: 'live', complete: true },\n );\n\n const result = await discoverModels({\n provider: 'anthropic',\n baseUrl: anthropic.BASE_URL,\n apiKey: 'anthropic-secret',\n cacheDir,\n now: () => 1001,\n fetchImpl: async () => {\n throw new Error('fresh cache must avoid network access');\n },\n });\n\n assert.equal(result.cache.state, 'fresh');\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.equal(result.models[0].defaultReasoningLevel, 'high');\n assert.equal(result.models[0].toolCalling, true);\n});\n\ntest('Anthropic discovery rejects cursor loops and falls back to its bundled catalog', async () => {\n let calls = 0;\n const result = await anthropic.discover({\n apiKey: 'anthropic-secret',\n fetchImpl: async () => {\n calls += 1;\n return new Response(JSON.stringify({\n data: [{ id: `claude-page-${calls}`, type: 'model' }],\n last_id: 'repeated-cursor',\n has_more: true,\n }));\n },\n });\n\n assert.equal(calls, 2);\n assert.equal(result.origin, 'bundled');\n assert.equal(result.complete, false);\n assert.equal(result.fallback.state, 'bundled');\n assert.ok(result.models.length > 0);\n});\n\ntest('OpenAI discovery preserves provider metadata and leaves unknown capabilities unset', () => {\n const model = openai.parseRow({\n id: 'gpt-example',\n object: 'model',\n created: 1785196800,\n owned_by: 'openai',\n });\n\n assert.deepEqual(model, {\n id: 'gpt-example',\n displayName: 'gpt-example',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n providerMetadata: {\n created: 1785196800,\n object: 'model',\n ownedBy: 'openai',\n },\n source: 'openai-catalog',\n });\n});\n\ntest('OpenAI discovery excludes embedding models and retains every other purpose in provider order', async () => {\n const ids = [\n 'gpt-example',\n 'text-embedding-example',\n 'ft:text-embedding-example:organization:suffix:id',\n 'vendor/embeddings-v2',\n 'gpt-image-example',\n 'tts-example',\n 'omni-moderation-example',\n 'ft:gpt-example:organization:suffix:id',\n 'embedded-knowledge-gpt-example',\n ];\n const calls = [];\n const result = await openai.discover({\n apiKey: 'openai-secret',\n fetchImpl: async (url, options) => {\n calls.push({\n url: String(url),\n authorization: options.headers.Authorization,\n });\n return new Response(JSON.stringify({\n object: 'list',\n data: ids.concat('gpt-example').map((id) => ({\n id,\n object: 'model',\n created: 1785196800,\n owned_by: 'openai',\n })),\n }));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gpt-example',\n 'gpt-image-example',\n 'tts-example',\n 'omni-moderation-example',\n 'ft:gpt-example:organization:suffix:id',\n 'embedded-knowledge-gpt-example',\n ]);\n assert.equal(result.origin, 'live');\n assert.equal(result.complete, true);\n assert.deepEqual(calls, [{\n url: 'https://api.openai.com/v1/models',\n authorization: 'Bearer openai-secret',\n }]);\n});\n\ntest('OpenAI discovery falls back to its bundled Codex model-cache catalog', async () => {\n const result = await openai.discover({\n apiKey: 'openai-secret',\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.origin, 'bundled');\n assert.equal(result.complete, false);\n assert.equal(result.fallback.state, 'bundled');\n assert.ok(result.models.some((model) => model.id === 'gpt-5.6-sol'));\n assert.ok(result.models.every((model) => !model.id.includes('embedding')));\n});\n\ntest('public OpenAI discovery filters embedding rows from an existing fresh cache', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openai-model-cache-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const cacheOptions = {\n provider: 'openai',\n endpoint: openai.ENDPOINT,\n apiKey: 'openai-secret',\n cacheDir,\n };\n writeCache(\n cacheOptions,\n cacheIdentity(cacheOptions),\n [\n openai.parseRow({ id: 'gpt-example' }),\n openai.parseRow({ id: 'text-embedding-example' }),\n ],\n 1000,\n { origin: 'live', complete: true },\n );\n\n const result = await discoverModels({\n provider: 'openai',\n baseUrl: openai.BASE_URL,\n apiKey: 'openai-secret',\n cacheDir,\n now: () => 1001,\n fetchImpl: async () => {\n throw new Error('fresh cache must avoid network access');\n },\n });\n\n assert.equal(result.cache.state, 'fresh');\n assert.deepEqual(result.models.map((model) => model.id), ['gpt-example']);\n});\n\ntest('Anthropic and OpenAI treat empty successful inventories as bundled fallbacks', async () => {\n const anthropicResult = await anthropic.discover({\n fetchImpl: async () => new Response(JSON.stringify({\n data: [],\n has_more: false,\n })),\n });\n const openaiResult = await openai.discover({\n fetchImpl: async () => new Response(JSON.stringify({\n object: 'list',\n data: [],\n })),\n });\n\n assert.equal(anthropicResult.origin, 'bundled');\n assert.equal(anthropicResult.fallback.state, 'bundled');\n assert.equal(openaiResult.origin, 'bundled');\n assert.equal(openaiResult.fallback.state, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n {\n name: 'command-a-plus-05-2026',\n is_deprecated: false,\n features: ['reasoning', 'vision', 'tools'],\n },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 436000);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n assert.equal(result.models[0].metadataSources.reasoning, 'provider-catalog');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches exact live ids from the owned snapshot without metadata network calls', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-owned-enrich-'));\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-a-plus-05-2026' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command A+');\n assert.equal(result.models[0].contextWindow, 436000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: null,\n expectedSource: null,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n expectedSource: 'provider-catalog',\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-v4-pro',\n expectedContext: 1048576,\n expectedSource: 'openrouter-catalog',\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, entry.expectedSource);\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('a provider without an owned cache rejects a malformed successful payload', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n await assert.rejects(zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async () => new Response('{\"unexpected\":true}'),\n }), /model list/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async () => new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] })),\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cache.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery classifies generateContent Gemini image models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/gemini-3.1-flash-image',\n displayName: 'Gemini 3.1 Flash Image',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 65536,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gemini-3.1-pro',\n 'gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('xAI compatibility filtering requires no separate metadata request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-owned-filter-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, xai.ENDPOINT);\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.deepEqual(result.warnings, []);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('xAI discovery enriches sparse live rows with exact bundled modalities', async () => {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n fetchImpl: async () => new Response(JSON.stringify({\n data: [\n { id: 'grok-4.5' },\n { id: 'grok-4.20-0309-reasoning' },\n { id: 'grok-imagine-image' },\n { id: 'grok-imagine-video-1.5' },\n ],\n })),\n });\n\n assert.deepEqual(result.models.map((model) => [\n model.id,\n model.inputModalities,\n model.outputModalities,\n model.reasoningLevels,\n model.defaultReasoningLevel,\n ]), [\n ['grok-4.5', ['text', 'image'], ['text'], ['low', 'medium', 'high'], 'high'],\n ['grok-4.20-0309-reasoning', ['text', 'image'], ['text'], null, null],\n ['grok-imagine-image', ['text', 'image'], ['image'], null, null],\n ['grok-imagine-video-1.5', ['image'], ['video'], null, null],\n ]);\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n defaultReasoningLevel: 'HIGH',\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.defaultReasoningLevel, 'high');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(model.metadataSources.defaultReasoningLevel, 'provider-catalog');\n});\n\ntest('xAI discovery filters unsupported multi-agent models locally', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) =>\n model.id.endsWith(':cloud') || /^gemma4:[^:]+-cloud$/u.test(model.id)));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery reads its cloud candidates without a catalog network request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-local-snapshot-'));\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama live discovery retains cloud enrichment but displays the exact model id', async () => {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'gemma4:31b-cloud' }] },\n fetchImpl: async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'gemma4:31b-cloud');\n return new Response(JSON.stringify({\n model_info: { 'gemma4.context_length': 262144 },\n capabilities: ['completion', 'thinking', 'tools', 'vision'],\n }));\n },\n });\n\n const gemma4 = result.models.find((model) => model.id === 'gemma4:31b-cloud');\n assert.equal(gemma4.displayName, 'gemma4:31b-cloud');\n assert.deepEqual(gemma4.reasoningLevels, ['none', 'low', 'medium', 'high', 'max']);\n assert.equal(gemma4.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(gemma4.contextWindow, 262144);\n assert.deepEqual(gemma4.inputModalities, ['text', 'image']);\n assert.ok(result.models.every((model) => model.displayName === model.id));\n});\n\ntest('Ollama live discovery applies reasoning controls to the full Gemma 4 family', async () => {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: {\n models: [\n { name: 'gemma4:e2b' },\n { name: 'gemma4:12b-it-q4_K_M' },\n { name: 'gemma4:26b-a4b-it-q8_0' },\n ],\n },\n fetchImpl: async (_url, options) => {\n const id = JSON.parse(options.body).name;\n return new Response(JSON.stringify({\n model_info: { 'gemma4.context_length': id === 'gemma4:e2b' ? 131072 : 262144 },\n capabilities: ['completion', 'thinking', 'tools', 'vision'],\n }));\n },\n });\n\n for (const id of [\n 'gemma4:e2b',\n 'gemma4:12b-it-q4_K_M',\n 'gemma4:26b-a4b-it-q8_0',\n ]) {\n const model = result.models.find((entry) => entry.id === id);\n assert.deepEqual(model.reasoningLevels, ['none', 'low', 'medium', 'high', 'max']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cache.state, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cache.state, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.equal(refreshed.models[0].id, 'nvidia/featured');\n assert.equal(refreshed.models.at(-1).id, 'private/model');\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cache.state, 'fresh');\n assert.equal(calls, 1);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n inventoryComplete: true,\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/provider-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "fc8d84167d6010edfc207fcf022cd020c5e1b33c": {"t": 1785758809.5856051, "n": 61913, "h": "40aa2ea87643b0a2", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\nconst { assertPrivateDirectoryMode, assertPrivateFileMode } = require('./helpers/file-mode');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeReasoningLevels,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst {\n cacheIdentity,\n withProviderCache,\n writeCache,\n} = require('../src/model-discovery/file-cache');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst anthropic = require('../src/model-discovery/providers/anthropic');\nconst openai = require('../src/model-discovery/providers/openai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('reasoning normalization preserves every effort accepted by the Codex model cache', () => {\n assert.deepEqual(\n normalizeReasoningLevels(['ultra', 'max', 'xhigh', 'high', 'medium', 'low']),\n ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'],\n );\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('Vertex AI OpenAI endpoints resolve as Google without probing', async () => {\n let fetchCalls = 0;\n const result = await resolveProvider({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n fetchImpl: async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n },\n });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'canonical-url');\n assert.equal(fetchCalls, 0);\n});\n\ntest('Google provider aliases resolve explicitly without probing', async () => {\n let fetches = 0;\n const fetchImpl = async () => {\n fetches += 1;\n throw new Error('must not fetch');\n };\n\n for (const provider of ['aistudio', 'gemini', 'vertexai', 'vertex-ai']) {\n const result = await resolveProvider({ provider, fetchImpl });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetches, 0);\n});\n\ntest('Vertex Google discovery classifies only explicitly supplied Gemini models', async () => {\n const result = await google.discover({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n suppliedModels: ['google/gemini-2.5-flash', 'google/gemini-3.1-flash-image'],\n fetchImpl: async () => {\n throw new Error('Vertex discovery must not call the Developer API catalog');\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'google/gemini-2.5-flash',\n 'google/gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.complete, false);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching strips provider authentication headers on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({\n url: String(url),\n apiKey: options.headers['x-api-key'],\n version: options.headers['anthropic-version'],\n });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"data\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://api.anthropic.com/v1/models',\n provider: 'anthropic',\n authHeaders: {\n 'x-api-key': 'anthropic-secret',\n 'anthropic-version': '2023-06-01',\n },\n fetchImpl,\n });\n\n assert.deepEqual(result, { data: [] });\n assert.deepEqual(calls, [\n {\n url: 'https://api.anthropic.com/v1/models',\n apiKey: 'anthropic-secret',\n version: '2023-06-01',\n },\n {\n url: 'https://cdn.example/catalog.json',\n apiKey: undefined,\n version: undefined,\n },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return { models: [model], origin: 'live', complete: true };\n });\n assert.equal(first.state, 'refreshed');\n assert.equal(first.origin, 'live');\n assert.equal(first.complete, true);\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(fresh.origin, 'live');\n assert.equal(fresh.complete, true);\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.state, 'stale');\n assert.equal(stale.origin, 'live');\n assert.equal(stale.complete, true);\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assertPrivateDirectoryMode(path.join(cacheDir, 'nvidia'));\n assertPrivateFileMode(path.join(cacheDir, 'nvidia', files[0]));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, ['https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json']);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.slice(0, 2).map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n reasoning: {\n supported_efforts: ['xhigh', 'high', 'medium', 'low', 'none'],\n default_effort: 'medium',\n default_enabled: false,\n supports_max_tokens: true,\n mandatory: false,\n },\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, ['none', 'low', 'medium', 'high', 'xhigh']);\n assert.equal(rich.defaultReasoningLevel, 'medium');\n assert.equal(rich.reasoningDefaultEnabled, false);\n assert.equal(rich.reasoningSupportsMaxTokens, true);\n assert.equal(rich.reasoningMandatory, false);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n defaultReasoningLevel: 'provider-catalog',\n reasoningDefaultEnabled: 'provider-catalog',\n reasoningSupportsMaxTokens: 'provider-catalog',\n reasoningMandatory: 'provider-catalog',\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its complete owned snapshot', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.models.length, 345);\n assert.ok(result.models.some((model) => model.id === 'openrouter/auto'));\n assert.ok(result.models.some((model) => model.id === 'moonshotai/kimi-k2.6'));\n assert.equal(result.fallback.state, 'bundled');\n});\n\ntest('OpenRouter reasoning metadata distinguishes all-efforts from no exposed effort selector', () => {\n const allEfforts = openrouter.parseRow({\n id: 'vendor/all-efforts',\n architecture: { modality: 'text->text' },\n reasoning: {\n supported_efforts: null,\n default_effort: 'medium',\n default_enabled: true,\n mandatory: false,\n },\n });\n assert.deepEqual(allEfforts.reasoningLevels, [\n 'none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max',\n ]);\n assert.equal(allEfforts.defaultReasoningLevel, 'medium');\n\n const noSelector = openrouter.parseRow({\n id: 'vendor/no-selector',\n architecture: { modality: 'text->text' },\n reasoning: {\n default_enabled: true,\n mandatory: true,\n },\n });\n assert.equal(noSelector.reasoning, true);\n assert.equal(noSelector.reasoningLevels, null);\n assert.equal(noSelector.defaultReasoningLevel, null);\n assert.equal(noSelector.reasoningDefaultEnabled, true);\n assert.equal(noSelector.reasoningMandatory, true);\n});\n\ntest('Anthropic discovery maps documented model capabilities without guessing', () => {\n const model = anthropic.parseRow({\n id: 'claude-sonnet-example',\n type: 'model',\n display_name: 'Claude Sonnet Example',\n created_at: '2026-07-01T00:00:00Z',\n max_input_tokens: 1000000,\n max_tokens: 128000,\n capabilities: {\n image_input: { supported: true },\n thinking: {\n supported: true,\n types: {\n adaptive: { supported: true },\n enabled: { supported: true },\n },\n },\n effort: {\n supported: true,\n low: { supported: true },\n medium: { supported: true },\n high: { supported: true },\n xhigh: { supported: false },\n max: { supported: true },\n },\n tool_use: { supported: true },\n future_capability: { supported: true },\n },\n });\n\n assert.deepEqual(model, {\n id: 'claude-sonnet-example',\n displayName: 'Claude Sonnet Example',\n contextWindow: 1000000,\n maxOutputTokens: 128000,\n inputModalities: ['text', 'image'],\n outputModalities: null,\n reasoning: true,\n reasoningLevels: ['low', 'medium', 'high', 'max'],\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: true,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: null,\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: 'provider-catalog',\n },\n providerMetadata: {\n createdAt: '2026-07-01T00:00:00Z',\n type: 'model',\n },\n source: 'anthropic-catalog',\n });\n});\n\ntest('Anthropic discovery authenticates and follows model pagination in provider order', async () => {\n const calls = [];\n const pages = [\n {\n data: [\n { id: 'claude-first', type: 'model', display_name: 'Claude First' },\n { id: 'claude-shared', type: 'model', display_name: 'Claude Shared' },\n ],\n first_id: 'claude-first',\n last_id: 'claude-shared',\n has_more: true,\n },\n {\n data: [\n { id: 'claude-shared', type: 'model', display_name: 'Duplicate' },\n { id: 'claude-last', type: 'model', display_name: 'Claude Last' },\n ],\n first_id: 'claude-shared',\n last_id: 'claude-last',\n has_more: false,\n },\n ];\n const result = await anthropic.discover({\n apiKey: 'anthropic-secret',\n fetchImpl: async (url, options) => {\n calls.push({\n url: String(url),\n apiKey: options.headers['x-api-key'],\n version: options.headers['anthropic-version'],\n });\n return new Response(JSON.stringify(pages[calls.length - 1]));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'claude-first',\n 'claude-shared',\n 'claude-last',\n ]);\n assert.equal(result.origin, 'live');\n assert.equal(result.complete, true);\n assert.deepEqual(calls, [\n {\n url: 'https://api.anthropic.com/v1/models?limit=1000',\n apiKey: 'anthropic-secret',\n version: '2023-06-01',\n },\n {\n url: 'https://api.anthropic.com/v1/models?limit=1000&after_id=claude-shared',\n apiKey: 'anthropic-secret',\n version: '2023-06-01',\n },\n ]);\n});\n\ntest('Anthropic discovery rejects cursor loops and falls back to its bundled catalog', async () => {\n let calls = 0;\n const result = await anthropic.discover({\n apiKey: 'anthropic-secret',\n fetchImpl: async () => {\n calls += 1;\n return new Response(JSON.stringify({\n data: [{ id: `claude-page-${calls}`, type: 'model' }],\n last_id: 'repeated-cursor',\n has_more: true,\n }));\n },\n });\n\n assert.equal(calls, 2);\n assert.equal(result.origin, 'bundled');\n assert.equal(result.complete, false);\n assert.equal(result.fallback.state, 'bundled');\n assert.ok(result.models.length > 0);\n});\n\ntest('OpenAI discovery preserves provider metadata and leaves unknown capabilities unset', () => {\n const model = openai.parseRow({\n id: 'gpt-example',\n object: 'model',\n created: 1785196800,\n owned_by: 'openai',\n });\n\n assert.deepEqual(model, {\n id: 'gpt-example',\n displayName: 'gpt-example',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n providerMetadata: {\n created: 1785196800,\n object: 'model',\n ownedBy: 'openai',\n },\n source: 'openai-catalog',\n });\n});\n\ntest('OpenAI discovery excludes embedding models and retains every other purpose in provider order', async () => {\n const ids = [\n 'gpt-example',\n 'text-embedding-example',\n 'ft:text-embedding-example:organization:suffix:id',\n 'vendor/embeddings-v2',\n 'gpt-image-example',\n 'tts-example',\n 'omni-moderation-example',\n 'ft:gpt-example:organization:suffix:id',\n 'embedded-knowledge-gpt-example',\n ];\n const calls = [];\n const result = await openai.discover({\n apiKey: 'openai-secret',\n fetchImpl: async (url, options) => {\n calls.push({\n url: String(url),\n authorization: options.headers.Authorization,\n });\n return new Response(JSON.stringify({\n object: 'list',\n data: ids.concat('gpt-example').map((id) => ({\n id,\n object: 'model',\n created: 1785196800,\n owned_by: 'openai',\n })),\n }));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gpt-example',\n 'gpt-image-example',\n 'tts-example',\n 'omni-moderation-example',\n 'ft:gpt-example:organization:suffix:id',\n 'embedded-knowledge-gpt-example',\n ]);\n assert.equal(result.origin, 'live');\n assert.equal(result.complete, true);\n assert.deepEqual(calls, [{\n url: 'https://api.openai.com/v1/models',\n authorization: 'Bearer openai-secret',\n }]);\n});\n\ntest('OpenAI discovery falls back to its bundled Codex model-cache catalog', async () => {\n const result = await openai.discover({\n apiKey: 'openai-secret',\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.origin, 'bundled');\n assert.equal(result.complete, false);\n assert.equal(result.fallback.state, 'bundled');\n assert.ok(result.models.some((model) => model.id === 'gpt-5.6-sol'));\n assert.ok(result.models.every((model) => !model.id.includes('embedding')));\n});\n\ntest('public OpenAI discovery filters embedding rows from an existing fresh cache', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openai-model-cache-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const cacheOptions = {\n provider: 'openai',\n endpoint: openai.ENDPOINT,\n apiKey: 'openai-secret',\n cacheDir,\n };\n writeCache(\n cacheOptions,\n cacheIdentity(cacheOptions),\n [\n openai.parseRow({ id: 'gpt-example' }),\n openai.parseRow({ id: 'text-embedding-example' }),\n ],\n 1000,\n { origin: 'live', complete: true },\n );\n\n const result = await discoverModels({\n provider: 'openai',\n baseUrl: openai.BASE_URL,\n apiKey: 'openai-secret',\n cacheDir,\n now: () => 1001,\n fetchImpl: async () => {\n throw new Error('fresh cache must avoid network access');\n },\n });\n\n assert.equal(result.cache.state, 'fresh');\n assert.deepEqual(result.models.map((model) => model.id), ['gpt-example']);\n});\n\ntest('Anthropic and OpenAI treat empty successful inventories as bundled fallbacks', async () => {\n const anthropicResult = await anthropic.discover({\n fetchImpl: async () => new Response(JSON.stringify({\n data: [],\n has_more: false,\n })),\n });\n const openaiResult = await openai.discover({\n fetchImpl: async () => new Response(JSON.stringify({\n object: 'list',\n data: [],\n })),\n });\n\n assert.equal(anthropicResult.origin, 'bundled');\n assert.equal(anthropicResult.fallback.state, 'bundled');\n assert.equal(openaiResult.origin, 'bundled');\n assert.equal(openaiResult.fallback.state, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n {\n name: 'command-a-plus-05-2026',\n is_deprecated: false,\n features: ['reasoning', 'vision', 'tools'],\n },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 436000);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n assert.equal(result.models[0].metadataSources.reasoning, 'provider-catalog');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches exact live ids from the owned snapshot without metadata network calls', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-owned-enrich-'));\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-a-plus-05-2026' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command A+');\n assert.equal(result.models[0].contextWindow, 436000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: null,\n expectedSource: null,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n expectedSource: 'provider-catalog',\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-v4-pro',\n expectedContext: 1048576,\n expectedSource: 'openrouter-catalog',\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, entry.expectedSource);\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('a provider without an owned cache rejects a malformed successful payload', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n await assert.rejects(zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async () => new Response('{\"unexpected\":true}'),\n }), /model list/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async () => new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] })),\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cache.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery classifies generateContent Gemini image models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/gemini-3.1-flash-image',\n displayName: 'Gemini 3.1 Flash Image',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 65536,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gemini-3.1-pro',\n 'gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('xAI compatibility filtering requires no separate metadata request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-owned-filter-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, xai.ENDPOINT);\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.deepEqual(result.warnings, []);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('xAI discovery enriches sparse live rows with exact bundled modalities', async () => {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n fetchImpl: async () => new Response(JSON.stringify({\n data: [\n { id: 'grok-4.5' },\n { id: 'grok-4.20-0309-reasoning' },\n { id: 'grok-imagine-image' },\n { id: 'grok-imagine-video-1.5' },\n ],\n })),\n });\n\n assert.deepEqual(result.models.map((model) => [\n model.id,\n model.inputModalities,\n model.outputModalities,\n model.reasoningLevels,\n model.defaultReasoningLevel,\n ]), [\n ['grok-4.5', ['text', 'image'], ['text'], ['low', 'medium', 'high'], 'high'],\n ['grok-4.20-0309-reasoning', ['text', 'image'], ['text'], null, null],\n ['grok-imagine-image', ['text', 'image'], ['image'], null, null],\n ['grok-imagine-video-1.5', ['image'], ['video'], null, null],\n ]);\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n defaultReasoningLevel: 'HIGH',\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.defaultReasoningLevel, 'high');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(model.metadataSources.defaultReasoningLevel, 'provider-catalog');\n});\n\ntest('xAI discovery filters unsupported multi-agent models locally', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) =>\n model.id.endsWith(':cloud') || /^gemma4:[^:]+-cloud$/u.test(model.id)));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery reads its cloud candidates without a catalog network request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-local-snapshot-'));\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama live discovery retains cloud enrichment but displays the exact model id', async () => {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'gemma4:31b-cloud' }] },\n fetchImpl: async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'gemma4:31b-cloud');\n return new Response(JSON.stringify({\n model_info: { 'gemma4.context_length': 262144 },\n capabilities: ['completion', 'thinking', 'tools', 'vision'],\n }));\n },\n });\n\n const gemma4 = result.models.find((model) => model.id === 'gemma4:31b-cloud');\n assert.equal(gemma4.displayName, 'gemma4:31b-cloud');\n assert.deepEqual(gemma4.reasoningLevels, ['none', 'low', 'medium', 'high', 'max']);\n assert.equal(gemma4.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(gemma4.contextWindow, 262144);\n assert.deepEqual(gemma4.inputModalities, ['text', 'image']);\n assert.ok(result.models.every((model) => model.displayName === model.id));\n});\n\ntest('Ollama live discovery applies reasoning controls to the full Gemma 4 family', async () => {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: {\n models: [\n { name: 'gemma4:e2b' },\n { name: 'gemma4:12b-it-q4_K_M' },\n { name: 'gemma4:26b-a4b-it-q8_0' },\n ],\n },\n fetchImpl: async (_url, options) => {\n const id = JSON.parse(options.body).name;\n return new Response(JSON.stringify({\n model_info: { 'gemma4.context_length': id === 'gemma4:e2b' ? 131072 : 262144 },\n capabilities: ['completion', 'thinking', 'tools', 'vision'],\n }));\n },\n });\n\n for (const id of [\n 'gemma4:e2b',\n 'gemma4:12b-it-q4_K_M',\n 'gemma4:26b-a4b-it-q8_0',\n ]) {\n const model = result.models.find((entry) => entry.id === id);\n assert.deepEqual(model.reasoningLevels, ['none', 'low', 'medium', 'high', 'max']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cache.state, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cache.state, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.equal(refreshed.models[0].id, 'nvidia/featured');\n assert.equal(refreshed.models.at(-1).id, 'private/model');\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cache.state, 'fresh');\n assert.equal(calls, 1);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n inventoryComplete: true,\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/provider-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "6745d842778c429be9ce76fd04582ce1f52f215a": {"t": 1785758811.3002453, "n": 60556, "h": "e70cfa5905ceb723", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\nconst { assertPrivateDirectoryMode, assertPrivateFileMode } = require('./helpers/file-mode');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeReasoningLevels,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst anthropic = require('../src/model-discovery/providers/anthropic');\nconst openai = require('../src/model-discovery/providers/openai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('reasoning normalization preserves every effort accepted by the Codex model cache', () => {\n assert.deepEqual(\n normalizeReasoningLevels(['ultra', 'max', 'xhigh', 'high', 'medium', 'low']),\n ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'],\n );\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('Vertex AI OpenAI endpoints resolve as Google without probing', async () => {\n let fetchCalls = 0;\n const result = await resolveProvider({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n fetchImpl: async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n },\n });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'canonical-url');\n assert.equal(fetchCalls, 0);\n});\n\ntest('Google provider aliases resolve explicitly without probing', async () => {\n let fetches = 0;\n const fetchImpl = async () => {\n fetches += 1;\n throw new Error('must not fetch');\n };\n\n for (const provider of ['aistudio', 'gemini', 'vertexai', 'vertex-ai']) {\n const result = await resolveProvider({ provider, fetchImpl });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetches, 0);\n});\n\ntest('Vertex Google discovery classifies only explicitly supplied Gemini models', async () => {\n const result = await google.discover({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n suppliedModels: ['google/gemini-2.5-flash', 'google/gemini-3.1-flash-image'],\n fetchImpl: async () => {\n throw new Error('Vertex discovery must not call the Developer API catalog');\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'google/gemini-2.5-flash',\n 'google/gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.complete, false);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching strips provider authentication headers on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({\n url: String(url),\n apiKey: options.headers['x-api-key'],\n version: options.headers['anthropic-version'],\n });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"data\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://api.anthropic.com/v1/models',\n provider: 'anthropic',\n authHeaders: {\n 'x-api-key': 'anthropic-secret',\n 'anthropic-version': '2023-06-01',\n },\n fetchImpl,\n });\n\n assert.deepEqual(result, { data: [] });\n assert.deepEqual(calls, [\n {\n url: 'https://api.anthropic.com/v1/models',\n apiKey: 'anthropic-secret',\n version: '2023-06-01',\n },\n {\n url: 'https://cdn.example/catalog.json',\n apiKey: undefined,\n version: undefined,\n },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return { models: [model], origin: 'live', complete: true };\n });\n assert.equal(first.state, 'refreshed');\n assert.equal(first.origin, 'live');\n assert.equal(first.complete, true);\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(fresh.origin, 'live');\n assert.equal(fresh.complete, true);\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.state, 'stale');\n assert.equal(stale.origin, 'live');\n assert.equal(stale.complete, true);\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assertPrivateDirectoryMode(path.join(cacheDir, 'nvidia'));\n assertPrivateFileMode(path.join(cacheDir, 'nvidia', files[0]));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, ['https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json']);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.slice(0, 2).map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n reasoning: {\n supported_efforts: ['xhigh', 'high', 'medium', 'low', 'none'],\n default_effort: 'medium',\n default_enabled: false,\n supports_max_tokens: true,\n mandatory: false,\n },\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, ['none', 'low', 'medium', 'high', 'xhigh']);\n assert.equal(rich.defaultReasoningLevel, 'medium');\n assert.equal(rich.reasoningDefaultEnabled, false);\n assert.equal(rich.reasoningSupportsMaxTokens, true);\n assert.equal(rich.reasoningMandatory, false);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n defaultReasoningLevel: 'provider-catalog',\n reasoningDefaultEnabled: 'provider-catalog',\n reasoningSupportsMaxTokens: 'provider-catalog',\n reasoningMandatory: 'provider-catalog',\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its complete owned snapshot', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.models.length, 345);\n assert.ok(result.models.some((model) => model.id === 'openrouter/auto'));\n assert.ok(result.models.some((model) => model.id === 'moonshotai/kimi-k2.6'));\n assert.equal(result.fallback.state, 'bundled');\n});\n\ntest('OpenRouter reasoning metadata distinguishes all-efforts from no exposed effort selector', () => {\n const allEfforts = openrouter.parseRow({\n id: 'vendor/all-efforts',\n architecture: { modality: 'text->text' },\n reasoning: {\n supported_efforts: null,\n default_effort: 'medium',\n default_enabled: true,\n mandatory: false,\n },\n });\n assert.deepEqual(allEfforts.reasoningLevels, [\n 'none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max',\n ]);\n assert.equal(allEfforts.defaultReasoningLevel, 'medium');\n\n const noSelector = openrouter.parseRow({\n id: 'vendor/no-selector',\n architecture: { modality: 'text->text' },\n reasoning: {\n default_enabled: true,\n mandatory: true,\n },\n });\n assert.equal(noSelector.reasoning, true);\n assert.equal(noSelector.reasoningLevels, null);\n assert.equal(noSelector.defaultReasoningLevel, null);\n assert.equal(noSelector.reasoningDefaultEnabled, true);\n assert.equal(noSelector.reasoningMandatory, true);\n});\n\ntest('Anthropic discovery maps documented model capabilities without guessing', () => {\n const model = anthropic.parseRow({\n id: 'claude-sonnet-example',\n type: 'model',\n display_name: 'Claude Sonnet Example',\n created_at: '2026-07-01T00:00:00Z',\n max_input_tokens: 1000000,\n max_tokens: 128000,\n capabilities: {\n image_input: { supported: true },\n thinking: {\n supported: true,\n types: {\n adaptive: { supported: true },\n enabled: { supported: true },\n },\n },\n effort: {\n supported: true,\n low: { supported: true },\n medium: { supported: true },\n high: { supported: true },\n xhigh: { supported: false },\n max: { supported: true },\n },\n tool_use: { supported: true },\n future_capability: { supported: true },\n },\n });\n\n assert.deepEqual(model, {\n id: 'claude-sonnet-example',\n displayName: 'Claude Sonnet Example',\n contextWindow: 1000000,\n maxOutputTokens: 128000,\n inputModalities: ['text', 'image'],\n outputModalities: null,\n reasoning: true,\n reasoningLevels: ['low', 'medium', 'high', 'max'],\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: true,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: null,\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: 'provider-catalog',\n },\n providerMetadata: {\n createdAt: '2026-07-01T00:00:00Z',\n type: 'model',\n },\n source: 'anthropic-catalog',\n });\n});\n\ntest('Anthropic discovery authenticates and follows model pagination in provider order', async () => {\n const calls = [];\n const pages = [\n {\n data: [\n { id: 'claude-first', type: 'model', display_name: 'Claude First' },\n { id: 'claude-shared', type: 'model', display_name: 'Claude Shared' },\n ],\n first_id: 'claude-first',\n last_id: 'claude-shared',\n has_more: true,\n },\n {\n data: [\n { id: 'claude-shared', type: 'model', display_name: 'Duplicate' },\n { id: 'claude-last', type: 'model', display_name: 'Claude Last' },\n ],\n first_id: 'claude-shared',\n last_id: 'claude-last',\n has_more: false,\n },\n ];\n const result = await anthropic.discover({\n apiKey: 'anthropic-secret',\n fetchImpl: async (url, options) => {\n calls.push({\n url: String(url),\n apiKey: options.headers['x-api-key'],\n version: options.headers['anthropic-version'],\n });\n return new Response(JSON.stringify(pages[calls.length - 1]));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'claude-first',\n 'claude-shared',\n 'claude-last',\n ]);\n assert.equal(result.origin, 'live');\n assert.equal(result.complete, true);\n assert.deepEqual(calls, [\n {\n url: 'https://api.anthropic.com/v1/models?limit=1000',\n apiKey: 'anthropic-secret',\n version: '2023-06-01',\n },\n {\n url: 'https://api.anthropic.com/v1/models?limit=1000&after_id=claude-shared',\n apiKey: 'anthropic-secret',\n version: '2023-06-01',\n },\n ]);\n});\n\ntest('Anthropic discovery rejects cursor loops and falls back to its bundled catalog', async () => {\n let calls = 0;\n const result = await anthropic.discover({\n apiKey: 'anthropic-secret',\n fetchImpl: async () => {\n calls += 1;\n return new Response(JSON.stringify({\n data: [{ id: `claude-page-${calls}`, type: 'model' }],\n last_id: 'repeated-cursor',\n has_more: true,\n }));\n },\n });\n\n assert.equal(calls, 2);\n assert.equal(result.origin, 'bundled');\n assert.equal(result.complete, false);\n assert.equal(result.fallback.state, 'bundled');\n assert.ok(result.models.length > 0);\n});\n\ntest('OpenAI discovery preserves provider metadata and leaves unknown capabilities unset', () => {\n const model = openai.parseRow({\n id: 'gpt-example',\n object: 'model',\n created: 1785196800,\n owned_by: 'openai',\n });\n\n assert.deepEqual(model, {\n id: 'gpt-example',\n displayName: 'gpt-example',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n providerMetadata: {\n created: 1785196800,\n object: 'model',\n ownedBy: 'openai',\n },\n source: 'openai-catalog',\n });\n});\n\ntest('OpenAI discovery retains every model purpose in exact provider order', async () => {\n const ids = [\n 'gpt-example',\n 'text-embedding-example',\n 'gpt-image-example',\n 'tts-example',\n 'omni-moderation-example',\n 'ft:gpt-example:organization:suffix:id',\n ];\n const calls = [];\n const result = await openai.discover({\n apiKey: 'openai-secret',\n fetchImpl: async (url, options) => {\n calls.push({\n url: String(url),\n authorization: options.headers.Authorization,\n });\n return new Response(JSON.stringify({\n object: 'list',\n data: ids.concat('gpt-example').map((id) => ({\n id,\n object: 'model',\n created: 1785196800,\n owned_by: 'openai',\n })),\n }));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), ids);\n assert.equal(result.origin, 'live');\n assert.equal(result.complete, true);\n assert.deepEqual(calls, [{\n url: 'https://api.openai.com/v1/models',\n authorization: 'Bearer openai-secret',\n }]);\n});\n\ntest('OpenAI discovery falls back to its bundled complete-purpose catalog', async () => {\n const result = await openai.discover({\n apiKey: 'openai-secret',\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.origin, 'bundled');\n assert.equal(result.complete, false);\n assert.equal(result.fallback.state, 'bundled');\n assert.ok(result.models.some((model) => model.id.includes('embedding')));\n assert.ok(result.models.some((model) => model.id.includes('image')));\n});\n\ntest('Anthropic and OpenAI treat empty successful inventories as bundled fallbacks', async () => {\n const anthropicResult = await anthropic.discover({\n fetchImpl: async () => new Response(JSON.stringify({\n data: [],\n has_more: false,\n })),\n });\n const openaiResult = await openai.discover({\n fetchImpl: async () => new Response(JSON.stringify({\n object: 'list',\n data: [],\n })),\n });\n\n assert.equal(anthropicResult.origin, 'bundled');\n assert.equal(anthropicResult.fallback.state, 'bundled');\n assert.equal(openaiResult.origin, 'bundled');\n assert.equal(openaiResult.fallback.state, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n {\n name: 'command-a-plus-05-2026',\n is_deprecated: false,\n features: ['reasoning', 'vision', 'tools'],\n },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 436000);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n assert.equal(result.models[0].metadataSources.reasoning, 'provider-catalog');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches exact live ids from the owned snapshot without metadata network calls', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-owned-enrich-'));\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-a-plus-05-2026' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command A+');\n assert.equal(result.models[0].contextWindow, 436000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: null,\n expectedSource: null,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n expectedSource: 'provider-catalog',\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-v4-pro',\n expectedContext: 1048576,\n expectedSource: 'openrouter-catalog',\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, entry.expectedSource);\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('a provider without an owned cache rejects a malformed successful payload', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n await assert.rejects(zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async () => new Response('{\"unexpected\":true}'),\n }), /model list/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async () => new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] })),\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cache.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery classifies generateContent Gemini image models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/gemini-3.1-flash-image',\n displayName: 'Gemini 3.1 Flash Image',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 65536,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gemini-3.1-pro',\n 'gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('xAI compatibility filtering requires no separate metadata request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-owned-filter-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, xai.ENDPOINT);\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.deepEqual(result.warnings, []);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('xAI discovery enriches sparse live rows with exact bundled modalities', async () => {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n fetchImpl: async () => new Response(JSON.stringify({\n data: [\n { id: 'grok-4.5' },\n { id: 'grok-4.20-0309-reasoning' },\n { id: 'grok-imagine-image' },\n { id: 'grok-imagine-video-1.5' },\n ],\n })),\n });\n\n assert.deepEqual(result.models.map((model) => [\n model.id,\n model.inputModalities,\n model.outputModalities,\n model.reasoningLevels,\n model.defaultReasoningLevel,\n ]), [\n ['grok-4.5', ['text', 'image'], ['text'], ['low', 'medium', 'high'], 'high'],\n ['grok-4.20-0309-reasoning', ['text', 'image'], ['text'], null, null],\n ['grok-imagine-image', ['text', 'image'], ['image'], null, null],\n ['grok-imagine-video-1.5', ['image'], ['video'], null, null],\n ]);\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n defaultReasoningLevel: 'HIGH',\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.defaultReasoningLevel, 'high');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(model.metadataSources.defaultReasoningLevel, 'provider-catalog');\n});\n\ntest('xAI discovery filters unsupported multi-agent models locally', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) =>\n model.id.endsWith(':cloud') || /^gemma4:[^:]+-cloud$/u.test(model.id)));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery reads its cloud candidates without a catalog network request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-local-snapshot-'));\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama live discovery retains cloud enrichment but displays the exact model id', async () => {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'gemma4:31b-cloud' }] },\n fetchImpl: async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'gemma4:31b-cloud');\n return new Response(JSON.stringify({\n model_info: { 'gemma4.context_length': 262144 },\n capabilities: ['completion', 'thinking', 'tools', 'vision'],\n }));\n },\n });\n\n const gemma4 = result.models.find((model) => model.id === 'gemma4:31b-cloud');\n assert.equal(gemma4.displayName, 'gemma4:31b-cloud');\n assert.deepEqual(gemma4.reasoningLevels, ['none', 'low', 'medium', 'high', 'max']);\n assert.equal(gemma4.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(gemma4.contextWindow, 262144);\n assert.deepEqual(gemma4.inputModalities, ['text', 'image']);\n assert.ok(result.models.every((model) => model.displayName === model.id));\n});\n\ntest('Ollama live discovery applies reasoning controls to the full Gemma 4 family', async () => {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: {\n models: [\n { name: 'gemma4:e2b' },\n { name: 'gemma4:12b-it-q4_K_M' },\n { name: 'gemma4:26b-a4b-it-q8_0' },\n ],\n },\n fetchImpl: async (_url, options) => {\n const id = JSON.parse(options.body).name;\n return new Response(JSON.stringify({\n model_info: { 'gemma4.context_length': id === 'gemma4:e2b' ? 131072 : 262144 },\n capabilities: ['completion', 'thinking', 'tools', 'vision'],\n }));\n },\n });\n\n for (const id of [\n 'gemma4:e2b',\n 'gemma4:12b-it-q4_K_M',\n 'gemma4:26b-a4b-it-q8_0',\n ]) {\n const model = result.models.find((entry) => entry.id === id);\n assert.deepEqual(model.reasoningLevels, ['none', 'low', 'medium', 'high', 'max']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cache.state, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cache.state, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.equal(refreshed.models[0].id, 'nvidia/featured');\n assert.equal(refreshed.models.at(-1).id, 'private/model');\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cache.state, 'fresh');\n assert.equal(calls, 1);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n inventoryComplete: true,\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/provider-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "ced3c68250dd3dd83461a703c2e4eedb75d67558": {"t": 1785758812.8301744, "n": 51830, "h": "d2a738ceb341543f", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\nconst { assertPrivateDirectoryMode, assertPrivateFileMode } = require('./helpers/file-mode');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeReasoningLevels,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('reasoning normalization preserves every effort accepted by the Codex model cache', () => {\n assert.deepEqual(\n normalizeReasoningLevels(['ultra', 'max', 'xhigh', 'high', 'medium', 'low']),\n ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'],\n );\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('Vertex AI OpenAI endpoints resolve as Google without probing', async () => {\n let fetchCalls = 0;\n const result = await resolveProvider({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n fetchImpl: async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n },\n });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'canonical-url');\n assert.equal(fetchCalls, 0);\n});\n\ntest('Google provider aliases resolve explicitly without probing', async () => {\n let fetches = 0;\n const fetchImpl = async () => {\n fetches += 1;\n throw new Error('must not fetch');\n };\n\n for (const provider of ['aistudio', 'gemini', 'vertexai', 'vertex-ai']) {\n const result = await resolveProvider({ provider, fetchImpl });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetches, 0);\n});\n\ntest('Vertex Google discovery classifies only explicitly supplied Gemini models', async () => {\n const result = await google.discover({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n suppliedModels: ['google/gemini-2.5-flash', 'google/gemini-3.1-flash-image'],\n fetchImpl: async () => {\n throw new Error('Vertex discovery must not call the Developer API catalog');\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'google/gemini-2.5-flash',\n 'google/gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.complete, false);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return { models: [model], origin: 'live', complete: true };\n });\n assert.equal(first.state, 'refreshed');\n assert.equal(first.origin, 'live');\n assert.equal(first.complete, true);\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(fresh.origin, 'live');\n assert.equal(fresh.complete, true);\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.state, 'stale');\n assert.equal(stale.origin, 'live');\n assert.equal(stale.complete, true);\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assertPrivateDirectoryMode(path.join(cacheDir, 'nvidia'));\n assertPrivateFileMode(path.join(cacheDir, 'nvidia', files[0]));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, ['https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json']);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.slice(0, 2).map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n reasoning: {\n supported_efforts: ['xhigh', 'high', 'medium', 'low', 'none'],\n default_effort: 'medium',\n default_enabled: false,\n supports_max_tokens: true,\n mandatory: false,\n },\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, ['none', 'low', 'medium', 'high', 'xhigh']);\n assert.equal(rich.defaultReasoningLevel, 'medium');\n assert.equal(rich.reasoningDefaultEnabled, false);\n assert.equal(rich.reasoningSupportsMaxTokens, true);\n assert.equal(rich.reasoningMandatory, false);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n defaultReasoningLevel: 'provider-catalog',\n reasoningDefaultEnabled: 'provider-catalog',\n reasoningSupportsMaxTokens: 'provider-catalog',\n reasoningMandatory: 'provider-catalog',\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its complete owned snapshot', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.models.length, 345);\n assert.ok(result.models.some((model) => model.id === 'openrouter/auto'));\n assert.ok(result.models.some((model) => model.id === 'moonshotai/kimi-k2.6'));\n assert.equal(result.fallback.state, 'bundled');\n});\n\ntest('OpenRouter reasoning metadata distinguishes all-efforts from no exposed effort selector', () => {\n const allEfforts = openrouter.parseRow({\n id: 'vendor/all-efforts',\n architecture: { modality: 'text->text' },\n reasoning: {\n supported_efforts: null,\n default_effort: 'medium',\n default_enabled: true,\n mandatory: false,\n },\n });\n assert.deepEqual(allEfforts.reasoningLevels, [\n 'none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max',\n ]);\n assert.equal(allEfforts.defaultReasoningLevel, 'medium');\n\n const noSelector = openrouter.parseRow({\n id: 'vendor/no-selector',\n architecture: { modality: 'text->text' },\n reasoning: {\n default_enabled: true,\n mandatory: true,\n },\n });\n assert.equal(noSelector.reasoning, true);\n assert.equal(noSelector.reasoningLevels, null);\n assert.equal(noSelector.defaultReasoningLevel, null);\n assert.equal(noSelector.reasoningDefaultEnabled, true);\n assert.equal(noSelector.reasoningMandatory, true);\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n {\n name: 'command-a-plus-05-2026',\n is_deprecated: false,\n features: ['reasoning', 'vision', 'tools'],\n },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 436000);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n assert.equal(result.models[0].metadataSources.reasoning, 'provider-catalog');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches exact live ids from the owned snapshot without metadata network calls', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-owned-enrich-'));\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-a-plus-05-2026' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command A+');\n assert.equal(result.models[0].contextWindow, 436000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: null,\n expectedSource: null,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n expectedSource: 'provider-catalog',\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-v4-pro',\n expectedContext: 1048576,\n expectedSource: 'openrouter-catalog',\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, entry.expectedSource);\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('a provider without an owned cache rejects a malformed successful payload', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n await assert.rejects(zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async () => new Response('{\"unexpected\":true}'),\n }), /model list/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async () => new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] })),\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cache.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery classifies generateContent Gemini image models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/gemini-3.1-flash-image',\n displayName: 'Gemini 3.1 Flash Image',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 65536,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gemini-3.1-pro',\n 'gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('xAI compatibility filtering requires no separate metadata request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-owned-filter-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, xai.ENDPOINT);\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.deepEqual(result.warnings, []);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('xAI discovery enriches sparse live rows with exact bundled modalities', async () => {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n fetchImpl: async () => new Response(JSON.stringify({\n data: [\n { id: 'grok-4.5' },\n { id: 'grok-4.20-0309-reasoning' },\n { id: 'grok-imagine-image' },\n { id: 'grok-imagine-video-1.5' },\n ],\n })),\n });\n\n assert.deepEqual(result.models.map((model) => [\n model.id,\n model.inputModalities,\n model.outputModalities,\n model.reasoningLevels,\n model.defaultReasoningLevel,\n ]), [\n ['grok-4.5', ['text', 'image'], ['text'], ['low', 'medium', 'high'], 'high'],\n ['grok-4.20-0309-reasoning', ['text', 'image'], ['text'], null, null],\n ['grok-imagine-image', ['text', 'image'], ['image'], null, null],\n ['grok-imagine-video-1.5', ['image'], ['video'], null, null],\n ]);\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n defaultReasoningLevel: 'HIGH',\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.defaultReasoningLevel, 'high');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(model.metadataSources.defaultReasoningLevel, 'provider-catalog');\n});\n\ntest('xAI discovery filters unsupported multi-agent models locally', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) =>\n model.id.endsWith(':cloud') || /^gemma4:[^:]+-cloud$/u.test(model.id)));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery reads its cloud candidates without a catalog network request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-local-snapshot-'));\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama live discovery retains cloud enrichment but displays the exact model id', async () => {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'gemma4:31b-cloud' }] },\n fetchImpl: async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'gemma4:31b-cloud');\n return new Response(JSON.stringify({\n model_info: { 'gemma4.context_length': 262144 },\n capabilities: ['completion', 'thinking', 'tools', 'vision'],\n }));\n },\n });\n\n const gemma4 = result.models.find((model) => model.id === 'gemma4:31b-cloud');\n assert.equal(gemma4.displayName, 'gemma4:31b-cloud');\n assert.deepEqual(gemma4.reasoningLevels, ['none', 'low', 'medium', 'high', 'max']);\n assert.equal(gemma4.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(gemma4.contextWindow, 262144);\n assert.deepEqual(gemma4.inputModalities, ['text', 'image']);\n assert.ok(result.models.every((model) => model.displayName === model.id));\n});\n\ntest('Ollama live discovery applies reasoning controls to the full Gemma 4 family', async () => {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: {\n models: [\n { name: 'gemma4:e2b' },\n { name: 'gemma4:12b-it-q4_K_M' },\n { name: 'gemma4:26b-a4b-it-q8_0' },\n ],\n },\n fetchImpl: async (_url, options) => {\n const id = JSON.parse(options.body).name;\n return new Response(JSON.stringify({\n model_info: { 'gemma4.context_length': id === 'gemma4:e2b' ? 131072 : 262144 },\n capabilities: ['completion', 'thinking', 'tools', 'vision'],\n }));\n },\n });\n\n for (const id of [\n 'gemma4:e2b',\n 'gemma4:12b-it-q4_K_M',\n 'gemma4:26b-a4b-it-q8_0',\n ]) {\n const model = result.models.find((entry) => entry.id === id);\n assert.deepEqual(model.reasoningLevels, ['none', 'low', 'medium', 'high', 'max']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cache.state, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cache.state, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.equal(refreshed.models[0].id, 'nvidia/featured');\n assert.equal(refreshed.models.at(-1).id, 'private/model');\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cache.state, 'fresh');\n assert.equal(calls, 1);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n inventoryComplete: true,\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/provider-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "6ee35d4ce75f4fa27c278eb75e6f84d085df91d9": {"t": 1785758815.2258942, "n": 51771, "h": "eadaa7810d36addb", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeReasoningLevels,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('reasoning normalization preserves every effort accepted by the Codex model cache', () => {\n assert.deepEqual(\n normalizeReasoningLevels(['ultra', 'max', 'xhigh', 'high', 'medium', 'low']),\n ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'],\n );\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('Vertex AI OpenAI endpoints resolve as Google without probing', async () => {\n let fetchCalls = 0;\n const result = await resolveProvider({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n fetchImpl: async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n },\n });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'canonical-url');\n assert.equal(fetchCalls, 0);\n});\n\ntest('Google provider aliases resolve explicitly without probing', async () => {\n let fetches = 0;\n const fetchImpl = async () => {\n fetches += 1;\n throw new Error('must not fetch');\n };\n\n for (const provider of ['aistudio', 'gemini', 'vertexai', 'vertex-ai']) {\n const result = await resolveProvider({ provider, fetchImpl });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetches, 0);\n});\n\ntest('Vertex Google discovery classifies only explicitly supplied Gemini models', async () => {\n const result = await google.discover({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n suppliedModels: ['google/gemini-2.5-flash', 'google/gemini-3.1-flash-image'],\n fetchImpl: async () => {\n throw new Error('Vertex discovery must not call the Developer API catalog');\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'google/gemini-2.5-flash',\n 'google/gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.complete, false);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return { models: [model], origin: 'live', complete: true };\n });\n assert.equal(first.state, 'refreshed');\n assert.equal(first.origin, 'live');\n assert.equal(first.complete, true);\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(fresh.origin, 'live');\n assert.equal(fresh.complete, true);\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.state, 'stale');\n assert.equal(stale.origin, 'live');\n assert.equal(stale.complete, true);\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, ['https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json']);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.slice(0, 2).map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n reasoning: {\n supported_efforts: ['xhigh', 'high', 'medium', 'low', 'none'],\n default_effort: 'medium',\n default_enabled: false,\n supports_max_tokens: true,\n mandatory: false,\n },\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, ['none', 'low', 'medium', 'high', 'xhigh']);\n assert.equal(rich.defaultReasoningLevel, 'medium');\n assert.equal(rich.reasoningDefaultEnabled, false);\n assert.equal(rich.reasoningSupportsMaxTokens, true);\n assert.equal(rich.reasoningMandatory, false);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n defaultReasoningLevel: 'provider-catalog',\n reasoningDefaultEnabled: 'provider-catalog',\n reasoningSupportsMaxTokens: 'provider-catalog',\n reasoningMandatory: 'provider-catalog',\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its complete owned snapshot', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.models.length, 345);\n assert.ok(result.models.some((model) => model.id === 'openrouter/auto'));\n assert.ok(result.models.some((model) => model.id === 'moonshotai/kimi-k2.6'));\n assert.equal(result.fallback.state, 'bundled');\n});\n\ntest('OpenRouter reasoning metadata distinguishes all-efforts from no exposed effort selector', () => {\n const allEfforts = openrouter.parseRow({\n id: 'vendor/all-efforts',\n architecture: { modality: 'text->text' },\n reasoning: {\n supported_efforts: null,\n default_effort: 'medium',\n default_enabled: true,\n mandatory: false,\n },\n });\n assert.deepEqual(allEfforts.reasoningLevels, [\n 'none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max',\n ]);\n assert.equal(allEfforts.defaultReasoningLevel, 'medium');\n\n const noSelector = openrouter.parseRow({\n id: 'vendor/no-selector',\n architecture: { modality: 'text->text' },\n reasoning: {\n default_enabled: true,\n mandatory: true,\n },\n });\n assert.equal(noSelector.reasoning, true);\n assert.equal(noSelector.reasoningLevels, null);\n assert.equal(noSelector.defaultReasoningLevel, null);\n assert.equal(noSelector.reasoningDefaultEnabled, true);\n assert.equal(noSelector.reasoningMandatory, true);\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n {\n name: 'command-a-plus-05-2026',\n is_deprecated: false,\n features: ['reasoning', 'vision', 'tools'],\n },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 436000);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n assert.equal(result.models[0].metadataSources.reasoning, 'provider-catalog');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches exact live ids from the owned snapshot without metadata network calls', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-owned-enrich-'));\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-a-plus-05-2026' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command A+');\n assert.equal(result.models[0].contextWindow, 436000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: null,\n expectedSource: null,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n expectedSource: 'provider-catalog',\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-v4-pro',\n expectedContext: 1048576,\n expectedSource: 'openrouter-catalog',\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, entry.expectedSource);\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('a provider without an owned cache rejects a malformed successful payload', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n await assert.rejects(zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async () => new Response('{\"unexpected\":true}'),\n }), /model list/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async () => new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] })),\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cache.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery classifies generateContent Gemini image models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/gemini-3.1-flash-image',\n displayName: 'Gemini 3.1 Flash Image',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 65536,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gemini-3.1-pro',\n 'gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('xAI compatibility filtering requires no separate metadata request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-owned-filter-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, xai.ENDPOINT);\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.deepEqual(result.warnings, []);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('xAI discovery enriches sparse live rows with exact bundled modalities', async () => {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n fetchImpl: async () => new Response(JSON.stringify({\n data: [\n { id: 'grok-4.5' },\n { id: 'grok-4.20-0309-reasoning' },\n { id: 'grok-imagine-image' },\n { id: 'grok-imagine-video-1.5' },\n ],\n })),\n });\n\n assert.deepEqual(result.models.map((model) => [\n model.id,\n model.inputModalities,\n model.outputModalities,\n model.reasoningLevels,\n model.defaultReasoningLevel,\n ]), [\n ['grok-4.5', ['text', 'image'], ['text'], ['low', 'medium', 'high'], 'high'],\n ['grok-4.20-0309-reasoning', ['text', 'image'], ['text'], null, null],\n ['grok-imagine-image', ['text', 'image'], ['image'], null, null],\n ['grok-imagine-video-1.5', ['image'], ['video'], null, null],\n ]);\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n defaultReasoningLevel: 'HIGH',\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.defaultReasoningLevel, 'high');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(model.metadataSources.defaultReasoningLevel, 'provider-catalog');\n});\n\ntest('xAI discovery filters unsupported multi-agent models locally', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) =>\n model.id.endsWith(':cloud') || /^gemma4:[^:]+-cloud$/u.test(model.id)));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery reads its cloud candidates without a catalog network request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-local-snapshot-'));\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama live discovery retains cloud enrichment but displays the exact model id', async () => {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'gemma4:31b-cloud' }] },\n fetchImpl: async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'gemma4:31b-cloud');\n return new Response(JSON.stringify({\n model_info: { 'gemma4.context_length': 262144 },\n capabilities: ['completion', 'thinking', 'tools', 'vision'],\n }));\n },\n });\n\n const gemma4 = result.models.find((model) => model.id === 'gemma4:31b-cloud');\n assert.equal(gemma4.displayName, 'gemma4:31b-cloud');\n assert.deepEqual(gemma4.reasoningLevels, ['none', 'low', 'medium', 'high', 'max']);\n assert.equal(gemma4.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(gemma4.contextWindow, 262144);\n assert.deepEqual(gemma4.inputModalities, ['text', 'image']);\n assert.ok(result.models.every((model) => model.displayName === model.id));\n});\n\ntest('Ollama live discovery applies reasoning controls to the full Gemma 4 family', async () => {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: {\n models: [\n { name: 'gemma4:e2b' },\n { name: 'gemma4:12b-it-q4_K_M' },\n { name: 'gemma4:26b-a4b-it-q8_0' },\n ],\n },\n fetchImpl: async (_url, options) => {\n const id = JSON.parse(options.body).name;\n return new Response(JSON.stringify({\n model_info: { 'gemma4.context_length': id === 'gemma4:e2b' ? 131072 : 262144 },\n capabilities: ['completion', 'thinking', 'tools', 'vision'],\n }));\n },\n });\n\n for (const id of [\n 'gemma4:e2b',\n 'gemma4:12b-it-q4_K_M',\n 'gemma4:26b-a4b-it-q8_0',\n ]) {\n const model = result.models.find((entry) => entry.id === id);\n assert.deepEqual(model.reasoningLevels, ['none', 'low', 'medium', 'high', 'max']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cache.state, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cache.state, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.equal(refreshed.models[0].id, 'nvidia/featured');\n assert.equal(refreshed.models.at(-1).id, 'private/model');\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cache.state, 'fresh');\n assert.equal(calls, 1);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n inventoryComplete: true,\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/provider-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "5e54fc8c3210ae2d7da445b1df59a516f3d0be9d": {"t": 1785758817.2677538, "n": 51687, "h": "1a8ecc92bc008757", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeReasoningLevels,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('reasoning normalization preserves every effort accepted by the Codex model cache', () => {\n assert.deepEqual(\n normalizeReasoningLevels(['ultra', 'max', 'xhigh', 'high', 'medium', 'low']),\n ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'],\n );\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('Vertex AI OpenAI endpoints resolve as Google without probing', async () => {\n let fetchCalls = 0;\n const result = await resolveProvider({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n fetchImpl: async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n },\n });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'canonical-url');\n assert.equal(fetchCalls, 0);\n});\n\ntest('Google provider aliases resolve explicitly without probing', async () => {\n let fetches = 0;\n const fetchImpl = async () => {\n fetches += 1;\n throw new Error('must not fetch');\n };\n\n for (const provider of ['aistudio', 'gemini', 'vertexai', 'vertex-ai']) {\n const result = await resolveProvider({ provider, fetchImpl });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetches, 0);\n});\n\ntest('Vertex Google discovery classifies only explicitly supplied Gemini models', async () => {\n const result = await google.discover({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n suppliedModels: ['google/gemini-2.5-flash', 'google/gemini-3.1-flash-image'],\n fetchImpl: async () => {\n throw new Error('Vertex discovery must not call the Developer API catalog');\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'google/gemini-2.5-flash',\n 'google/gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.complete, false);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return { models: [model], origin: 'live', complete: true };\n });\n assert.equal(first.state, 'refreshed');\n assert.equal(first.origin, 'live');\n assert.equal(first.complete, true);\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(fresh.origin, 'live');\n assert.equal(fresh.complete, true);\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.state, 'stale');\n assert.equal(stale.origin, 'live');\n assert.equal(stale.complete, true);\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, ['https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json']);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.slice(0, 2).map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n reasoning: {\n supported_efforts: ['xhigh', 'high', 'medium', 'low', 'none'],\n default_effort: 'medium',\n default_enabled: false,\n supports_max_tokens: true,\n mandatory: false,\n },\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, ['none', 'low', 'medium', 'high', 'xhigh']);\n assert.equal(rich.defaultReasoningLevel, 'medium');\n assert.equal(rich.reasoningDefaultEnabled, false);\n assert.equal(rich.reasoningSupportsMaxTokens, true);\n assert.equal(rich.reasoningMandatory, false);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n defaultReasoningLevel: 'provider-catalog',\n reasoningDefaultEnabled: 'provider-catalog',\n reasoningSupportsMaxTokens: 'provider-catalog',\n reasoningMandatory: 'provider-catalog',\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its complete owned snapshot', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.models.length, 345);\n assert.ok(result.models.some((model) => model.id === 'openrouter/auto'));\n assert.ok(result.models.some((model) => model.id === 'moonshotai/kimi-k2.6'));\n assert.equal(result.fallback.state, 'bundled');\n});\n\ntest('OpenRouter reasoning metadata distinguishes all-efforts from no exposed effort selector', () => {\n const allEfforts = openrouter.parseRow({\n id: 'vendor/all-efforts',\n architecture: { modality: 'text->text' },\n reasoning: {\n supported_efforts: null,\n default_effort: 'medium',\n default_enabled: true,\n mandatory: false,\n },\n });\n assert.deepEqual(allEfforts.reasoningLevels, [\n 'none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max',\n ]);\n assert.equal(allEfforts.defaultReasoningLevel, 'medium');\n\n const noSelector = openrouter.parseRow({\n id: 'vendor/no-selector',\n architecture: { modality: 'text->text' },\n reasoning: {\n default_enabled: true,\n mandatory: true,\n },\n });\n assert.equal(noSelector.reasoning, true);\n assert.equal(noSelector.reasoningLevels, null);\n assert.equal(noSelector.defaultReasoningLevel, null);\n assert.equal(noSelector.reasoningDefaultEnabled, true);\n assert.equal(noSelector.reasoningMandatory, true);\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n {\n name: 'command-a-plus-05-2026',\n is_deprecated: false,\n features: ['reasoning', 'vision', 'tools'],\n },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 436000);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n assert.equal(result.models[0].metadataSources.reasoning, 'provider-catalog');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches exact live ids from the owned snapshot without metadata network calls', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-owned-enrich-'));\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-a-plus-05-2026' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command A+');\n assert.equal(result.models[0].contextWindow, 436000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: null,\n expectedSource: null,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n expectedSource: 'provider-catalog',\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-v4-pro',\n expectedContext: 1048576,\n expectedSource: 'openrouter-catalog',\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, entry.expectedSource);\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('a provider without an owned cache rejects a malformed successful payload', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n await assert.rejects(zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async () => new Response('{\"unexpected\":true}'),\n }), /model list/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async () => new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] })),\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cache.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery classifies generateContent Gemini image models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/gemini-3.1-flash-image',\n displayName: 'Gemini 3.1 Flash Image',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 65536,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gemini-3.1-pro',\n 'gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('xAI compatibility filtering requires no separate metadata request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-owned-filter-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, xai.ENDPOINT);\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.deepEqual(result.warnings, []);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('xAI discovery enriches sparse live rows with exact bundled modalities', async () => {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n fetchImpl: async () => new Response(JSON.stringify({\n data: [\n { id: 'grok-4.5' },\n { id: 'grok-4.20-0309-reasoning' },\n { id: 'grok-imagine-image' },\n { id: 'grok-imagine-video-1.5' },\n ],\n })),\n });\n\n assert.deepEqual(result.models.map((model) => [\n model.id,\n model.inputModalities,\n model.outputModalities,\n model.reasoningLevels,\n model.defaultReasoningLevel,\n ]), [\n ['grok-4.5', ['text', 'image'], ['text'], ['low', 'medium', 'high'], 'high'],\n ['grok-4.20-0309-reasoning', ['text', 'image'], ['text'], null, null],\n ['grok-imagine-image', ['text', 'image'], ['image'], null, null],\n ['grok-imagine-video-1.5', ['image'], ['video'], null, null],\n ]);\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n defaultReasoningLevel: 'HIGH',\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.defaultReasoningLevel, 'high');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(model.metadataSources.defaultReasoningLevel, 'provider-catalog');\n});\n\ntest('xAI discovery filters unsupported multi-agent models locally', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) =>\n model.id.endsWith(':cloud') || /^gemma4:[^:]+-cloud$/u.test(model.id)));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery reads its cloud candidates without a catalog network request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-local-snapshot-'));\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama live discovery retains exact bundled Gemma 4 cloud enrichment', async () => {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'gemma4:31b-cloud' }] },\n fetchImpl: async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'gemma4:31b-cloud');\n return new Response(JSON.stringify({\n model_info: { 'gemma4.context_length': 262144 },\n capabilities: ['completion', 'thinking', 'tools', 'vision'],\n }));\n },\n });\n\n const gemma4 = result.models.find((model) => model.id === 'gemma4:31b-cloud');\n assert.equal(gemma4.displayName, 'Google: Gemma 4 31B');\n assert.deepEqual(gemma4.reasoningLevels, ['none', 'low', 'medium', 'high', 'max']);\n assert.equal(gemma4.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(gemma4.contextWindow, 262144);\n assert.deepEqual(gemma4.inputModalities, ['text', 'image']);\n});\n\ntest('Ollama live discovery applies reasoning controls to the full Gemma 4 family', async () => {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: {\n models: [\n { name: 'gemma4:e2b' },\n { name: 'gemma4:12b-it-q4_K_M' },\n { name: 'gemma4:26b-a4b-it-q8_0' },\n ],\n },\n fetchImpl: async (_url, options) => {\n const id = JSON.parse(options.body).name;\n return new Response(JSON.stringify({\n model_info: { 'gemma4.context_length': id === 'gemma4:e2b' ? 131072 : 262144 },\n capabilities: ['completion', 'thinking', 'tools', 'vision'],\n }));\n },\n });\n\n for (const id of [\n 'gemma4:e2b',\n 'gemma4:12b-it-q4_K_M',\n 'gemma4:26b-a4b-it-q8_0',\n ]) {\n const model = result.models.find((entry) => entry.id === id);\n assert.deepEqual(model.reasoningLevels, ['none', 'low', 'medium', 'high', 'max']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cache.state, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cache.state, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.equal(refreshed.models[0].id, 'nvidia/featured');\n assert.equal(refreshed.models.at(-1).id, 'private/model');\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cache.state, 'fresh');\n assert.equal(calls, 1);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n inventoryComplete: true,\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/provider-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "3240da898d26b996ce573e52381c17a0bc3fbb67": {"t": 1785758818.6835973, "n": 49604, "h": "29b4b6bea4eb55ec", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeReasoningLevels,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('reasoning normalization preserves every effort accepted by the Codex model cache', () => {\n assert.deepEqual(\n normalizeReasoningLevels(['ultra', 'max', 'xhigh', 'high', 'medium', 'low']),\n ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'],\n );\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('Vertex AI OpenAI endpoints resolve as Google without probing', async () => {\n let fetchCalls = 0;\n const result = await resolveProvider({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n fetchImpl: async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n },\n });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'canonical-url');\n assert.equal(fetchCalls, 0);\n});\n\ntest('Google provider aliases resolve explicitly without probing', async () => {\n let fetches = 0;\n const fetchImpl = async () => {\n fetches += 1;\n throw new Error('must not fetch');\n };\n\n for (const provider of ['aistudio', 'gemini', 'vertexai', 'vertex-ai']) {\n const result = await resolveProvider({ provider, fetchImpl });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetches, 0);\n});\n\ntest('Vertex Google discovery classifies only explicitly supplied Gemini models', async () => {\n const result = await google.discover({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n suppliedModels: ['google/gemini-2.5-flash', 'google/gemini-3.1-flash-image'],\n fetchImpl: async () => {\n throw new Error('Vertex discovery must not call the Developer API catalog');\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'google/gemini-2.5-flash',\n 'google/gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.complete, false);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return { models: [model], origin: 'live', complete: true };\n });\n assert.equal(first.state, 'refreshed');\n assert.equal(first.origin, 'live');\n assert.equal(first.complete, true);\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(fresh.origin, 'live');\n assert.equal(fresh.complete, true);\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.state, 'stale');\n assert.equal(stale.origin, 'live');\n assert.equal(stale.complete, true);\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, ['https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json']);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.slice(0, 2).map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n reasoningDefaultEnabled: null,\n reasoningSupportsMaxTokens: null,\n reasoningMandatory: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n reasoning: {\n supported_efforts: ['xhigh', 'high', 'medium', 'low', 'none'],\n default_effort: 'medium',\n default_enabled: false,\n supports_max_tokens: true,\n mandatory: false,\n },\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, ['none', 'low', 'medium', 'high', 'xhigh']);\n assert.equal(rich.defaultReasoningLevel, 'medium');\n assert.equal(rich.reasoningDefaultEnabled, false);\n assert.equal(rich.reasoningSupportsMaxTokens, true);\n assert.equal(rich.reasoningMandatory, false);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: 'provider-catalog',\n defaultReasoningLevel: 'provider-catalog',\n reasoningDefaultEnabled: 'provider-catalog',\n reasoningSupportsMaxTokens: 'provider-catalog',\n reasoningMandatory: 'provider-catalog',\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its complete owned snapshot', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.models.length, 345);\n assert.ok(result.models.some((model) => model.id === 'openrouter/auto'));\n assert.ok(result.models.some((model) => model.id === 'moonshotai/kimi-k2.6'));\n assert.equal(result.fallback.state, 'bundled');\n});\n\ntest('OpenRouter reasoning metadata distinguishes all-efforts from no exposed effort selector', () => {\n const allEfforts = openrouter.parseRow({\n id: 'vendor/all-efforts',\n architecture: { modality: 'text->text' },\n reasoning: {\n supported_efforts: null,\n default_effort: 'medium',\n default_enabled: true,\n mandatory: false,\n },\n });\n assert.deepEqual(allEfforts.reasoningLevels, [\n 'none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max',\n ]);\n assert.equal(allEfforts.defaultReasoningLevel, 'medium');\n\n const noSelector = openrouter.parseRow({\n id: 'vendor/no-selector',\n architecture: { modality: 'text->text' },\n reasoning: {\n default_enabled: true,\n mandatory: true,\n },\n });\n assert.equal(noSelector.reasoning, true);\n assert.equal(noSelector.reasoningLevels, null);\n assert.equal(noSelector.defaultReasoningLevel, null);\n assert.equal(noSelector.reasoningDefaultEnabled, true);\n assert.equal(noSelector.reasoningMandatory, true);\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n {\n name: 'command-a-plus-05-2026',\n is_deprecated: false,\n features: ['reasoning', 'vision', 'tools'],\n },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 436000);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n assert.equal(result.models[0].metadataSources.reasoning, 'provider-catalog');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches exact live ids from the owned snapshot without metadata network calls', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-owned-enrich-'));\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-a-plus-05-2026' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command A+');\n assert.equal(result.models[0].contextWindow, 436000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].reasoningDefaultEnabled, true);\n assert.equal(result.models[0].reasoningSupportsMaxTokens, true);\n assert.equal(result.models[0].reasoningMandatory, false);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: null,\n expectedSource: null,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n expectedSource: 'provider-catalog',\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-v4-pro',\n expectedContext: 1048576,\n expectedSource: 'openrouter-catalog',\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, entry.expectedSource);\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('a provider without an owned cache rejects a malformed successful payload', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n await assert.rejects(zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async () => new Response('{\"unexpected\":true}'),\n }), /model list/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async () => new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] })),\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cache.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery classifies generateContent Gemini image models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/gemini-3.1-flash-image',\n displayName: 'Gemini 3.1 Flash Image',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 65536,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gemini-3.1-pro',\n 'gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('xAI compatibility filtering requires no separate metadata request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-owned-filter-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, xai.ENDPOINT);\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.deepEqual(result.warnings, []);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('xAI discovery enriches sparse live rows with exact bundled modalities', async () => {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n fetchImpl: async () => new Response(JSON.stringify({\n data: [\n { id: 'grok-4.5' },\n { id: 'grok-4.20-0309-reasoning' },\n { id: 'grok-imagine-image' },\n { id: 'grok-imagine-video-1.5' },\n ],\n })),\n });\n\n assert.deepEqual(result.models.map((model) => [\n model.id,\n model.inputModalities,\n model.outputModalities,\n model.reasoningLevels,\n model.defaultReasoningLevel,\n ]), [\n ['grok-4.5', ['text', 'image'], ['text'], ['low', 'medium', 'high'], 'high'],\n ['grok-4.20-0309-reasoning', ['text', 'image'], ['text'], null, null],\n ['grok-imagine-image', ['text', 'image'], ['image'], null, null],\n ['grok-imagine-video-1.5', ['image'], ['video'], null, null],\n ]);\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n defaultReasoningLevel: 'HIGH',\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.defaultReasoningLevel, 'high');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(model.metadataSources.defaultReasoningLevel, 'provider-catalog');\n});\n\ntest('xAI discovery filters unsupported multi-agent models locally', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) => model.id.endsWith(':cloud')));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery reads its cloud candidates without a catalog network request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-local-snapshot-'));\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cache.state, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cache.state, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.equal(refreshed.models[0].id, 'nvidia/featured');\n assert.equal(refreshed.models.at(-1).id, 'private/model');\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cache.state, 'fresh');\n assert.equal(calls, 1);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n inventoryComplete: true,\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/provider-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "28e6ec7bf9558f6650632ebe9d6f08fcb35dbc9c": {"t": 1785758820.5305588, "n": 47011, "h": "870f270b3065e1e9", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeReasoningLevels,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('reasoning normalization preserves every effort accepted by the Codex model cache', () => {\n assert.deepEqual(\n normalizeReasoningLevels(['ultra', 'max', 'xhigh', 'high', 'medium', 'low']),\n ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'],\n );\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('Vertex AI OpenAI endpoints resolve as Google without probing', async () => {\n let fetchCalls = 0;\n const result = await resolveProvider({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n fetchImpl: async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n },\n });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'canonical-url');\n assert.equal(fetchCalls, 0);\n});\n\ntest('Google provider aliases resolve explicitly without probing', async () => {\n let fetches = 0;\n const fetchImpl = async () => {\n fetches += 1;\n throw new Error('must not fetch');\n };\n\n for (const provider of ['aistudio', 'gemini', 'vertexai', 'vertex-ai']) {\n const result = await resolveProvider({ provider, fetchImpl });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetches, 0);\n});\n\ntest('Vertex Google discovery classifies only explicitly supplied Gemini models', async () => {\n const result = await google.discover({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n suppliedModels: ['google/gemini-2.5-flash', 'google/gemini-3.1-flash-image'],\n fetchImpl: async () => {\n throw new Error('Vertex discovery must not call the Developer API catalog');\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'google/gemini-2.5-flash',\n 'google/gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.complete, false);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return { models: [model], origin: 'live', complete: true };\n });\n assert.equal(first.state, 'refreshed');\n assert.equal(first.origin, 'live');\n assert.equal(first.complete, true);\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(fresh.origin, 'live');\n assert.equal(fresh.complete, true);\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.state, 'stale');\n assert.equal(stale.origin, 'live');\n assert.equal(stale.complete, true);\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, ['https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json']);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.slice(0, 2).map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n defaultReasoningLevel: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, null);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: null,\n defaultReasoningLevel: null,\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its complete owned snapshot', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.models.length, 343);\n assert.ok(result.models.some((model) => model.id === 'openrouter/auto'));\n assert.ok(result.models.some((model) => model.id === 'moonshotai/kimi-k2.6'));\n assert.equal(result.fallback.state, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n { name: 'command-a-plus-05-2026', is_deprecated: false },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 436000);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, null);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches exact live ids from the owned snapshot without metadata network calls', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-owned-enrich-'));\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-a-plus-05-2026' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command A+');\n assert.equal(result.models[0].contextWindow, 436000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, null);\n assert.equal(result.models[0].toolCalling, null);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: null,\n expectedSource: null,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n expectedSource: 'provider-catalog',\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-v4-pro',\n expectedContext: 1048576,\n expectedSource: 'openrouter-catalog',\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, entry.expectedSource);\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('a provider without an owned cache rejects a malformed successful payload', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n await assert.rejects(zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async () => new Response('{\"unexpected\":true}'),\n }), /model list/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async () => new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] })),\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cache.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery classifies generateContent Gemini image models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/gemini-3.1-flash-image',\n displayName: 'Gemini 3.1 Flash Image',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 65536,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gemini-3.1-pro',\n 'gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('xAI compatibility filtering requires no separate metadata request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-owned-filter-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, xai.ENDPOINT);\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.deepEqual(result.warnings, []);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('xAI discovery enriches sparse live rows with exact bundled modalities', async () => {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n fetchImpl: async () => new Response(JSON.stringify({\n data: [\n { id: 'grok-4.5' },\n { id: 'grok-4.20-0309-reasoning' },\n { id: 'grok-imagine-image' },\n { id: 'grok-imagine-video-1.5' },\n ],\n })),\n });\n\n assert.deepEqual(result.models.map((model) => [\n model.id,\n model.inputModalities,\n model.outputModalities,\n model.reasoningLevels,\n model.defaultReasoningLevel,\n ]), [\n ['grok-4.5', ['text', 'image'], ['text'], ['low', 'medium', 'high'], 'high'],\n ['grok-4.20-0309-reasoning', ['text', 'image'], ['text'], null, null],\n ['grok-imagine-image', ['text', 'image'], ['image'], null, null],\n ['grok-imagine-video-1.5', ['image'], ['video'], null, null],\n ]);\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n defaultReasoningLevel: 'HIGH',\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.defaultReasoningLevel, 'high');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n assert.equal(model.metadataSources.defaultReasoningLevel, 'provider-catalog');\n});\n\ntest('xAI discovery filters unsupported multi-agent models locally', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) => model.id.endsWith(':cloud')));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery reads its cloud candidates without a catalog network request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-local-snapshot-'));\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cache.state, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cache.state, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.equal(refreshed.models[0].id, 'nvidia/featured');\n assert.equal(refreshed.models.at(-1).id, 'private/model');\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cache.state, 'fresh');\n assert.equal(calls, 1);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n inventoryComplete: true,\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/provider-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "3f249b8f9dc1cdb74c427e11a2fe4fa70f65498b": {"t": 1785758822.086752, "n": 46207, "h": "d14761bac5345480", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('Vertex AI OpenAI endpoints resolve as Google without probing', async () => {\n let fetchCalls = 0;\n const result = await resolveProvider({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n fetchImpl: async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n },\n });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'canonical-url');\n assert.equal(fetchCalls, 0);\n});\n\ntest('Google provider aliases resolve explicitly without probing', async () => {\n let fetches = 0;\n const fetchImpl = async () => {\n fetches += 1;\n throw new Error('must not fetch');\n };\n\n for (const provider of ['aistudio', 'gemini', 'vertexai', 'vertex-ai']) {\n const result = await resolveProvider({ provider, fetchImpl });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetches, 0);\n});\n\ntest('Vertex Google discovery classifies only explicitly supplied Gemini models', async () => {\n const result = await google.discover({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n suppliedModels: ['google/gemini-2.5-flash', 'google/gemini-3.1-flash-image'],\n fetchImpl: async () => {\n throw new Error('Vertex discovery must not call the Developer API catalog');\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'google/gemini-2.5-flash',\n 'google/gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.complete, false);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return { models: [model], origin: 'live', complete: true };\n });\n assert.equal(first.state, 'refreshed');\n assert.equal(first.origin, 'live');\n assert.equal(first.complete, true);\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(fresh.origin, 'live');\n assert.equal(fresh.complete, true);\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.state, 'stale');\n assert.equal(stale.origin, 'live');\n assert.equal(stale.complete, true);\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, ['https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json']);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.slice(0, 2).map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, null);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: null,\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its complete owned snapshot', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.models.length, 343);\n assert.ok(result.models.some((model) => model.id === 'openrouter/auto'));\n assert.ok(result.models.some((model) => model.id === 'moonshotai/kimi-k2.6'));\n assert.equal(result.fallback.state, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n { name: 'command-a-plus-05-2026', is_deprecated: false },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 436000);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, null);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches exact live ids from the owned snapshot without metadata network calls', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-owned-enrich-'));\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-a-plus-05-2026' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command A+');\n assert.equal(result.models[0].contextWindow, 436000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, null);\n assert.equal(result.models[0].toolCalling, null);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: null,\n expectedSource: null,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n expectedSource: 'provider-catalog',\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-v4-pro',\n expectedContext: 1048576,\n expectedSource: 'openrouter-catalog',\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, entry.expectedSource);\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('a provider without an owned cache rejects a malformed successful payload', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n await assert.rejects(zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async () => new Response('{\"unexpected\":true}'),\n }), /model list/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async () => new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] })),\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cache.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery classifies generateContent Gemini image models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/gemini-3.1-flash-image',\n displayName: 'Gemini 3.1 Flash Image',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 65536,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gemini-3.1-pro',\n 'gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('xAI compatibility filtering requires no separate metadata request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-owned-filter-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, xai.ENDPOINT);\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.deepEqual(result.warnings, []);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('xAI discovery enriches sparse live rows with exact bundled modalities', async () => {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n fetchImpl: async () => new Response(JSON.stringify({\n data: [\n { id: 'grok-4.20-0309-reasoning' },\n { id: 'grok-imagine-image' },\n { id: 'grok-imagine-video-1.5' },\n ],\n })),\n });\n\n assert.deepEqual(result.models.map((model) => [\n model.id,\n model.inputModalities,\n model.outputModalities,\n ]), [\n ['grok-4.20-0309-reasoning', ['text', 'image'], ['text']],\n ['grok-imagine-image', ['text', 'image'], ['image']],\n ['grok-imagine-video-1.5', ['image'], ['video']],\n ]);\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n});\n\ntest('xAI discovery filters unsupported multi-agent models locally', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) => model.id.endsWith(':cloud')));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery reads its cloud candidates without a catalog network request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-local-snapshot-'));\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cache.state, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cache.state, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.equal(refreshed.models[0].id, 'nvidia/featured');\n assert.equal(refreshed.models.at(-1).id, 'private/model');\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cache.state, 'fresh');\n assert.equal(calls, 1);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n inventoryComplete: true,\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/provider-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "9eb58dd5d974105fbc480ab363b0847b4d1c8a82": {"t": 1785758823.9067376, "n": 45500, "h": "32a0c5b99522190a", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('Vertex AI OpenAI endpoints resolve as Google without probing', async () => {\n let fetchCalls = 0;\n const result = await resolveProvider({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n fetchImpl: async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n },\n });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'canonical-url');\n assert.equal(fetchCalls, 0);\n});\n\ntest('Google provider aliases resolve explicitly without probing', async () => {\n let fetches = 0;\n const fetchImpl = async () => {\n fetches += 1;\n throw new Error('must not fetch');\n };\n\n for (const provider of ['aistudio', 'gemini', 'vertexai', 'vertex-ai']) {\n const result = await resolveProvider({ provider, fetchImpl });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetches, 0);\n});\n\ntest('Vertex Google discovery classifies only explicitly supplied Gemini models', async () => {\n const result = await google.discover({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n suppliedModels: ['google/gemini-2.5-flash', 'google/gemini-3.1-flash-image'],\n fetchImpl: async () => {\n throw new Error('Vertex discovery must not call the Developer API catalog');\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'google/gemini-2.5-flash',\n 'google/gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.complete, false);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return { models: [model], origin: 'live', complete: true };\n });\n assert.equal(first.state, 'refreshed');\n assert.equal(first.origin, 'live');\n assert.equal(first.complete, true);\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(fresh.origin, 'live');\n assert.equal(fresh.complete, true);\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.state, 'stale');\n assert.equal(stale.origin, 'live');\n assert.equal(stale.complete, true);\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, ['https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json']);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.slice(0, 2).map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, null);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: null,\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its complete owned snapshot', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.models.length, 343);\n assert.ok(result.models.some((model) => model.id === 'openrouter/auto'));\n assert.ok(result.models.some((model) => model.id === 'moonshotai/kimi-k2.6'));\n assert.equal(result.fallback.state, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n { name: 'command-a-plus-05-2026', is_deprecated: false },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 436000);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.deepEqual(result.models[0].inputModalities, ['text']);\n assert.equal(result.models[0].reasoning, null);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches exact live ids from the owned snapshot without metadata network calls', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-owned-enrich-'));\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-a-plus-05-2026' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command A+');\n assert.equal(result.models[0].contextWindow, 436000);\n assert.deepEqual(result.models[0].inputModalities, ['text']);\n assert.equal(result.models[0].reasoning, null);\n assert.equal(result.models[0].toolCalling, null);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-catalog');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: null,\n expectedSource: null,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n expectedSource: 'provider-catalog',\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-v4-pro',\n expectedContext: 1048576,\n expectedSource: 'openrouter-catalog',\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, entry.expectedSource);\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('a provider without an owned cache rejects a malformed successful payload', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n await assert.rejects(zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async () => new Response('{\"unexpected\":true}'),\n }), /model list/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async () => new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] })),\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cache.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery classifies generateContent Gemini image models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/gemini-3.1-flash-image',\n displayName: 'Gemini 3.1 Flash Image',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 65536,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gemini-3.1-pro',\n 'gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('xAI compatibility filtering requires no separate metadata request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-owned-filter-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, xai.ENDPOINT);\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.deepEqual(result.warnings, []);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n});\n\ntest('xAI discovery filters unsupported multi-agent models locally', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) => model.id.endsWith(':cloud')));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery reads its cloud candidates without a catalog network request', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-local-snapshot-'));\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cache.state, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cache.state, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.equal(refreshed.models[0].id, 'nvidia/featured');\n assert.equal(refreshed.models.at(-1).id, 'private/model');\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cache.state, 'fresh');\n assert.equal(calls, 1);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n inventoryComplete: true,\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/provider-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "5b8f9c2a0758538f9c3f7787cdee3bf7d271f7e6": {"t": 1785758825.802455, "n": 62115, "h": "f962e21ba778039f", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst {\n CATALOG_TTL_MS,\n OPENCLAW_CATALOGS,\n loadOpenClawCatalog,\n parseOpenClawCatalog,\n} = require('../src/model-discovery/openclaw-catalog');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('OpenClaw catalog sync includes the extended static providers and preserves Ollama Cloud', () => {\n assert.deepEqual(Object.keys(OPENCLAW_CATALOGS).sort(), [\n 'cohere', 'deepseek', 'moonshot', 'nvidia', 'ollama-cloud', 'zai',\n ]);\n assert.equal(CATALOG_TTL_MS, 24 * 60 * 60 * 1000);\n for (const entry of Object.values(OPENCLAW_CATALOGS)) {\n const url = new URL(entry.url);\n assert.equal(url.protocol, 'https:');\n assert.equal(url.hostname, 'raw.githubusercontent.com');\n assert.match(url.pathname, /^\\/openclaw\\/openclaw\\/main\\/extensions\\//u);\n assert.match(url.pathname, /\\/openclaw\\.plugin\\.json$/u);\n }\n assert.equal(OPENCLAW_CATALOGS.ollama, undefined);\n});\n\ntest('extended OpenClaw static catalogs use bundled first-run fallbacks', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'extended-openclaw-bundled-'));\n try {\n for (const provider of ['zai', 'moonshot', 'deepseek']) {\n const result = await loadOpenClawCatalog({\n provider,\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.state, 'bundled');\n assert.ok(result.models.length > 0, `${provider} must bundle model rows`);\n }\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama Cloud catalog parsing requires the distinct cloud provider base URL', () => {\n const payload = {\n modelCatalog: {\n providers: {\n 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [{\n id: 'cloud-test:cloud',\n name: 'Cloud Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8192,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('ollama-cloud', payload);\n assert.deepEqual(models.map((model) => model.id), ['cloud-test:cloud']);\n assert.equal(models[0].toolCalling, true);\n payload.modelCatalog.providers['ollama-cloud'].baseUrl = 'http://localhost:11434';\n assert.throws(() => parseOpenClawCatalog('ollama-cloud', payload), /base URL/i);\n});\n\ntest('bundled provider snapshots preserve provider-native Ollama and Moonshot capabilities', () => {\n const ollamaCloud = require('../src/model-discovery/catalogs/openclaw/ollama-cloud.json');\n const ollamaModels = new Map(\n ollamaCloud.modelCatalog.providers['ollama-cloud'].models.map((model) => [model.id, model]),\n );\n assert.equal(ollamaModels.get('kimi-k2.5:cloud').contextWindow, 262144);\n assert.deepEqual(ollamaModels.get('kimi-k2.5:cloud').input, ['text', 'image']);\n assert.equal(ollamaModels.get('minimax-m2.7:cloud').contextWindow, 196608);\n assert.equal(ollamaModels.get('glm-5.1:cloud').contextWindow, 202752);\n\n const moonshotCatalog = require('../src/model-discovery/catalogs/openclaw/moonshot.json');\n const moonshotModels = new Map(\n moonshotCatalog.modelCatalog.providers.moonshot.models.map((model) => [model.id, model]),\n );\n assert.equal(moonshotModels.get('kimi-k2.6').reasoning, true);\n assert.equal(moonshotModels.get('kimi-k2.5').reasoning, true);\n});\n\ntest('provider-native corrections override stale OpenClaw catalog metadata', () => {\n const ollamaModels = parseOpenClawCatalog('ollama-cloud', {\n modelCatalog: { providers: { 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [\n { id: 'kimi-k2.5:cloud', input: ['text'], contextWindow: 128000 },\n { id: 'minimax-m2.7:cloud', input: ['text'], contextWindow: 128000 },\n { id: 'glm-5.1:cloud', input: ['text'], contextWindow: 128000 },\n ],\n } } },\n });\n assert.deepEqual(ollamaModels.map((model) => ({\n id: model.id,\n contextWindow: model.contextWindow,\n inputModalities: model.inputModalities,\n })), [\n { id: 'kimi-k2.5:cloud', contextWindow: 262144, inputModalities: ['text', 'image'] },\n { id: 'minimax-m2.7:cloud', contextWindow: 196608, inputModalities: ['text'] },\n { id: 'glm-5.1:cloud', contextWindow: 202752, inputModalities: ['text'] },\n ]);\n\n const moonshotModels = parseOpenClawCatalog('moonshot', {\n modelCatalog: { providers: { moonshot: {\n baseUrl: 'https://api.moonshot.ai/v1',\n models: [\n { id: 'kimi-k2.6', input: ['text', 'image'] },\n { id: 'kimi-k2.5', input: ['text', 'image'] },\n ],\n } } },\n });\n assert.deepEqual(moonshotModels.map((model) => model.reasoning), [true, true]);\n});\n\ntest('OpenClaw catalog parsing validates provider identity and drops deprecated models', () => {\n const payload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [\n {\n id: 'vendor/current',\n name: 'Current',\n input: ['text', 'image'],\n contextWindow: 131072,\n maxTokens: 8192,\n reasoning: true,\n compat: { supportsTools: true },\n },\n {\n id: 'vendor/old',\n name: 'Old',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4096,\n status: 'deprecated',\n },\n ],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('nvidia', payload);\n assert.deepEqual(models.map((model) => model.id), ['vendor/current']);\n assert.deepEqual(models[0].inputModalities, ['text', 'image']);\n assert.equal(models[0].reasoning, true);\n assert.equal(models[0].toolCalling, true);\n assert.equal(models[0].source, 'openclaw-static');\n\n payload.modelCatalog.providers.nvidia.baseUrl = 'https://attacker.example/v1';\n assert.throws(() => parseOpenClawCatalog('nvidia', payload), /base URL/i);\n assert.throws(() => parseOpenClawCatalog('ollama', payload), /unsupported OpenClaw catalog/i);\n});\n\ntest('OpenClaw catalog uses supported provider efforts instead of assuming every Codex level', () => {\n const payload = {\n modelCatalog: {\n providers: {\n zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-capable',\n name: 'GLM Capable',\n input: ['text', 'image'],\n output: ['text'],\n reasoning: true,\n contextWindow: 128000,\n maxTokens: 8192,\n thinkingLevelMap: { low: null, high: 'max', max: 'max' },\n compat: { supportsReasoningEffort: true, supportedReasoningEfforts: ['max'] },\n }],\n },\n },\n },\n };\n const [model] = parseOpenClawCatalog('zai', payload);\n assert.deepEqual(model.inputModalities, ['text', 'image']);\n assert.deepEqual(model.outputModalities, ['text']);\n assert.deepEqual(model.reasoningLevels, ['max']);\n assert.equal(model.metadataSources.outputModalities, 'provider-seed');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-seed');\n});\n\ntest('OpenClaw catalog leaves exact reasoning levels unknown when only configurability is known', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{ id: 'glm-unknown-levels', reasoning: true, compat: { supportsReasoningEffort: true } }],\n } } },\n };\n assert.equal(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, null);\n});\n\ntest('OpenClaw catalog normalizes thinking map values when explicit efforts are absent', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-mapped-levels', reasoning: true,\n thinkingLevelMap: { low: null, high: 'max', xhigh: 'max' },\n }],\n } } },\n };\n assert.deepEqual(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, ['max']);\n});\n\ntest('OpenClaw catalog sync refreshes at most daily and retains the last successful file', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-sync-'));\n let calls = 0;\n const payload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-test',\n name: 'Command Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8000,\n }],\n },\n },\n },\n };\n try {\n const options = {\n provider: 'cohere',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, request) => {\n calls += 1;\n assert.equal(url, OPENCLAW_CATALOGS.cohere.url);\n assert.equal(request.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n },\n };\n const refreshed = await loadOpenClawCatalog(options);\n assert.equal(refreshed.state, 'refreshed');\n assert.deepEqual(refreshed.models.map((model) => model.id), ['command-test']);\n\n const fresh = await loadOpenClawCatalog({\n ...options,\n now: () => 1000 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh catalog must not fetch');\n },\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(calls, 1);\n\n const stale = await loadOpenClawCatalog({\n ...options,\n now: () => 1001 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('offline');\n },\n });\n assert.equal(stale.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['command-test']);\n assert.match(stale.warnings[0], /last successful/i);\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync uses its bundled snapshot on first-run network failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-bundled-'));\n try {\n const result = await loadOpenClawCatalog({\n provider: 'nvidia',\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.state, 'bundled');\n assert.ok(result.models.length > 0);\n assert.match(result.warnings[0], /bundled OpenClaw catalog/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync does not replace caller cancellation with a bundled snapshot', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-cancel-'));\n const controller = new AbortController();\n controller.abort();\n try {\n await assert.rejects(loadOpenClawCatalog({\n provider: 'cohere',\n cacheDir,\n signal: controller.signal,\n fetchImpl: async () => { throw new Error('aborted'); },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery merges the daily OpenClaw catalog behind the live NVIDIA feed', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-merge-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n };\n try {\n const result = await nvidia.discover({\n apiKey: 'nvidia-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [{\n model: 'live/model',\n 'model-name': 'Live Model',\n context: 128000,\n 'max-output': 8000,\n }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['live/model', 'static/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery does not replace caller cancellation with its static catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-cancel-'));\n const controller = new AbortController();\n try {\n await assert.rejects(nvidia.discover({\n cacheDir,\n signal: controller.signal,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n controller.abort();\n throw new Error('aborted');\n },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('Vertex AI OpenAI endpoints resolve as Google without probing', async () => {\n let fetchCalls = 0;\n const result = await resolveProvider({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n fetchImpl: async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n },\n });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'canonical-url');\n assert.equal(fetchCalls, 0);\n});\n\ntest('Google provider aliases resolve explicitly without probing', async () => {\n let fetches = 0;\n const fetchImpl = async () => {\n fetches += 1;\n throw new Error('must not fetch');\n };\n\n for (const provider of ['aistudio', 'gemini', 'vertexai', 'vertex-ai']) {\n const result = await resolveProvider({ provider, fetchImpl });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetches, 0);\n});\n\ntest('Vertex Google discovery classifies only explicitly supplied Gemini models', async () => {\n const result = await google.discover({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n suppliedModels: ['google/gemini-2.5-flash', 'google/gemini-3.1-flash-image'],\n fetchImpl: async () => {\n throw new Error('Vertex discovery must not call the Developer API catalog');\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'google/gemini-2.5-flash',\n 'google/gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.complete, false);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return { models: [model], origin: 'live', complete: true };\n });\n assert.equal(first.state, 'refreshed');\n assert.equal(first.origin, 'live');\n assert.equal(first.complete, true);\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(fresh.origin, 'live');\n assert.equal(fresh.complete, true);\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.state, 'stale');\n assert.equal(stale.origin, 'live');\n assert.equal(stale.complete, true);\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'meta/llama-test',\n name: 'Llama Test',\n input: ['text'],\n contextWindow: 65536,\n maxTokens: 4096,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, [\n OPENCLAW_CATALOGS.nvidia.url,\n 'https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json',\n ]);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, null);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: null,\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its bundled OpenClaw seed', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'openrouter/auto',\n 'moonshotai/kimi-k2.6',\n 'moonshotai/kimi-k2.5',\n ]);\n assert.equal(result.fallback.state, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n { name: 'command-a-plus-05-2026', is_deprecated: false },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 128000);\n assert.equal(result.models[0].maxOutputTokens, 64000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches live accessible models from the daily OpenClaw catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-openclaw-enrich-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-synced',\n name: 'Command Synced',\n input: ['text', 'image'],\n contextWindow: 200000,\n maxTokens: 16000,\n reasoning: true,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.cohere.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-synced' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command Synced');\n assert.equal(result.models[0].contextWindow, 200000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: 1000000,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-chat',\n expectedContext: 1000000,\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS[entry.provider].url) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled catalog');\n }\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('static-backed discovery treats a malformed successful payload as refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n const result = await zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response('{\"unexpected\":true}');\n },\n });\n assert.ok(result.models.length > 0);\n assert.match(result.warnings.at(-1), /live catalog refresh failed/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] }));\n },\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cache.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery classifies generateContent Gemini image models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/gemini-3.1-flash-image',\n displayName: 'Gemini 3.1 Flash Image',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 65536,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gemini-3.1-pro',\n 'gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('malformed xAI suppression refresh retains the bundled suppressions', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-malformed-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n if (url.includes('raw.githubusercontent.com')) {\n return new Response(JSON.stringify({ unexpected: true }));\n }\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.match(result.warnings[0], /bundled snapshot/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n});\n\ntest('xAI discovery removes OpenClaw-suppressed models without sending its API key to GitHub', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === 'https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/xai/openclaw.plugin.json') {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify({\n modelCatalog: {\n discovery: { xai: 'refreshable' },\n suppressions: [{ provider: 'xai', model: 'grok-multi-agent' }],\n },\n }));\n }\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) => model.id.endsWith(':cloud')));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery does not wait for a stalled cloud catalog refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-nonblocking-'));\n let releaseCloud;\n const cloudBlocked = new Promise((resolve) => { releaseCloud = resolve; });\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n if (String(url).includes('raw.githubusercontent.com')) {\n await cloudBlocked;\n throw new Error('offline');\n }\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n releaseCloud();\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cache.state, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'nvidia/featured',\n name: 'Featured',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cache.state, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.deepEqual(refreshed.models.map((model) => model.id), [\n 'nvidia/featured',\n 'private/model',\n ]);\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cache.state, 'fresh');\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n inventoryComplete: true,\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (String(url).startsWith('https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/')) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled metadata');\n }\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/openclaw-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "b2e469b9cc0e5e09cedc6e18cd91a373db2ea5ed": {"t": 1785758827.8689177, "n": 61636, "h": "0ba29067dc6ae293", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst {\n CATALOG_TTL_MS,\n OPENCLAW_CATALOGS,\n loadOpenClawCatalog,\n parseOpenClawCatalog,\n} = require('../src/model-discovery/openclaw-catalog');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('OpenClaw catalog sync includes the extended static providers and preserves Ollama Cloud', () => {\n assert.deepEqual(Object.keys(OPENCLAW_CATALOGS).sort(), [\n 'cohere', 'deepseek', 'moonshot', 'nvidia', 'ollama-cloud', 'zai',\n ]);\n assert.equal(CATALOG_TTL_MS, 24 * 60 * 60 * 1000);\n for (const entry of Object.values(OPENCLAW_CATALOGS)) {\n const url = new URL(entry.url);\n assert.equal(url.protocol, 'https:');\n assert.equal(url.hostname, 'raw.githubusercontent.com');\n assert.match(url.pathname, /^\\/openclaw\\/openclaw\\/main\\/extensions\\//u);\n assert.match(url.pathname, /\\/openclaw\\.plugin\\.json$/u);\n }\n assert.equal(OPENCLAW_CATALOGS.ollama, undefined);\n});\n\ntest('extended OpenClaw static catalogs use bundled first-run fallbacks', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'extended-openclaw-bundled-'));\n try {\n for (const provider of ['zai', 'moonshot', 'deepseek']) {\n const result = await loadOpenClawCatalog({\n provider,\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.state, 'bundled');\n assert.ok(result.models.length > 0, `${provider} must bundle model rows`);\n }\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama Cloud catalog parsing requires the distinct cloud provider base URL', () => {\n const payload = {\n modelCatalog: {\n providers: {\n 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [{\n id: 'cloud-test:cloud',\n name: 'Cloud Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8192,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('ollama-cloud', payload);\n assert.deepEqual(models.map((model) => model.id), ['cloud-test:cloud']);\n assert.equal(models[0].toolCalling, true);\n payload.modelCatalog.providers['ollama-cloud'].baseUrl = 'http://localhost:11434';\n assert.throws(() => parseOpenClawCatalog('ollama-cloud', payload), /base URL/i);\n});\n\ntest('bundled provider snapshots preserve provider-native Ollama and Moonshot capabilities', () => {\n const ollamaCloud = require('../src/model-discovery/catalogs/openclaw/ollama-cloud.json');\n const ollamaModels = new Map(\n ollamaCloud.modelCatalog.providers['ollama-cloud'].models.map((model) => [model.id, model]),\n );\n assert.equal(ollamaModels.get('kimi-k2.5:cloud').contextWindow, 262144);\n assert.deepEqual(ollamaModels.get('kimi-k2.5:cloud').input, ['text', 'image']);\n assert.equal(ollamaModels.get('minimax-m2.7:cloud').contextWindow, 196608);\n assert.equal(ollamaModels.get('glm-5.1:cloud').contextWindow, 202752);\n\n const moonshotCatalog = require('../src/model-discovery/catalogs/openclaw/moonshot.json');\n const moonshotModels = new Map(\n moonshotCatalog.modelCatalog.providers.moonshot.models.map((model) => [model.id, model]),\n );\n assert.equal(moonshotModels.get('kimi-k2.6').reasoning, true);\n assert.equal(moonshotModels.get('kimi-k2.5').reasoning, true);\n});\n\ntest('provider-native corrections override stale OpenClaw catalog metadata', () => {\n const ollamaModels = parseOpenClawCatalog('ollama-cloud', {\n modelCatalog: { providers: { 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [\n { id: 'kimi-k2.5:cloud', input: ['text'], contextWindow: 128000 },\n { id: 'minimax-m2.7:cloud', input: ['text'], contextWindow: 128000 },\n { id: 'glm-5.1:cloud', input: ['text'], contextWindow: 128000 },\n ],\n } } },\n });\n assert.deepEqual(ollamaModels.map((model) => ({\n id: model.id,\n contextWindow: model.contextWindow,\n inputModalities: model.inputModalities,\n })), [\n { id: 'kimi-k2.5:cloud', contextWindow: 262144, inputModalities: ['text', 'image'] },\n { id: 'minimax-m2.7:cloud', contextWindow: 196608, inputModalities: ['text'] },\n { id: 'glm-5.1:cloud', contextWindow: 202752, inputModalities: ['text'] },\n ]);\n\n const moonshotModels = parseOpenClawCatalog('moonshot', {\n modelCatalog: { providers: { moonshot: {\n baseUrl: 'https://api.moonshot.ai/v1',\n models: [\n { id: 'kimi-k2.6', input: ['text', 'image'] },\n { id: 'kimi-k2.5', input: ['text', 'image'] },\n ],\n } } },\n });\n assert.deepEqual(moonshotModels.map((model) => model.reasoning), [true, true]);\n});\n\ntest('OpenClaw catalog parsing validates provider identity and drops deprecated models', () => {\n const payload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [\n {\n id: 'vendor/current',\n name: 'Current',\n input: ['text', 'image'],\n contextWindow: 131072,\n maxTokens: 8192,\n reasoning: true,\n compat: { supportsTools: true },\n },\n {\n id: 'vendor/old',\n name: 'Old',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4096,\n status: 'deprecated',\n },\n ],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('nvidia', payload);\n assert.deepEqual(models.map((model) => model.id), ['vendor/current']);\n assert.deepEqual(models[0].inputModalities, ['text', 'image']);\n assert.equal(models[0].reasoning, true);\n assert.equal(models[0].toolCalling, true);\n assert.equal(models[0].source, 'openclaw-static');\n\n payload.modelCatalog.providers.nvidia.baseUrl = 'https://attacker.example/v1';\n assert.throws(() => parseOpenClawCatalog('nvidia', payload), /base URL/i);\n assert.throws(() => parseOpenClawCatalog('ollama', payload), /unsupported OpenClaw catalog/i);\n});\n\ntest('OpenClaw catalog uses supported provider efforts instead of assuming every Codex level', () => {\n const payload = {\n modelCatalog: {\n providers: {\n zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-capable',\n name: 'GLM Capable',\n input: ['text', 'image'],\n output: ['text'],\n reasoning: true,\n contextWindow: 128000,\n maxTokens: 8192,\n thinkingLevelMap: { low: null, high: 'max', max: 'max' },\n compat: { supportsReasoningEffort: true, supportedReasoningEfforts: ['max'] },\n }],\n },\n },\n },\n };\n const [model] = parseOpenClawCatalog('zai', payload);\n assert.deepEqual(model.inputModalities, ['text', 'image']);\n assert.deepEqual(model.outputModalities, ['text']);\n assert.deepEqual(model.reasoningLevels, ['max']);\n assert.equal(model.metadataSources.outputModalities, 'provider-seed');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-seed');\n});\n\ntest('OpenClaw catalog leaves exact reasoning levels unknown when only configurability is known', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{ id: 'glm-unknown-levels', reasoning: true, compat: { supportsReasoningEffort: true } }],\n } } },\n };\n assert.equal(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, null);\n});\n\ntest('OpenClaw catalog normalizes thinking map values when explicit efforts are absent', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-mapped-levels', reasoning: true,\n thinkingLevelMap: { low: null, high: 'max', xhigh: 'max' },\n }],\n } } },\n };\n assert.deepEqual(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, ['max']);\n});\n\ntest('OpenClaw catalog sync refreshes at most daily and retains the last successful file', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-sync-'));\n let calls = 0;\n const payload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-test',\n name: 'Command Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8000,\n }],\n },\n },\n },\n };\n try {\n const options = {\n provider: 'cohere',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, request) => {\n calls += 1;\n assert.equal(url, OPENCLAW_CATALOGS.cohere.url);\n assert.equal(request.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n },\n };\n const refreshed = await loadOpenClawCatalog(options);\n assert.equal(refreshed.state, 'refreshed');\n assert.deepEqual(refreshed.models.map((model) => model.id), ['command-test']);\n\n const fresh = await loadOpenClawCatalog({\n ...options,\n now: () => 1000 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh catalog must not fetch');\n },\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(calls, 1);\n\n const stale = await loadOpenClawCatalog({\n ...options,\n now: () => 1001 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('offline');\n },\n });\n assert.equal(stale.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['command-test']);\n assert.match(stale.warnings[0], /last successful/i);\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync uses its bundled snapshot on first-run network failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-bundled-'));\n try {\n const result = await loadOpenClawCatalog({\n provider: 'nvidia',\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.state, 'bundled');\n assert.ok(result.models.length > 0);\n assert.match(result.warnings[0], /bundled OpenClaw catalog/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync does not replace caller cancellation with a bundled snapshot', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-cancel-'));\n const controller = new AbortController();\n controller.abort();\n try {\n await assert.rejects(loadOpenClawCatalog({\n provider: 'cohere',\n cacheDir,\n signal: controller.signal,\n fetchImpl: async () => { throw new Error('aborted'); },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery merges the daily OpenClaw catalog behind the live NVIDIA feed', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-merge-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n };\n try {\n const result = await nvidia.discover({\n apiKey: 'nvidia-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [{\n model: 'live/model',\n 'model-name': 'Live Model',\n context: 128000,\n 'max-output': 8000,\n }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['live/model', 'static/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery does not replace caller cancellation with its static catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-cancel-'));\n const controller = new AbortController();\n try {\n await assert.rejects(nvidia.discover({\n cacheDir,\n signal: controller.signal,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n controller.abort();\n throw new Error('aborted');\n },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('Vertex AI OpenAI endpoints resolve as Google without probing', async () => {\n let fetchCalls = 0;\n const result = await resolveProvider({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n fetchImpl: async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n },\n });\n assert.equal(result.provider, 'google');\n assert.equal(result.providerResolution, 'canonical-url');\n assert.equal(fetchCalls, 0);\n});\n\ntest('Vertex Google discovery classifies only explicitly supplied Gemini models', async () => {\n const result = await google.discover({\n baseUrl: 'https://aiplatform.googleapis.com/v1/projects/demo/locations/global/endpoints/openapi',\n suppliedModels: ['google/gemini-2.5-flash', 'google/gemini-3.1-flash-image'],\n fetchImpl: async () => {\n throw new Error('Vertex discovery must not call the Developer API catalog');\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'google/gemini-2.5-flash',\n 'google/gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.complete, false);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return { models: [model], origin: 'live', complete: true };\n });\n assert.equal(first.state, 'refreshed');\n assert.equal(first.origin, 'live');\n assert.equal(first.complete, true);\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(fresh.origin, 'live');\n assert.equal(fresh.complete, true);\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.state, 'stale');\n assert.equal(stale.origin, 'live');\n assert.equal(stale.complete, true);\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'meta/llama-test',\n name: 'Llama Test',\n input: ['text'],\n contextWindow: 65536,\n maxTokens: 4096,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, [\n OPENCLAW_CATALOGS.nvidia.url,\n 'https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json',\n ]);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, null);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: null,\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its bundled OpenClaw seed', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'openrouter/auto',\n 'moonshotai/kimi-k2.6',\n 'moonshotai/kimi-k2.5',\n ]);\n assert.equal(result.fallback.state, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n { name: 'command-a-plus-05-2026', is_deprecated: false },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 128000);\n assert.equal(result.models[0].maxOutputTokens, 64000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches live accessible models from the daily OpenClaw catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-openclaw-enrich-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-synced',\n name: 'Command Synced',\n input: ['text', 'image'],\n contextWindow: 200000,\n maxTokens: 16000,\n reasoning: true,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.cohere.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-synced' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command Synced');\n assert.equal(result.models[0].contextWindow, 200000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: 1000000,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-chat',\n expectedContext: 1000000,\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS[entry.provider].url) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled catalog');\n }\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('static-backed discovery treats a malformed successful payload as refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n const result = await zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response('{\"unexpected\":true}');\n },\n });\n assert.ok(result.models.length > 0);\n assert.match(result.warnings.at(-1), /live catalog refresh failed/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] }));\n },\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cache.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery classifies generateContent Gemini image models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/gemini-3.1-flash-image',\n displayName: 'Gemini 3.1 Flash Image',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 65536,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gemini-3.1-pro',\n 'gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].inputModalities, ['text', 'image', 'audio', 'video', 'document']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('malformed xAI suppression refresh retains the bundled suppressions', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-malformed-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n if (url.includes('raw.githubusercontent.com')) {\n return new Response(JSON.stringify({ unexpected: true }));\n }\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.match(result.warnings[0], /bundled snapshot/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n});\n\ntest('xAI discovery removes OpenClaw-suppressed models without sending its API key to GitHub', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === 'https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/xai/openclaw.plugin.json') {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify({\n modelCatalog: {\n discovery: { xai: 'refreshable' },\n suppressions: [{ provider: 'xai', model: 'grok-multi-agent' }],\n },\n }));\n }\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) => model.id.endsWith(':cloud')));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery does not wait for a stalled cloud catalog refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-nonblocking-'));\n let releaseCloud;\n const cloudBlocked = new Promise((resolve) => { releaseCloud = resolve; });\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n if (String(url).includes('raw.githubusercontent.com')) {\n await cloudBlocked;\n throw new Error('offline');\n }\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n releaseCloud();\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cache.state, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'nvidia/featured',\n name: 'Featured',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cache.state, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.deepEqual(refreshed.models.map((model) => model.id), [\n 'nvidia/featured',\n 'private/model',\n ]);\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cache.state, 'fresh');\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n inventoryComplete: true,\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (String(url).startsWith('https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/')) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled metadata');\n }\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/openclaw-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "0c2b3357296d42798e7cad375443d99e658db45c": {"t": 1785758829.5492263, "n": 60316, "h": "4595ad52dd2c8155", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst {\n CATALOG_TTL_MS,\n OPENCLAW_CATALOGS,\n loadOpenClawCatalog,\n parseOpenClawCatalog,\n} = require('../src/model-discovery/openclaw-catalog');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('OpenClaw catalog sync includes the extended static providers and preserves Ollama Cloud', () => {\n assert.deepEqual(Object.keys(OPENCLAW_CATALOGS).sort(), [\n 'cohere', 'deepseek', 'moonshot', 'nvidia', 'ollama-cloud', 'zai',\n ]);\n assert.equal(CATALOG_TTL_MS, 24 * 60 * 60 * 1000);\n for (const entry of Object.values(OPENCLAW_CATALOGS)) {\n const url = new URL(entry.url);\n assert.equal(url.protocol, 'https:');\n assert.equal(url.hostname, 'raw.githubusercontent.com');\n assert.match(url.pathname, /^\\/openclaw\\/openclaw\\/main\\/extensions\\//u);\n assert.match(url.pathname, /\\/openclaw\\.plugin\\.json$/u);\n }\n assert.equal(OPENCLAW_CATALOGS.ollama, undefined);\n});\n\ntest('extended OpenClaw static catalogs use bundled first-run fallbacks', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'extended-openclaw-bundled-'));\n try {\n for (const provider of ['zai', 'moonshot', 'deepseek']) {\n const result = await loadOpenClawCatalog({\n provider,\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.state, 'bundled');\n assert.ok(result.models.length > 0, `${provider} must bundle model rows`);\n }\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama Cloud catalog parsing requires the distinct cloud provider base URL', () => {\n const payload = {\n modelCatalog: {\n providers: {\n 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [{\n id: 'cloud-test:cloud',\n name: 'Cloud Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8192,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('ollama-cloud', payload);\n assert.deepEqual(models.map((model) => model.id), ['cloud-test:cloud']);\n assert.equal(models[0].toolCalling, true);\n payload.modelCatalog.providers['ollama-cloud'].baseUrl = 'http://localhost:11434';\n assert.throws(() => parseOpenClawCatalog('ollama-cloud', payload), /base URL/i);\n});\n\ntest('bundled provider snapshots preserve provider-native Ollama and Moonshot capabilities', () => {\n const ollamaCloud = require('../src/model-discovery/catalogs/openclaw/ollama-cloud.json');\n const ollamaModels = new Map(\n ollamaCloud.modelCatalog.providers['ollama-cloud'].models.map((model) => [model.id, model]),\n );\n assert.equal(ollamaModels.get('kimi-k2.5:cloud').contextWindow, 262144);\n assert.deepEqual(ollamaModels.get('kimi-k2.5:cloud').input, ['text', 'image']);\n assert.equal(ollamaModels.get('minimax-m2.7:cloud').contextWindow, 196608);\n assert.equal(ollamaModels.get('glm-5.1:cloud').contextWindow, 202752);\n\n const moonshotCatalog = require('../src/model-discovery/catalogs/openclaw/moonshot.json');\n const moonshotModels = new Map(\n moonshotCatalog.modelCatalog.providers.moonshot.models.map((model) => [model.id, model]),\n );\n assert.equal(moonshotModels.get('kimi-k2.6').reasoning, true);\n assert.equal(moonshotModels.get('kimi-k2.5').reasoning, true);\n});\n\ntest('provider-native corrections override stale OpenClaw catalog metadata', () => {\n const ollamaModels = parseOpenClawCatalog('ollama-cloud', {\n modelCatalog: { providers: { 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [\n { id: 'kimi-k2.5:cloud', input: ['text'], contextWindow: 128000 },\n { id: 'minimax-m2.7:cloud', input: ['text'], contextWindow: 128000 },\n { id: 'glm-5.1:cloud', input: ['text'], contextWindow: 128000 },\n ],\n } } },\n });\n assert.deepEqual(ollamaModels.map((model) => ({\n id: model.id,\n contextWindow: model.contextWindow,\n inputModalities: model.inputModalities,\n })), [\n { id: 'kimi-k2.5:cloud', contextWindow: 262144, inputModalities: ['text', 'image'] },\n { id: 'minimax-m2.7:cloud', contextWindow: 196608, inputModalities: ['text'] },\n { id: 'glm-5.1:cloud', contextWindow: 202752, inputModalities: ['text'] },\n ]);\n\n const moonshotModels = parseOpenClawCatalog('moonshot', {\n modelCatalog: { providers: { moonshot: {\n baseUrl: 'https://api.moonshot.ai/v1',\n models: [\n { id: 'kimi-k2.6', input: ['text', 'image'] },\n { id: 'kimi-k2.5', input: ['text', 'image'] },\n ],\n } } },\n });\n assert.deepEqual(moonshotModels.map((model) => model.reasoning), [true, true]);\n});\n\ntest('OpenClaw catalog parsing validates provider identity and drops deprecated models', () => {\n const payload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [\n {\n id: 'vendor/current',\n name: 'Current',\n input: ['text', 'image'],\n contextWindow: 131072,\n maxTokens: 8192,\n reasoning: true,\n compat: { supportsTools: true },\n },\n {\n id: 'vendor/old',\n name: 'Old',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4096,\n status: 'deprecated',\n },\n ],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('nvidia', payload);\n assert.deepEqual(models.map((model) => model.id), ['vendor/current']);\n assert.deepEqual(models[0].inputModalities, ['text', 'image']);\n assert.equal(models[0].reasoning, true);\n assert.equal(models[0].toolCalling, true);\n assert.equal(models[0].source, 'openclaw-static');\n\n payload.modelCatalog.providers.nvidia.baseUrl = 'https://attacker.example/v1';\n assert.throws(() => parseOpenClawCatalog('nvidia', payload), /base URL/i);\n assert.throws(() => parseOpenClawCatalog('ollama', payload), /unsupported OpenClaw catalog/i);\n});\n\ntest('OpenClaw catalog uses supported provider efforts instead of assuming every Codex level', () => {\n const payload = {\n modelCatalog: {\n providers: {\n zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-capable',\n name: 'GLM Capable',\n input: ['text', 'image'],\n output: ['text'],\n reasoning: true,\n contextWindow: 128000,\n maxTokens: 8192,\n thinkingLevelMap: { low: null, high: 'max', max: 'max' },\n compat: { supportsReasoningEffort: true, supportedReasoningEfforts: ['max'] },\n }],\n },\n },\n },\n };\n const [model] = parseOpenClawCatalog('zai', payload);\n assert.deepEqual(model.inputModalities, ['text', 'image']);\n assert.deepEqual(model.outputModalities, ['text']);\n assert.deepEqual(model.reasoningLevels, ['max']);\n assert.equal(model.metadataSources.outputModalities, 'provider-seed');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-seed');\n});\n\ntest('OpenClaw catalog leaves exact reasoning levels unknown when only configurability is known', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{ id: 'glm-unknown-levels', reasoning: true, compat: { supportsReasoningEffort: true } }],\n } } },\n };\n assert.equal(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, null);\n});\n\ntest('OpenClaw catalog normalizes thinking map values when explicit efforts are absent', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-mapped-levels', reasoning: true,\n thinkingLevelMap: { low: null, high: 'max', xhigh: 'max' },\n }],\n } } },\n };\n assert.deepEqual(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, ['max']);\n});\n\ntest('OpenClaw catalog sync refreshes at most daily and retains the last successful file', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-sync-'));\n let calls = 0;\n const payload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-test',\n name: 'Command Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8000,\n }],\n },\n },\n },\n };\n try {\n const options = {\n provider: 'cohere',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, request) => {\n calls += 1;\n assert.equal(url, OPENCLAW_CATALOGS.cohere.url);\n assert.equal(request.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n },\n };\n const refreshed = await loadOpenClawCatalog(options);\n assert.equal(refreshed.state, 'refreshed');\n assert.deepEqual(refreshed.models.map((model) => model.id), ['command-test']);\n\n const fresh = await loadOpenClawCatalog({\n ...options,\n now: () => 1000 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh catalog must not fetch');\n },\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(calls, 1);\n\n const stale = await loadOpenClawCatalog({\n ...options,\n now: () => 1001 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('offline');\n },\n });\n assert.equal(stale.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['command-test']);\n assert.match(stale.warnings[0], /last successful/i);\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync uses its bundled snapshot on first-run network failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-bundled-'));\n try {\n const result = await loadOpenClawCatalog({\n provider: 'nvidia',\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.state, 'bundled');\n assert.ok(result.models.length > 0);\n assert.match(result.warnings[0], /bundled OpenClaw catalog/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync does not replace caller cancellation with a bundled snapshot', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-cancel-'));\n const controller = new AbortController();\n controller.abort();\n try {\n await assert.rejects(loadOpenClawCatalog({\n provider: 'cohere',\n cacheDir,\n signal: controller.signal,\n fetchImpl: async () => { throw new Error('aborted'); },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery merges the daily OpenClaw catalog behind the live NVIDIA feed', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-merge-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n };\n try {\n const result = await nvidia.discover({\n apiKey: 'nvidia-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [{\n model: 'live/model',\n 'model-name': 'Live Model',\n context: 128000,\n 'max-output': 8000,\n }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['live/model', 'static/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery does not replace caller cancellation with its static catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-cancel-'));\n const controller = new AbortController();\n try {\n await assert.rejects(nvidia.discover({\n cacheDir,\n signal: controller.signal,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n controller.abort();\n throw new Error('aborted');\n },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return { models: [model], origin: 'live', complete: true };\n });\n assert.equal(first.state, 'refreshed');\n assert.equal(first.origin, 'live');\n assert.equal(first.complete, true);\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(fresh.origin, 'live');\n assert.equal(fresh.complete, true);\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.state, 'stale');\n assert.equal(stale.origin, 'live');\n assert.equal(stale.complete, true);\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'meta/llama-test',\n name: 'Llama Test',\n input: ['text'],\n contextWindow: 65536,\n maxTokens: 4096,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, [\n OPENCLAW_CATALOGS.nvidia.url,\n 'https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json',\n ]);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, null);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: null,\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its bundled OpenClaw seed', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'openrouter/auto',\n 'moonshotai/kimi-k2.6',\n 'moonshotai/kimi-k2.5',\n ]);\n assert.equal(result.fallback.state, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n { name: 'command-a-plus-05-2026', is_deprecated: false },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 128000);\n assert.equal(result.models[0].maxOutputTokens, 64000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches live accessible models from the daily OpenClaw catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-openclaw-enrich-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-synced',\n name: 'Command Synced',\n input: ['text', 'image'],\n contextWindow: 200000,\n maxTokens: 16000,\n reasoning: true,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.cohere.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-synced' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command Synced');\n assert.equal(result.models[0].contextWindow, 200000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: 1000000,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-chat',\n expectedContext: 1000000,\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS[entry.provider].url) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled catalog');\n }\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('static-backed discovery treats a malformed successful payload as refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n const result = await zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response('{\"unexpected\":true}');\n },\n });\n assert.ok(result.models.length > 0);\n assert.match(result.warnings.at(-1), /live catalog refresh failed/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] }));\n },\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cache.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery classifies generateContent Gemini image models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/gemini-3.1-flash-image',\n displayName: 'Gemini 3.1 Flash Image',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 65536,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'gemini-3.1-pro',\n 'gemini-3.1-flash-image',\n ]);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.deepEqual(result.models[0].outputModalities, ['text']);\n assert.deepEqual(result.models[1].inputModalities, ['text', 'image']);\n assert.deepEqual(result.models[1].outputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('malformed xAI suppression refresh retains the bundled suppressions', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-malformed-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n if (url.includes('raw.githubusercontent.com')) {\n return new Response(JSON.stringify({ unexpected: true }));\n }\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.match(result.warnings[0], /bundled snapshot/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n});\n\ntest('xAI discovery removes OpenClaw-suppressed models without sending its API key to GitHub', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === 'https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/xai/openclaw.plugin.json') {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify({\n modelCatalog: {\n discovery: { xai: 'refreshable' },\n suppressions: [{ provider: 'xai', model: 'grok-multi-agent' }],\n },\n }));\n }\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) => model.id.endsWith(':cloud')));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery does not wait for a stalled cloud catalog refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-nonblocking-'));\n let releaseCloud;\n const cloudBlocked = new Promise((resolve) => { releaseCloud = resolve; });\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n if (String(url).includes('raw.githubusercontent.com')) {\n await cloudBlocked;\n throw new Error('offline');\n }\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n releaseCloud();\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cache.state, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'nvidia/featured',\n name: 'Featured',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cache.state, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.deepEqual(refreshed.models.map((model) => model.id), [\n 'nvidia/featured',\n 'private/model',\n ]);\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cache.state, 'fresh');\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n inventoryComplete: true,\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (String(url).startsWith('https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/')) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled metadata');\n }\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/openclaw-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "3851d1757ed2bb129fbddb1b2fa8dfda51566944": {"t": 1785758831.540693, "n": 59824, "h": "d324f1625eca8605", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst {\n CATALOG_TTL_MS,\n OPENCLAW_CATALOGS,\n loadOpenClawCatalog,\n parseOpenClawCatalog,\n} = require('../src/model-discovery/openclaw-catalog');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('OpenClaw catalog sync includes the extended static providers and preserves Ollama Cloud', () => {\n assert.deepEqual(Object.keys(OPENCLAW_CATALOGS).sort(), [\n 'cohere', 'deepseek', 'moonshot', 'nvidia', 'ollama-cloud', 'zai',\n ]);\n assert.equal(CATALOG_TTL_MS, 24 * 60 * 60 * 1000);\n for (const entry of Object.values(OPENCLAW_CATALOGS)) {\n const url = new URL(entry.url);\n assert.equal(url.protocol, 'https:');\n assert.equal(url.hostname, 'raw.githubusercontent.com');\n assert.match(url.pathname, /^\\/openclaw\\/openclaw\\/main\\/extensions\\//u);\n assert.match(url.pathname, /\\/openclaw\\.plugin\\.json$/u);\n }\n assert.equal(OPENCLAW_CATALOGS.ollama, undefined);\n});\n\ntest('extended OpenClaw static catalogs use bundled first-run fallbacks', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'extended-openclaw-bundled-'));\n try {\n for (const provider of ['zai', 'moonshot', 'deepseek']) {\n const result = await loadOpenClawCatalog({\n provider,\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.state, 'bundled');\n assert.ok(result.models.length > 0, `${provider} must bundle model rows`);\n }\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama Cloud catalog parsing requires the distinct cloud provider base URL', () => {\n const payload = {\n modelCatalog: {\n providers: {\n 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [{\n id: 'cloud-test:cloud',\n name: 'Cloud Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8192,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('ollama-cloud', payload);\n assert.deepEqual(models.map((model) => model.id), ['cloud-test:cloud']);\n assert.equal(models[0].toolCalling, true);\n payload.modelCatalog.providers['ollama-cloud'].baseUrl = 'http://localhost:11434';\n assert.throws(() => parseOpenClawCatalog('ollama-cloud', payload), /base URL/i);\n});\n\ntest('bundled provider snapshots preserve provider-native Ollama and Moonshot capabilities', () => {\n const ollamaCloud = require('../src/model-discovery/catalogs/openclaw/ollama-cloud.json');\n const ollamaModels = new Map(\n ollamaCloud.modelCatalog.providers['ollama-cloud'].models.map((model) => [model.id, model]),\n );\n assert.equal(ollamaModels.get('kimi-k2.5:cloud').contextWindow, 262144);\n assert.deepEqual(ollamaModels.get('kimi-k2.5:cloud').input, ['text', 'image']);\n assert.equal(ollamaModels.get('minimax-m2.7:cloud').contextWindow, 196608);\n assert.equal(ollamaModels.get('glm-5.1:cloud').contextWindow, 202752);\n\n const moonshotCatalog = require('../src/model-discovery/catalogs/openclaw/moonshot.json');\n const moonshotModels = new Map(\n moonshotCatalog.modelCatalog.providers.moonshot.models.map((model) => [model.id, model]),\n );\n assert.equal(moonshotModels.get('kimi-k2.6').reasoning, true);\n assert.equal(moonshotModels.get('kimi-k2.5').reasoning, true);\n});\n\ntest('provider-native corrections override stale OpenClaw catalog metadata', () => {\n const ollamaModels = parseOpenClawCatalog('ollama-cloud', {\n modelCatalog: { providers: { 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [\n { id: 'kimi-k2.5:cloud', input: ['text'], contextWindow: 128000 },\n { id: 'minimax-m2.7:cloud', input: ['text'], contextWindow: 128000 },\n { id: 'glm-5.1:cloud', input: ['text'], contextWindow: 128000 },\n ],\n } } },\n });\n assert.deepEqual(ollamaModels.map((model) => ({\n id: model.id,\n contextWindow: model.contextWindow,\n inputModalities: model.inputModalities,\n })), [\n { id: 'kimi-k2.5:cloud', contextWindow: 262144, inputModalities: ['text', 'image'] },\n { id: 'minimax-m2.7:cloud', contextWindow: 196608, inputModalities: ['text'] },\n { id: 'glm-5.1:cloud', contextWindow: 202752, inputModalities: ['text'] },\n ]);\n\n const moonshotModels = parseOpenClawCatalog('moonshot', {\n modelCatalog: { providers: { moonshot: {\n baseUrl: 'https://api.moonshot.ai/v1',\n models: [\n { id: 'kimi-k2.6', input: ['text', 'image'] },\n { id: 'kimi-k2.5', input: ['text', 'image'] },\n ],\n } } },\n });\n assert.deepEqual(moonshotModels.map((model) => model.reasoning), [true, true]);\n});\n\ntest('OpenClaw catalog parsing validates provider identity and drops deprecated models', () => {\n const payload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [\n {\n id: 'vendor/current',\n name: 'Current',\n input: ['text', 'image'],\n contextWindow: 131072,\n maxTokens: 8192,\n reasoning: true,\n compat: { supportsTools: true },\n },\n {\n id: 'vendor/old',\n name: 'Old',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4096,\n status: 'deprecated',\n },\n ],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('nvidia', payload);\n assert.deepEqual(models.map((model) => model.id), ['vendor/current']);\n assert.deepEqual(models[0].inputModalities, ['text', 'image']);\n assert.equal(models[0].reasoning, true);\n assert.equal(models[0].toolCalling, true);\n assert.equal(models[0].source, 'openclaw-static');\n\n payload.modelCatalog.providers.nvidia.baseUrl = 'https://attacker.example/v1';\n assert.throws(() => parseOpenClawCatalog('nvidia', payload), /base URL/i);\n assert.throws(() => parseOpenClawCatalog('ollama', payload), /unsupported OpenClaw catalog/i);\n});\n\ntest('OpenClaw catalog uses supported provider efforts instead of assuming every Codex level', () => {\n const payload = {\n modelCatalog: {\n providers: {\n zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-capable',\n name: 'GLM Capable',\n input: ['text', 'image'],\n output: ['text'],\n reasoning: true,\n contextWindow: 128000,\n maxTokens: 8192,\n thinkingLevelMap: { low: null, high: 'max', max: 'max' },\n compat: { supportsReasoningEffort: true, supportedReasoningEfforts: ['max'] },\n }],\n },\n },\n },\n };\n const [model] = parseOpenClawCatalog('zai', payload);\n assert.deepEqual(model.inputModalities, ['text', 'image']);\n assert.deepEqual(model.outputModalities, ['text']);\n assert.deepEqual(model.reasoningLevels, ['max']);\n assert.equal(model.metadataSources.outputModalities, 'provider-seed');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-seed');\n});\n\ntest('OpenClaw catalog leaves exact reasoning levels unknown when only configurability is known', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{ id: 'glm-unknown-levels', reasoning: true, compat: { supportsReasoningEffort: true } }],\n } } },\n };\n assert.equal(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, null);\n});\n\ntest('OpenClaw catalog normalizes thinking map values when explicit efforts are absent', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-mapped-levels', reasoning: true,\n thinkingLevelMap: { low: null, high: 'max', xhigh: 'max' },\n }],\n } } },\n };\n assert.deepEqual(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, ['max']);\n});\n\ntest('OpenClaw catalog sync refreshes at most daily and retains the last successful file', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-sync-'));\n let calls = 0;\n const payload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-test',\n name: 'Command Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8000,\n }],\n },\n },\n },\n };\n try {\n const options = {\n provider: 'cohere',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, request) => {\n calls += 1;\n assert.equal(url, OPENCLAW_CATALOGS.cohere.url);\n assert.equal(request.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n },\n };\n const refreshed = await loadOpenClawCatalog(options);\n assert.equal(refreshed.state, 'refreshed');\n assert.deepEqual(refreshed.models.map((model) => model.id), ['command-test']);\n\n const fresh = await loadOpenClawCatalog({\n ...options,\n now: () => 1000 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh catalog must not fetch');\n },\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(calls, 1);\n\n const stale = await loadOpenClawCatalog({\n ...options,\n now: () => 1001 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('offline');\n },\n });\n assert.equal(stale.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['command-test']);\n assert.match(stale.warnings[0], /last successful/i);\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync uses its bundled snapshot on first-run network failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-bundled-'));\n try {\n const result = await loadOpenClawCatalog({\n provider: 'nvidia',\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.state, 'bundled');\n assert.ok(result.models.length > 0);\n assert.match(result.warnings[0], /bundled OpenClaw catalog/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync does not replace caller cancellation with a bundled snapshot', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-cancel-'));\n const controller = new AbortController();\n controller.abort();\n try {\n await assert.rejects(loadOpenClawCatalog({\n provider: 'cohere',\n cacheDir,\n signal: controller.signal,\n fetchImpl: async () => { throw new Error('aborted'); },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery merges the daily OpenClaw catalog behind the live NVIDIA feed', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-merge-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n };\n try {\n const result = await nvidia.discover({\n apiKey: 'nvidia-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [{\n model: 'live/model',\n 'model-name': 'Live Model',\n context: 128000,\n 'max-output': 8000,\n }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['live/model', 'static/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery does not replace caller cancellation with its static catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-cancel-'));\n const controller = new AbortController();\n try {\n await assert.rejects(nvidia.discover({\n cacheDir,\n signal: controller.signal,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n controller.abort();\n throw new Error('aborted');\n },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return { models: [model], origin: 'live', complete: true };\n });\n assert.equal(first.state, 'refreshed');\n assert.equal(first.origin, 'live');\n assert.equal(first.complete, true);\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.state, 'fresh');\n assert.equal(fresh.origin, 'live');\n assert.equal(fresh.complete, true);\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.state, 'stale');\n assert.equal(stale.origin, 'live');\n assert.equal(stale.complete, true);\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.state, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'meta/llama-test',\n name: 'Llama Test',\n input: ['text'],\n contextWindow: 65536,\n maxTokens: 4096,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, [\n OPENCLAW_CATALOGS.nvidia.url,\n 'https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json',\n ]);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, null);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: null,\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its bundled OpenClaw seed', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'openrouter/auto',\n 'moonshotai/kimi-k2.6',\n 'moonshotai/kimi-k2.5',\n ]);\n assert.equal(result.fallback.state, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n { name: 'command-a-plus-05-2026', is_deprecated: false },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 128000);\n assert.equal(result.models[0].maxOutputTokens, 64000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches live accessible models from the daily OpenClaw catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-openclaw-enrich-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-synced',\n name: 'Command Synced',\n input: ['text', 'image'],\n contextWindow: 200000,\n maxTokens: 16000,\n reasoning: true,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.cohere.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-synced' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command Synced');\n assert.equal(result.models[0].contextWindow, 200000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: 1000000,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-chat',\n expectedContext: 1000000,\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS[entry.provider].url) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled catalog');\n }\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('static-backed discovery treats a malformed successful payload as refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n const result = await zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response('{\"unexpected\":true}');\n },\n });\n assert.ok(result.models.length > 0);\n assert.match(result.warnings.at(-1), /live catalog refresh failed/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] }));\n },\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cache.state, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery uses the native catalog and keeps only generateContent text models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['gemini-3.1-pro']);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('malformed xAI suppression refresh retains the bundled suppressions', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-malformed-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n if (url.includes('raw.githubusercontent.com')) {\n return new Response(JSON.stringify({ unexpected: true }));\n }\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.match(result.warnings[0], /bundled snapshot/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n});\n\ntest('xAI discovery removes OpenClaw-suppressed models without sending its API key to GitHub', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === 'https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/xai/openclaw.plugin.json') {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify({\n modelCatalog: {\n discovery: { xai: 'refreshable' },\n suppressions: [{ provider: 'xai', model: 'grok-multi-agent' }],\n },\n }));\n }\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) => model.id.endsWith(':cloud')));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery does not wait for a stalled cloud catalog refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-nonblocking-'));\n let releaseCloud;\n const cloudBlocked = new Promise((resolve) => { releaseCloud = resolve; });\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n if (String(url).includes('raw.githubusercontent.com')) {\n await cloudBlocked;\n throw new Error('offline');\n }\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n releaseCloud();\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cache.state, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'nvidia/featured',\n name: 'Featured',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cache.state, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.deepEqual(refreshed.models.map((model) => model.id), [\n 'nvidia/featured',\n 'private/model',\n ]);\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cache.state, 'fresh');\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n inventoryComplete: true,\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (String(url).startsWith('https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/')) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled metadata');\n }\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/openclaw-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "25a0f55664650458236a53de60f5041463c11499": {"t": 1785758833.4316566, "n": 62534, "h": "adf1fe6fd42d8430", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst {\n CATALOG_TTL_MS,\n OPENCLAW_CATALOGS,\n loadOpenClawCatalog,\n parseOpenClawCatalog,\n} = require('../src/model-discovery/openclaw-catalog');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('OpenClaw catalog sync includes the extended static providers and preserves Ollama Cloud', () => {\n assert.deepEqual(Object.keys(OPENCLAW_CATALOGS).sort(), [\n 'cohere', 'deepseek', 'moonshot', 'nvidia', 'ollama-cloud', 'zai',\n ]);\n assert.equal(CATALOG_TTL_MS, 24 * 60 * 60 * 1000);\n for (const entry of Object.values(OPENCLAW_CATALOGS)) {\n const url = new URL(entry.url);\n assert.equal(url.protocol, 'https:');\n assert.equal(url.hostname, 'raw.githubusercontent.com');\n assert.match(url.pathname, /^\\/openclaw\\/openclaw\\/main\\/extensions\\//u);\n assert.match(url.pathname, /\\/openclaw\\.plugin\\.json$/u);\n }\n assert.equal(OPENCLAW_CATALOGS.ollama, undefined);\n});\n\ntest('extended OpenClaw static catalogs use bundled first-run fallbacks', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'extended-openclaw-bundled-'));\n try {\n for (const provider of ['zai', 'moonshot', 'deepseek']) {\n const result = await loadOpenClawCatalog({\n provider,\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.cacheStatus, 'bundled');\n assert.ok(result.models.length > 0, `${provider} must bundle model rows`);\n }\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama Cloud catalog parsing requires the distinct cloud provider base URL', () => {\n const payload = {\n modelCatalog: {\n providers: {\n 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [{\n id: 'cloud-test:cloud',\n name: 'Cloud Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8192,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('ollama-cloud', payload);\n assert.deepEqual(models.map((model) => model.id), ['cloud-test:cloud']);\n assert.equal(models[0].toolCalling, true);\n payload.modelCatalog.providers['ollama-cloud'].baseUrl = 'http://localhost:11434';\n assert.throws(() => parseOpenClawCatalog('ollama-cloud', payload), /base URL/i);\n});\n\ntest('bundled provider snapshots preserve provider-native Ollama and Moonshot capabilities', () => {\n const ollamaCloud = require('../src/model-discovery/catalogs/openclaw/ollama-cloud.json');\n const ollamaModels = new Map(\n ollamaCloud.modelCatalog.providers['ollama-cloud'].models.map((model) => [model.id, model]),\n );\n assert.equal(ollamaModels.get('kimi-k2.5:cloud').contextWindow, 262144);\n assert.deepEqual(ollamaModels.get('kimi-k2.5:cloud').input, ['text', 'image']);\n assert.equal(ollamaModels.get('minimax-m2.7:cloud').contextWindow, 196608);\n assert.equal(ollamaModels.get('glm-5.1:cloud').contextWindow, 202752);\n\n const moonshotCatalog = require('../src/model-discovery/catalogs/openclaw/moonshot.json');\n const moonshotModels = new Map(\n moonshotCatalog.modelCatalog.providers.moonshot.models.map((model) => [model.id, model]),\n );\n assert.equal(moonshotModels.get('kimi-k2.6').reasoning, true);\n assert.equal(moonshotModels.get('kimi-k2.5').reasoning, true);\n});\n\ntest('provider-native corrections override stale OpenClaw catalog metadata', () => {\n const ollamaModels = parseOpenClawCatalog('ollama-cloud', {\n modelCatalog: { providers: { 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [\n { id: 'kimi-k2.5:cloud', input: ['text'], contextWindow: 128000 },\n { id: 'minimax-m2.7:cloud', input: ['text'], contextWindow: 128000 },\n { id: 'glm-5.1:cloud', input: ['text'], contextWindow: 128000 },\n ],\n } } },\n });\n assert.deepEqual(ollamaModels.map((model) => ({\n id: model.id,\n contextWindow: model.contextWindow,\n inputModalities: model.inputModalities,\n })), [\n { id: 'kimi-k2.5:cloud', contextWindow: 262144, inputModalities: ['text', 'image'] },\n { id: 'minimax-m2.7:cloud', contextWindow: 196608, inputModalities: ['text'] },\n { id: 'glm-5.1:cloud', contextWindow: 202752, inputModalities: ['text'] },\n ]);\n\n const moonshotModels = parseOpenClawCatalog('moonshot', {\n modelCatalog: { providers: { moonshot: {\n baseUrl: 'https://api.moonshot.ai/v1',\n models: [\n { id: 'kimi-k2.6', input: ['text', 'image'] },\n { id: 'kimi-k2.5', input: ['text', 'image'] },\n ],\n } } },\n });\n assert.deepEqual(moonshotModels.map((model) => model.reasoning), [true, true]);\n});\n\ntest('OpenClaw catalog parsing validates provider identity and drops deprecated models', () => {\n const payload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [\n {\n id: 'vendor/current',\n name: 'Current',\n input: ['text', 'image'],\n contextWindow: 131072,\n maxTokens: 8192,\n reasoning: true,\n compat: { supportsTools: true },\n },\n {\n id: 'vendor/old',\n name: 'Old',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4096,\n status: 'deprecated',\n },\n ],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('nvidia', payload);\n assert.deepEqual(models.map((model) => model.id), ['vendor/current']);\n assert.deepEqual(models[0].inputModalities, ['text', 'image']);\n assert.equal(models[0].reasoning, true);\n assert.equal(models[0].toolCalling, true);\n assert.equal(models[0].source, 'openclaw-static');\n\n payload.modelCatalog.providers.nvidia.baseUrl = 'https://attacker.example/v1';\n assert.throws(() => parseOpenClawCatalog('nvidia', payload), /base URL/i);\n assert.throws(() => parseOpenClawCatalog('ollama', payload), /unsupported OpenClaw catalog/i);\n});\n\ntest('OpenClaw catalog uses supported provider efforts instead of assuming every Codex level', () => {\n const payload = {\n modelCatalog: {\n providers: {\n zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-capable',\n name: 'GLM Capable',\n input: ['text', 'image'],\n output: ['text'],\n reasoning: true,\n contextWindow: 128000,\n maxTokens: 8192,\n thinkingLevelMap: { low: null, high: 'max', max: 'max' },\n compat: { supportsReasoningEffort: true, supportedReasoningEfforts: ['max'] },\n }],\n },\n },\n },\n };\n const [model] = parseOpenClawCatalog('zai', payload);\n assert.deepEqual(model.inputModalities, ['text', 'image']);\n assert.deepEqual(model.outputModalities, ['text']);\n assert.deepEqual(model.reasoningLevels, ['max']);\n assert.equal(model.metadataSources.outputModalities, 'provider-seed');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-seed');\n});\n\ntest('OpenClaw catalog leaves exact reasoning levels unknown when only configurability is known', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{ id: 'glm-unknown-levels', reasoning: true, compat: { supportsReasoningEffort: true } }],\n } } },\n };\n assert.equal(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, null);\n});\n\ntest('OpenClaw catalog normalizes thinking map values when explicit efforts are absent', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-mapped-levels', reasoning: true,\n thinkingLevelMap: { low: null, high: 'max', xhigh: 'max' },\n }],\n } } },\n };\n assert.deepEqual(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, ['max']);\n});\n\ntest('OpenClaw catalog sync refreshes at most daily and retains the last successful file', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-sync-'));\n let calls = 0;\n const payload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-test',\n name: 'Command Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8000,\n }],\n },\n },\n },\n };\n try {\n const options = {\n provider: 'cohere',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, request) => {\n calls += 1;\n assert.equal(url, OPENCLAW_CATALOGS.cohere.url);\n assert.equal(request.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n },\n };\n const refreshed = await loadOpenClawCatalog(options);\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.deepEqual(refreshed.models.map((model) => model.id), ['command-test']);\n\n const fresh = await loadOpenClawCatalog({\n ...options,\n now: () => 1000 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh catalog must not fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 1);\n\n const stale = await loadOpenClawCatalog({\n ...options,\n now: () => 1001 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('offline');\n },\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['command-test']);\n assert.match(stale.warnings[0], /last successful/i);\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync uses its bundled snapshot on first-run network failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-bundled-'));\n try {\n const result = await loadOpenClawCatalog({\n provider: 'nvidia',\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.cacheStatus, 'bundled');\n assert.ok(result.models.length > 0);\n assert.match(result.warnings[0], /bundled OpenClaw catalog/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync does not replace caller cancellation with a bundled snapshot', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-cancel-'));\n const controller = new AbortController();\n controller.abort();\n try {\n await assert.rejects(loadOpenClawCatalog({\n provider: 'cohere',\n cacheDir,\n signal: controller.signal,\n fetchImpl: async () => { throw new Error('aborted'); },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery merges the daily OpenClaw catalog behind the live NVIDIA feed', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-merge-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n };\n try {\n const result = await nvidia.discover({\n apiKey: 'nvidia-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [{\n model: 'live/model',\n 'model-name': 'Live Model',\n context: 128000,\n 'max-output': 8000,\n }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['live/model', 'static/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery does not replace caller cancellation with its static catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-cancel-'));\n const controller = new AbortController();\n try {\n await assert.rejects(nvidia.discover({\n cacheDir,\n signal: controller.signal,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n controller.abort();\n throw new Error('aborted');\n },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return { models: [model], origin: 'live', complete: true };\n });\n assert.equal(first.cacheStatus, 'refreshed');\n assert.equal(first.origin, 'live');\n assert.equal(first.complete, true);\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(fresh.origin, 'live');\n assert.equal(fresh.complete, true);\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.equal(stale.origin, 'live');\n assert.equal(stale.complete, true);\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache upgrades legacy models with unknown rich capability metadata', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-legacy-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const legacy = normalizeSuppliedModels(['provider/model'])[0];\n delete legacy.outputModalities;\n delete legacy.reasoningLevels;\n delete legacy.metadataSources.outputModalities;\n delete legacy.metadataSources.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 1,\n provider: options.provider,\n endpointDigest: identity.endpointDigest,\n authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000,\n models: [legacy],\n }));\n const fresh = await withProviderCache(options, async () => { throw new Error('must not refresh'); });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(fresh.models[0].outputModalities, null);\n assert.equal(fresh.models[0].reasoningLevels, null);\n assert.equal(fresh.models[0].metadataSources.outputModalities, null);\n assert.equal(fresh.models[0].metadataSources.reasoningLevels, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache writes schema version 2 after upgrading version 1', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 1, now: () => 2000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const legacy = normalizeSuppliedModels(['provider/legacy'])[0];\n delete legacy.outputModalities;\n delete legacy.reasoningLevels;\n delete legacy.metadataSources.outputModalities;\n delete legacy.metadataSources.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 1, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [legacy],\n }));\n await withProviderCache(options, async () => normalizeSuppliedModels(['provider/current']));\n assert.equal(JSON.parse(fs.readFileSync(identity.file, 'utf8')).schemaVersion, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.cacheStatus, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.cacheStatus, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'meta/llama-test',\n name: 'Llama Test',\n input: ['text'],\n contextWindow: 65536,\n maxTokens: 4096,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, [\n OPENCLAW_CATALOGS.nvidia.url,\n 'https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json',\n ]);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, null);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: null,\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its bundled OpenClaw seed', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'openrouter/auto',\n 'moonshotai/kimi-k2.6',\n 'moonshotai/kimi-k2.5',\n ]);\n assert.equal(result.fallback.cacheStatus, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n { name: 'command-a-plus-05-2026', is_deprecated: false },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 128000);\n assert.equal(result.models[0].maxOutputTokens, 64000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches live accessible models from the daily OpenClaw catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-openclaw-enrich-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-synced',\n name: 'Command Synced',\n input: ['text', 'image'],\n contextWindow: 200000,\n maxTokens: 16000,\n reasoning: true,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.cohere.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-synced' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command Synced');\n assert.equal(result.models[0].contextWindow, 200000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: 1000000,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-chat',\n expectedContext: 1000000,\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS[entry.provider].url) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled catalog');\n }\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('static-backed discovery treats a malformed successful payload as refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n const result = await zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response('{\"unexpected\":true}');\n },\n });\n assert.ok(result.models.length > 0);\n assert.match(result.warnings.at(-1), /live catalog refresh failed/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] }));\n },\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery uses the native catalog and keeps only generateContent text models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['gemini-3.1-pro']);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('malformed xAI suppression refresh retains the bundled suppressions', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-malformed-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n if (url.includes('raw.githubusercontent.com')) {\n return new Response(JSON.stringify({ unexpected: true }));\n }\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.match(result.warnings[0], /bundled snapshot/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n});\n\ntest('xAI discovery removes OpenClaw-suppressed models without sending its API key to GitHub', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === 'https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/xai/openclaw.plugin.json') {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify({\n modelCatalog: {\n discovery: { xai: 'refreshable' },\n suppressions: [{ provider: 'xai', model: 'grok-multi-agent' }],\n },\n }));\n }\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) => model.id.endsWith(':cloud')));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery does not wait for a stalled cloud catalog refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-nonblocking-'));\n let releaseCloud;\n const cloudBlocked = new Promise((resolve) => { releaseCloud = resolve; });\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n if (String(url).includes('raw.githubusercontent.com')) {\n await cloudBlocked;\n throw new Error('offline');\n }\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n releaseCloud();\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cacheStatus, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'nvidia/featured',\n name: 'Featured',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.deepEqual(refreshed.models.map((model) => model.id), [\n 'nvidia/featured',\n 'private/model',\n ]);\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n inventoryComplete: true,\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (String(url).startsWith('https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/')) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled metadata');\n }\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/openclaw-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "f70e49a44991ae8b8a36423f5a2bcb03552f131a": {"t": 1785758835.0526366, "n": 62250, "h": "7782d8c85c593aab", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst {\n CATALOG_TTL_MS,\n OPENCLAW_CATALOGS,\n loadOpenClawCatalog,\n parseOpenClawCatalog,\n} = require('../src/model-discovery/openclaw-catalog');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('OpenClaw catalog sync includes the extended static providers and preserves Ollama Cloud', () => {\n assert.deepEqual(Object.keys(OPENCLAW_CATALOGS).sort(), [\n 'cohere', 'deepseek', 'moonshot', 'nvidia', 'ollama-cloud', 'zai',\n ]);\n assert.equal(CATALOG_TTL_MS, 24 * 60 * 60 * 1000);\n for (const entry of Object.values(OPENCLAW_CATALOGS)) {\n const url = new URL(entry.url);\n assert.equal(url.protocol, 'https:');\n assert.equal(url.hostname, 'raw.githubusercontent.com');\n assert.match(url.pathname, /^\\/openclaw\\/openclaw\\/main\\/extensions\\//u);\n assert.match(url.pathname, /\\/openclaw\\.plugin\\.json$/u);\n }\n assert.equal(OPENCLAW_CATALOGS.ollama, undefined);\n});\n\ntest('extended OpenClaw static catalogs use bundled first-run fallbacks', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'extended-openclaw-bundled-'));\n try {\n for (const provider of ['zai', 'moonshot', 'deepseek']) {\n const result = await loadOpenClawCatalog({\n provider,\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.cacheStatus, 'bundled');\n assert.ok(result.models.length > 0, `${provider} must bundle model rows`);\n }\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama Cloud catalog parsing requires the distinct cloud provider base URL', () => {\n const payload = {\n modelCatalog: {\n providers: {\n 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [{\n id: 'cloud-test:cloud',\n name: 'Cloud Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8192,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('ollama-cloud', payload);\n assert.deepEqual(models.map((model) => model.id), ['cloud-test:cloud']);\n assert.equal(models[0].toolCalling, true);\n payload.modelCatalog.providers['ollama-cloud'].baseUrl = 'http://localhost:11434';\n assert.throws(() => parseOpenClawCatalog('ollama-cloud', payload), /base URL/i);\n});\n\ntest('bundled provider snapshots preserve provider-native Ollama and Moonshot capabilities', () => {\n const ollamaCloud = require('../src/model-discovery/catalogs/openclaw/ollama-cloud.json');\n const ollamaModels = new Map(\n ollamaCloud.modelCatalog.providers['ollama-cloud'].models.map((model) => [model.id, model]),\n );\n assert.equal(ollamaModels.get('kimi-k2.5:cloud').contextWindow, 262144);\n assert.deepEqual(ollamaModels.get('kimi-k2.5:cloud').input, ['text', 'image']);\n assert.equal(ollamaModels.get('minimax-m2.7:cloud').contextWindow, 196608);\n assert.equal(ollamaModels.get('glm-5.1:cloud').contextWindow, 202752);\n\n const moonshotCatalog = require('../src/model-discovery/catalogs/openclaw/moonshot.json');\n const moonshotModels = new Map(\n moonshotCatalog.modelCatalog.providers.moonshot.models.map((model) => [model.id, model]),\n );\n assert.equal(moonshotModels.get('kimi-k2.6').reasoning, true);\n assert.equal(moonshotModels.get('kimi-k2.5').reasoning, true);\n});\n\ntest('provider-native corrections override stale OpenClaw catalog metadata', () => {\n const ollamaModels = parseOpenClawCatalog('ollama-cloud', {\n modelCatalog: { providers: { 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [\n { id: 'kimi-k2.5:cloud', input: ['text'], contextWindow: 128000 },\n { id: 'minimax-m2.7:cloud', input: ['text'], contextWindow: 128000 },\n { id: 'glm-5.1:cloud', input: ['text'], contextWindow: 128000 },\n ],\n } } },\n });\n assert.deepEqual(ollamaModels.map((model) => ({\n id: model.id,\n contextWindow: model.contextWindow,\n inputModalities: model.inputModalities,\n })), [\n { id: 'kimi-k2.5:cloud', contextWindow: 262144, inputModalities: ['text', 'image'] },\n { id: 'minimax-m2.7:cloud', contextWindow: 196608, inputModalities: ['text'] },\n { id: 'glm-5.1:cloud', contextWindow: 202752, inputModalities: ['text'] },\n ]);\n\n const moonshotModels = parseOpenClawCatalog('moonshot', {\n modelCatalog: { providers: { moonshot: {\n baseUrl: 'https://api.moonshot.ai/v1',\n models: [\n { id: 'kimi-k2.6', input: ['text', 'image'] },\n { id: 'kimi-k2.5', input: ['text', 'image'] },\n ],\n } } },\n });\n assert.deepEqual(moonshotModels.map((model) => model.reasoning), [true, true]);\n});\n\ntest('OpenClaw catalog parsing validates provider identity and drops deprecated models', () => {\n const payload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [\n {\n id: 'vendor/current',\n name: 'Current',\n input: ['text', 'image'],\n contextWindow: 131072,\n maxTokens: 8192,\n reasoning: true,\n compat: { supportsTools: true },\n },\n {\n id: 'vendor/old',\n name: 'Old',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4096,\n status: 'deprecated',\n },\n ],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('nvidia', payload);\n assert.deepEqual(models.map((model) => model.id), ['vendor/current']);\n assert.deepEqual(models[0].inputModalities, ['text', 'image']);\n assert.equal(models[0].reasoning, true);\n assert.equal(models[0].toolCalling, true);\n assert.equal(models[0].source, 'openclaw-static');\n\n payload.modelCatalog.providers.nvidia.baseUrl = 'https://attacker.example/v1';\n assert.throws(() => parseOpenClawCatalog('nvidia', payload), /base URL/i);\n assert.throws(() => parseOpenClawCatalog('ollama', payload), /unsupported OpenClaw catalog/i);\n});\n\ntest('OpenClaw catalog uses supported provider efforts instead of assuming every Codex level', () => {\n const payload = {\n modelCatalog: {\n providers: {\n zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-capable',\n name: 'GLM Capable',\n input: ['text', 'image'],\n output: ['text'],\n reasoning: true,\n contextWindow: 128000,\n maxTokens: 8192,\n thinkingLevelMap: { low: null, high: 'max', max: 'max' },\n compat: { supportsReasoningEffort: true, supportedReasoningEfforts: ['max'] },\n }],\n },\n },\n },\n };\n const [model] = parseOpenClawCatalog('zai', payload);\n assert.deepEqual(model.inputModalities, ['text', 'image']);\n assert.deepEqual(model.outputModalities, ['text']);\n assert.deepEqual(model.reasoningLevels, ['max']);\n assert.equal(model.metadataSources.outputModalities, 'provider-seed');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-seed');\n});\n\ntest('OpenClaw catalog leaves exact reasoning levels unknown when only configurability is known', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{ id: 'glm-unknown-levels', reasoning: true, compat: { supportsReasoningEffort: true } }],\n } } },\n };\n assert.equal(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, null);\n});\n\ntest('OpenClaw catalog normalizes thinking map values when explicit efforts are absent', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-mapped-levels', reasoning: true,\n thinkingLevelMap: { low: null, high: 'max', xhigh: 'max' },\n }],\n } } },\n };\n assert.deepEqual(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, ['max']);\n});\n\ntest('OpenClaw catalog sync refreshes at most daily and retains the last successful file', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-sync-'));\n let calls = 0;\n const payload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-test',\n name: 'Command Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8000,\n }],\n },\n },\n },\n };\n try {\n const options = {\n provider: 'cohere',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, request) => {\n calls += 1;\n assert.equal(url, OPENCLAW_CATALOGS.cohere.url);\n assert.equal(request.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n },\n };\n const refreshed = await loadOpenClawCatalog(options);\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.deepEqual(refreshed.models.map((model) => model.id), ['command-test']);\n\n const fresh = await loadOpenClawCatalog({\n ...options,\n now: () => 1000 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh catalog must not fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 1);\n\n const stale = await loadOpenClawCatalog({\n ...options,\n now: () => 1001 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('offline');\n },\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['command-test']);\n assert.match(stale.warnings[0], /last successful/i);\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync uses its bundled snapshot on first-run network failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-bundled-'));\n try {\n const result = await loadOpenClawCatalog({\n provider: 'nvidia',\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.cacheStatus, 'bundled');\n assert.ok(result.models.length > 0);\n assert.match(result.warnings[0], /bundled OpenClaw catalog/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync does not replace caller cancellation with a bundled snapshot', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-cancel-'));\n const controller = new AbortController();\n controller.abort();\n try {\n await assert.rejects(loadOpenClawCatalog({\n provider: 'cohere',\n cacheDir,\n signal: controller.signal,\n fetchImpl: async () => { throw new Error('aborted'); },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery merges the daily OpenClaw catalog behind the live NVIDIA feed', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-merge-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n };\n try {\n const result = await nvidia.discover({\n apiKey: 'nvidia-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [{\n model: 'live/model',\n 'model-name': 'Live Model',\n context: 128000,\n 'max-output': 8000,\n }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['live/model', 'static/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery does not replace caller cancellation with its static catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-cancel-'));\n const controller = new AbortController();\n try {\n await assert.rejects(nvidia.discover({\n cacheDir,\n signal: controller.signal,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n controller.abort();\n throw new Error('aborted');\n },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return [model];\n });\n assert.equal(first.cacheStatus, 'refreshed');\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache upgrades legacy models with unknown rich capability metadata', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-legacy-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const legacy = normalizeSuppliedModels(['provider/model'])[0];\n delete legacy.outputModalities;\n delete legacy.reasoningLevels;\n delete legacy.metadataSources.outputModalities;\n delete legacy.metadataSources.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 1,\n provider: options.provider,\n endpointDigest: identity.endpointDigest,\n authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000,\n models: [legacy],\n }));\n const fresh = await withProviderCache(options, async () => { throw new Error('must not refresh'); });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(fresh.models[0].outputModalities, null);\n assert.equal(fresh.models[0].reasoningLevels, null);\n assert.equal(fresh.models[0].metadataSources.outputModalities, null);\n assert.equal(fresh.models[0].metadataSources.reasoningLevels, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache writes schema version 2 after upgrading version 1', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 1, now: () => 2000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const legacy = normalizeSuppliedModels(['provider/legacy'])[0];\n delete legacy.outputModalities;\n delete legacy.reasoningLevels;\n delete legacy.metadataSources.outputModalities;\n delete legacy.metadataSources.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 1, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [legacy],\n }));\n await withProviderCache(options, async () => normalizeSuppliedModels(['provider/current']));\n assert.equal(JSON.parse(fs.readFileSync(identity.file, 'utf8')).schemaVersion, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.cacheStatus, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.cacheStatus, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'meta/llama-test',\n name: 'Llama Test',\n input: ['text'],\n contextWindow: 65536,\n maxTokens: 4096,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, [\n OPENCLAW_CATALOGS.nvidia.url,\n 'https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json',\n ]);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, null);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: null,\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its bundled OpenClaw seed', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'openrouter/auto',\n 'moonshotai/kimi-k2.6',\n 'moonshotai/kimi-k2.5',\n ]);\n assert.equal(result.fallback.cacheStatus, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n { name: 'command-a-plus-05-2026', is_deprecated: false },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 128000);\n assert.equal(result.models[0].maxOutputTokens, 64000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches live accessible models from the daily OpenClaw catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-openclaw-enrich-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-synced',\n name: 'Command Synced',\n input: ['text', 'image'],\n contextWindow: 200000,\n maxTokens: 16000,\n reasoning: true,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.cohere.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-synced' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command Synced');\n assert.equal(result.models[0].contextWindow, 200000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: 1000000,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-chat',\n expectedContext: 1000000,\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS[entry.provider].url) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled catalog');\n }\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('static-backed discovery treats a malformed successful payload as refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n const result = await zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response('{\"unexpected\":true}');\n },\n });\n assert.ok(result.models.length > 0);\n assert.match(result.warnings.at(-1), /live catalog refresh failed/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] }));\n },\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery uses the native catalog and keeps only generateContent text models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['gemini-3.1-pro']);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('malformed xAI suppression refresh retains the bundled suppressions', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-malformed-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n if (url.includes('raw.githubusercontent.com')) {\n return new Response(JSON.stringify({ unexpected: true }));\n }\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.match(result.warnings[0], /bundled snapshot/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n});\n\ntest('xAI discovery removes OpenClaw-suppressed models without sending its API key to GitHub', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === 'https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/xai/openclaw.plugin.json') {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify({\n modelCatalog: {\n discovery: { xai: 'refreshable' },\n suppressions: [{ provider: 'xai', model: 'grok-multi-agent' }],\n },\n }));\n }\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) => model.id.endsWith(':cloud')));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery does not wait for a stalled cloud catalog refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-nonblocking-'));\n let releaseCloud;\n const cloudBlocked = new Promise((resolve) => { releaseCloud = resolve; });\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n if (String(url).includes('raw.githubusercontent.com')) {\n await cloudBlocked;\n throw new Error('offline');\n }\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n releaseCloud();\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cacheStatus, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'nvidia/featured',\n name: 'Featured',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n inventoryComplete: false,\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.deepEqual(refreshed.models.map((model) => model.id), [\n 'nvidia/featured',\n 'private/model',\n ]);\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n inventoryComplete: true,\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (String(url).startsWith('https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/')) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled metadata');\n }\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/openclaw-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "3faf870ed0216c9f3e0bda7dcd01543c1d41fece": {"t": 1785758836.5005844, "n": 62159, "h": "7ae454a7aaa1f759", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst {\n CATALOG_TTL_MS,\n OPENCLAW_CATALOGS,\n loadOpenClawCatalog,\n parseOpenClawCatalog,\n} = require('../src/model-discovery/openclaw-catalog');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('OpenClaw catalog sync includes the extended static providers and preserves Ollama Cloud', () => {\n assert.deepEqual(Object.keys(OPENCLAW_CATALOGS).sort(), [\n 'cohere', 'deepseek', 'moonshot', 'nvidia', 'ollama-cloud', 'zai',\n ]);\n assert.equal(CATALOG_TTL_MS, 24 * 60 * 60 * 1000);\n for (const entry of Object.values(OPENCLAW_CATALOGS)) {\n const url = new URL(entry.url);\n assert.equal(url.protocol, 'https:');\n assert.equal(url.hostname, 'raw.githubusercontent.com');\n assert.match(url.pathname, /^\\/openclaw\\/openclaw\\/main\\/extensions\\//u);\n assert.match(url.pathname, /\\/openclaw\\.plugin\\.json$/u);\n }\n assert.equal(OPENCLAW_CATALOGS.ollama, undefined);\n});\n\ntest('extended OpenClaw static catalogs use bundled first-run fallbacks', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'extended-openclaw-bundled-'));\n try {\n for (const provider of ['zai', 'moonshot', 'deepseek']) {\n const result = await loadOpenClawCatalog({\n provider,\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.cacheStatus, 'bundled');\n assert.ok(result.models.length > 0, `${provider} must bundle model rows`);\n }\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama Cloud catalog parsing requires the distinct cloud provider base URL', () => {\n const payload = {\n modelCatalog: {\n providers: {\n 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [{\n id: 'cloud-test:cloud',\n name: 'Cloud Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8192,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('ollama-cloud', payload);\n assert.deepEqual(models.map((model) => model.id), ['cloud-test:cloud']);\n assert.equal(models[0].toolCalling, true);\n payload.modelCatalog.providers['ollama-cloud'].baseUrl = 'http://localhost:11434';\n assert.throws(() => parseOpenClawCatalog('ollama-cloud', payload), /base URL/i);\n});\n\ntest('bundled provider snapshots preserve provider-native Ollama and Moonshot capabilities', () => {\n const ollamaCloud = require('../src/model-discovery/catalogs/openclaw/ollama-cloud.json');\n const ollamaModels = new Map(\n ollamaCloud.modelCatalog.providers['ollama-cloud'].models.map((model) => [model.id, model]),\n );\n assert.equal(ollamaModels.get('kimi-k2.5:cloud').contextWindow, 262144);\n assert.deepEqual(ollamaModels.get('kimi-k2.5:cloud').input, ['text', 'image']);\n assert.equal(ollamaModels.get('minimax-m2.7:cloud').contextWindow, 196608);\n assert.equal(ollamaModels.get('glm-5.1:cloud').contextWindow, 202752);\n\n const moonshotCatalog = require('../src/model-discovery/catalogs/openclaw/moonshot.json');\n const moonshotModels = new Map(\n moonshotCatalog.modelCatalog.providers.moonshot.models.map((model) => [model.id, model]),\n );\n assert.equal(moonshotModels.get('kimi-k2.6').reasoning, true);\n assert.equal(moonshotModels.get('kimi-k2.5').reasoning, true);\n});\n\ntest('provider-native corrections override stale OpenClaw catalog metadata', () => {\n const ollamaModels = parseOpenClawCatalog('ollama-cloud', {\n modelCatalog: { providers: { 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [\n { id: 'kimi-k2.5:cloud', input: ['text'], contextWindow: 128000 },\n { id: 'minimax-m2.7:cloud', input: ['text'], contextWindow: 128000 },\n { id: 'glm-5.1:cloud', input: ['text'], contextWindow: 128000 },\n ],\n } } },\n });\n assert.deepEqual(ollamaModels.map((model) => ({\n id: model.id,\n contextWindow: model.contextWindow,\n inputModalities: model.inputModalities,\n })), [\n { id: 'kimi-k2.5:cloud', contextWindow: 262144, inputModalities: ['text', 'image'] },\n { id: 'minimax-m2.7:cloud', contextWindow: 196608, inputModalities: ['text'] },\n { id: 'glm-5.1:cloud', contextWindow: 202752, inputModalities: ['text'] },\n ]);\n\n const moonshotModels = parseOpenClawCatalog('moonshot', {\n modelCatalog: { providers: { moonshot: {\n baseUrl: 'https://api.moonshot.ai/v1',\n models: [\n { id: 'kimi-k2.6', input: ['text', 'image'] },\n { id: 'kimi-k2.5', input: ['text', 'image'] },\n ],\n } } },\n });\n assert.deepEqual(moonshotModels.map((model) => model.reasoning), [true, true]);\n});\n\ntest('OpenClaw catalog parsing validates provider identity and drops deprecated models', () => {\n const payload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [\n {\n id: 'vendor/current',\n name: 'Current',\n input: ['text', 'image'],\n contextWindow: 131072,\n maxTokens: 8192,\n reasoning: true,\n compat: { supportsTools: true },\n },\n {\n id: 'vendor/old',\n name: 'Old',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4096,\n status: 'deprecated',\n },\n ],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('nvidia', payload);\n assert.deepEqual(models.map((model) => model.id), ['vendor/current']);\n assert.deepEqual(models[0].inputModalities, ['text', 'image']);\n assert.equal(models[0].reasoning, true);\n assert.equal(models[0].toolCalling, true);\n assert.equal(models[0].source, 'openclaw-static');\n\n payload.modelCatalog.providers.nvidia.baseUrl = 'https://attacker.example/v1';\n assert.throws(() => parseOpenClawCatalog('nvidia', payload), /base URL/i);\n assert.throws(() => parseOpenClawCatalog('ollama', payload), /unsupported OpenClaw catalog/i);\n});\n\ntest('OpenClaw catalog uses supported provider efforts instead of assuming every Codex level', () => {\n const payload = {\n modelCatalog: {\n providers: {\n zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-capable',\n name: 'GLM Capable',\n input: ['text', 'image'],\n output: ['text'],\n reasoning: true,\n contextWindow: 128000,\n maxTokens: 8192,\n thinkingLevelMap: { low: null, high: 'max', max: 'max' },\n compat: { supportsReasoningEffort: true, supportedReasoningEfforts: ['max'] },\n }],\n },\n },\n },\n };\n const [model] = parseOpenClawCatalog('zai', payload);\n assert.deepEqual(model.inputModalities, ['text', 'image']);\n assert.deepEqual(model.outputModalities, ['text']);\n assert.deepEqual(model.reasoningLevels, ['max']);\n assert.equal(model.metadataSources.outputModalities, 'provider-seed');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-seed');\n});\n\ntest('OpenClaw catalog leaves exact reasoning levels unknown when only configurability is known', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{ id: 'glm-unknown-levels', reasoning: true, compat: { supportsReasoningEffort: true } }],\n } } },\n };\n assert.equal(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, null);\n});\n\ntest('OpenClaw catalog normalizes thinking map values when explicit efforts are absent', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-mapped-levels', reasoning: true,\n thinkingLevelMap: { low: null, high: 'max', xhigh: 'max' },\n }],\n } } },\n };\n assert.deepEqual(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, ['max']);\n});\n\ntest('OpenClaw catalog sync refreshes at most daily and retains the last successful file', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-sync-'));\n let calls = 0;\n const payload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-test',\n name: 'Command Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8000,\n }],\n },\n },\n },\n };\n try {\n const options = {\n provider: 'cohere',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, request) => {\n calls += 1;\n assert.equal(url, OPENCLAW_CATALOGS.cohere.url);\n assert.equal(request.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n },\n };\n const refreshed = await loadOpenClawCatalog(options);\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.deepEqual(refreshed.models.map((model) => model.id), ['command-test']);\n\n const fresh = await loadOpenClawCatalog({\n ...options,\n now: () => 1000 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh catalog must not fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 1);\n\n const stale = await loadOpenClawCatalog({\n ...options,\n now: () => 1001 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('offline');\n },\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['command-test']);\n assert.match(stale.warnings[0], /last successful/i);\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync uses its bundled snapshot on first-run network failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-bundled-'));\n try {\n const result = await loadOpenClawCatalog({\n provider: 'nvidia',\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.cacheStatus, 'bundled');\n assert.ok(result.models.length > 0);\n assert.match(result.warnings[0], /bundled OpenClaw catalog/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync does not replace caller cancellation with a bundled snapshot', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-cancel-'));\n const controller = new AbortController();\n controller.abort();\n try {\n await assert.rejects(loadOpenClawCatalog({\n provider: 'cohere',\n cacheDir,\n signal: controller.signal,\n fetchImpl: async () => { throw new Error('aborted'); },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery merges the daily OpenClaw catalog behind the live NVIDIA feed', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-merge-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n };\n try {\n const result = await nvidia.discover({\n apiKey: 'nvidia-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [{\n model: 'live/model',\n 'model-name': 'Live Model',\n context: 128000,\n 'max-output': 8000,\n }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['live/model', 'static/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery does not replace caller cancellation with its static catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-cancel-'));\n const controller = new AbortController();\n try {\n await assert.rejects(nvidia.discover({\n cacheDir,\n signal: controller.signal,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n controller.abort();\n throw new Error('aborted');\n },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return [model];\n });\n assert.equal(first.cacheStatus, 'refreshed');\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache upgrades legacy models with unknown rich capability metadata', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-legacy-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const legacy = normalizeSuppliedModels(['provider/model'])[0];\n delete legacy.outputModalities;\n delete legacy.reasoningLevels;\n delete legacy.metadataSources.outputModalities;\n delete legacy.metadataSources.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 1,\n provider: options.provider,\n endpointDigest: identity.endpointDigest,\n authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000,\n models: [legacy],\n }));\n const fresh = await withProviderCache(options, async () => { throw new Error('must not refresh'); });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(fresh.models[0].outputModalities, null);\n assert.equal(fresh.models[0].reasoningLevels, null);\n assert.equal(fresh.models[0].metadataSources.outputModalities, null);\n assert.equal(fresh.models[0].metadataSources.reasoningLevels, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache writes schema version 2 after upgrading version 1', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 1, now: () => 2000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const legacy = normalizeSuppliedModels(['provider/legacy'])[0];\n delete legacy.outputModalities;\n delete legacy.reasoningLevels;\n delete legacy.metadataSources.outputModalities;\n delete legacy.metadataSources.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 1, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [legacy],\n }));\n await withProviderCache(options, async () => normalizeSuppliedModels(['provider/current']));\n assert.equal(JSON.parse(fs.readFileSync(identity.file, 'utf8')).schemaVersion, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.cacheStatus, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.cacheStatus, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'meta/llama-test',\n name: 'Llama Test',\n input: ['text'],\n contextWindow: 65536,\n maxTokens: 4096,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, [\n OPENCLAW_CATALOGS.nvidia.url,\n 'https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json',\n ]);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, null);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: null,\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its bundled OpenClaw seed', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'openrouter/auto',\n 'moonshotai/kimi-k2.6',\n 'moonshotai/kimi-k2.5',\n ]);\n assert.equal(result.fallback.cacheStatus, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n { name: 'command-a-plus-05-2026', is_deprecated: false },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 128000);\n assert.equal(result.models[0].maxOutputTokens, 64000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches live accessible models from the daily OpenClaw catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-openclaw-enrich-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-synced',\n name: 'Command Synced',\n input: ['text', 'image'],\n contextWindow: 200000,\n maxTokens: 16000,\n reasoning: true,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.cohere.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-synced' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command Synced');\n assert.equal(result.models[0].contextWindow, 200000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: 1000000,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-chat',\n expectedContext: 1000000,\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS[entry.provider].url) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled catalog');\n }\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('static-backed discovery treats a malformed successful payload as refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n const result = await zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response('{\"unexpected\":true}');\n },\n });\n assert.ok(result.models.length > 0);\n assert.match(result.warnings.at(-1), /live catalog refresh failed/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] }));\n },\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery uses the native catalog and keeps only generateContent text models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['gemini-3.1-pro']);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('malformed xAI suppression refresh retains the bundled suppressions', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-malformed-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n if (url.includes('raw.githubusercontent.com')) {\n return new Response(JSON.stringify({ unexpected: true }));\n }\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.match(result.warnings[0], /bundled snapshot/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n});\n\ntest('xAI discovery removes OpenClaw-suppressed models without sending its API key to GitHub', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === 'https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/xai/openclaw.plugin.json') {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify({\n modelCatalog: {\n discovery: { xai: 'refreshable' },\n suppressions: [{ provider: 'xai', model: 'grok-multi-agent' }],\n },\n }));\n }\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama owns validation and normalization of its standard local native endpoint', () => {\n assert.equal(\n ollama.resolveLocalApiBase('http://localhost:11434/v1/'),\n 'http://localhost:11434',\n );\n assert.equal(\n ollama.resolveLocalApiBase('http://127.0.0.1:11434'),\n 'http://127.0.0.1:11434',\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('https://localhost:11434/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n assert.throws(\n () => ollama.resolveLocalApiBase('http://provider.example/v1'),\n /standard local Ollama HTTP endpoint/i,\n );\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) => model.id.endsWith(':cloud')));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery does not wait for a stalled cloud catalog refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-nonblocking-'));\n let releaseCloud;\n const cloudBlocked = new Promise((resolve) => { releaseCloud = resolve; });\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n if (String(url).includes('raw.githubusercontent.com')) {\n await cloudBlocked;\n throw new Error('offline');\n }\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n releaseCloud();\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.deepEqual(result.traits, {\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(result.cacheStatus, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'nvidia/featured',\n name: 'Featured',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.deepEqual(refreshed.traits, {\n local: false,\n nativeInspection: false,\n supportsCloudPull: false,\n });\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.deepEqual(refreshed.models.map((model) => model.id), [\n 'nvidia/featured',\n 'private/model',\n ]);\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public Ollama discovery exposes local native-inspection traits', async () => {\n const result = await discoverModels({\n baseUrl: 'http://localhost:11434/v1',\n suppliedModels: ['local-model'],\n fetchImpl: async (url) => {\n if (String(url).endsWith('/api/tags')) {\n return new Response(JSON.stringify({ models: [{ name: 'local-model' }] }));\n }\n return new Response(JSON.stringify({\n capabilities: ['completion', 'vision', 'tools'],\n }));\n },\n });\n\n assert.equal(result.provider, 'ollama');\n assert.deepEqual(result.traits, {\n local: true,\n nativeInspection: true,\n supportsCloudPull: true,\n });\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (String(url).startsWith('https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/')) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled metadata');\n }\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/openclaw-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "97a5d2bfeffdaf3c6606f67a4e1fbb165ff9e911": {"t": 1785758838.0118902, "n": 60654, "h": "e9e94364003b9792", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst {\n CATALOG_TTL_MS,\n OPENCLAW_CATALOGS,\n loadOpenClawCatalog,\n parseOpenClawCatalog,\n} = require('../src/model-discovery/openclaw-catalog');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('OpenClaw catalog sync includes the extended static providers and preserves Ollama Cloud', () => {\n assert.deepEqual(Object.keys(OPENCLAW_CATALOGS).sort(), [\n 'cohere', 'deepseek', 'moonshot', 'nvidia', 'ollama-cloud', 'zai',\n ]);\n assert.equal(CATALOG_TTL_MS, 24 * 60 * 60 * 1000);\n for (const entry of Object.values(OPENCLAW_CATALOGS)) {\n const url = new URL(entry.url);\n assert.equal(url.protocol, 'https:');\n assert.equal(url.hostname, 'raw.githubusercontent.com');\n assert.match(url.pathname, /^\\/openclaw\\/openclaw\\/main\\/extensions\\//u);\n assert.match(url.pathname, /\\/openclaw\\.plugin\\.json$/u);\n }\n assert.equal(OPENCLAW_CATALOGS.ollama, undefined);\n});\n\ntest('extended OpenClaw static catalogs use bundled first-run fallbacks', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'extended-openclaw-bundled-'));\n try {\n for (const provider of ['zai', 'moonshot', 'deepseek']) {\n const result = await loadOpenClawCatalog({\n provider,\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.cacheStatus, 'bundled');\n assert.ok(result.models.length > 0, `${provider} must bundle model rows`);\n }\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama Cloud catalog parsing requires the distinct cloud provider base URL', () => {\n const payload = {\n modelCatalog: {\n providers: {\n 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [{\n id: 'cloud-test:cloud',\n name: 'Cloud Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8192,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('ollama-cloud', payload);\n assert.deepEqual(models.map((model) => model.id), ['cloud-test:cloud']);\n assert.equal(models[0].toolCalling, true);\n payload.modelCatalog.providers['ollama-cloud'].baseUrl = 'http://localhost:11434';\n assert.throws(() => parseOpenClawCatalog('ollama-cloud', payload), /base URL/i);\n});\n\ntest('bundled provider snapshots preserve provider-native Ollama and Moonshot capabilities', () => {\n const ollamaCloud = require('../src/model-discovery/catalogs/openclaw/ollama-cloud.json');\n const ollamaModels = new Map(\n ollamaCloud.modelCatalog.providers['ollama-cloud'].models.map((model) => [model.id, model]),\n );\n assert.equal(ollamaModels.get('kimi-k2.5:cloud').contextWindow, 262144);\n assert.deepEqual(ollamaModels.get('kimi-k2.5:cloud').input, ['text', 'image']);\n assert.equal(ollamaModels.get('minimax-m2.7:cloud').contextWindow, 196608);\n assert.equal(ollamaModels.get('glm-5.1:cloud').contextWindow, 202752);\n\n const moonshotCatalog = require('../src/model-discovery/catalogs/openclaw/moonshot.json');\n const moonshotModels = new Map(\n moonshotCatalog.modelCatalog.providers.moonshot.models.map((model) => [model.id, model]),\n );\n assert.equal(moonshotModels.get('kimi-k2.6').reasoning, true);\n assert.equal(moonshotModels.get('kimi-k2.5').reasoning, true);\n});\n\ntest('provider-native corrections override stale OpenClaw catalog metadata', () => {\n const ollamaModels = parseOpenClawCatalog('ollama-cloud', {\n modelCatalog: { providers: { 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [\n { id: 'kimi-k2.5:cloud', input: ['text'], contextWindow: 128000 },\n { id: 'minimax-m2.7:cloud', input: ['text'], contextWindow: 128000 },\n { id: 'glm-5.1:cloud', input: ['text'], contextWindow: 128000 },\n ],\n } } },\n });\n assert.deepEqual(ollamaModels.map((model) => ({\n id: model.id,\n contextWindow: model.contextWindow,\n inputModalities: model.inputModalities,\n })), [\n { id: 'kimi-k2.5:cloud', contextWindow: 262144, inputModalities: ['text', 'image'] },\n { id: 'minimax-m2.7:cloud', contextWindow: 196608, inputModalities: ['text'] },\n { id: 'glm-5.1:cloud', contextWindow: 202752, inputModalities: ['text'] },\n ]);\n\n const moonshotModels = parseOpenClawCatalog('moonshot', {\n modelCatalog: { providers: { moonshot: {\n baseUrl: 'https://api.moonshot.ai/v1',\n models: [\n { id: 'kimi-k2.6', input: ['text', 'image'] },\n { id: 'kimi-k2.5', input: ['text', 'image'] },\n ],\n } } },\n });\n assert.deepEqual(moonshotModels.map((model) => model.reasoning), [true, true]);\n});\n\ntest('OpenClaw catalog parsing validates provider identity and drops deprecated models', () => {\n const payload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [\n {\n id: 'vendor/current',\n name: 'Current',\n input: ['text', 'image'],\n contextWindow: 131072,\n maxTokens: 8192,\n reasoning: true,\n compat: { supportsTools: true },\n },\n {\n id: 'vendor/old',\n name: 'Old',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4096,\n status: 'deprecated',\n },\n ],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('nvidia', payload);\n assert.deepEqual(models.map((model) => model.id), ['vendor/current']);\n assert.deepEqual(models[0].inputModalities, ['text', 'image']);\n assert.equal(models[0].reasoning, true);\n assert.equal(models[0].toolCalling, true);\n assert.equal(models[0].source, 'openclaw-static');\n\n payload.modelCatalog.providers.nvidia.baseUrl = 'https://attacker.example/v1';\n assert.throws(() => parseOpenClawCatalog('nvidia', payload), /base URL/i);\n assert.throws(() => parseOpenClawCatalog('ollama', payload), /unsupported OpenClaw catalog/i);\n});\n\ntest('OpenClaw catalog uses supported provider efforts instead of assuming every Codex level', () => {\n const payload = {\n modelCatalog: {\n providers: {\n zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-capable',\n name: 'GLM Capable',\n input: ['text', 'image'],\n output: ['text'],\n reasoning: true,\n contextWindow: 128000,\n maxTokens: 8192,\n thinkingLevelMap: { low: null, high: 'max', max: 'max' },\n compat: { supportsReasoningEffort: true, supportedReasoningEfforts: ['max'] },\n }],\n },\n },\n },\n };\n const [model] = parseOpenClawCatalog('zai', payload);\n assert.deepEqual(model.inputModalities, ['text', 'image']);\n assert.deepEqual(model.outputModalities, ['text']);\n assert.deepEqual(model.reasoningLevels, ['max']);\n assert.equal(model.metadataSources.outputModalities, 'provider-seed');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-seed');\n});\n\ntest('OpenClaw catalog leaves exact reasoning levels unknown when only configurability is known', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{ id: 'glm-unknown-levels', reasoning: true, compat: { supportsReasoningEffort: true } }],\n } } },\n };\n assert.equal(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, null);\n});\n\ntest('OpenClaw catalog normalizes thinking map values when explicit efforts are absent', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-mapped-levels', reasoning: true,\n thinkingLevelMap: { low: null, high: 'max', xhigh: 'max' },\n }],\n } } },\n };\n assert.deepEqual(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, ['max']);\n});\n\ntest('OpenClaw catalog sync refreshes at most daily and retains the last successful file', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-sync-'));\n let calls = 0;\n const payload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-test',\n name: 'Command Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8000,\n }],\n },\n },\n },\n };\n try {\n const options = {\n provider: 'cohere',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, request) => {\n calls += 1;\n assert.equal(url, OPENCLAW_CATALOGS.cohere.url);\n assert.equal(request.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n },\n };\n const refreshed = await loadOpenClawCatalog(options);\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.deepEqual(refreshed.models.map((model) => model.id), ['command-test']);\n\n const fresh = await loadOpenClawCatalog({\n ...options,\n now: () => 1000 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh catalog must not fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 1);\n\n const stale = await loadOpenClawCatalog({\n ...options,\n now: () => 1001 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('offline');\n },\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['command-test']);\n assert.match(stale.warnings[0], /last successful/i);\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync uses its bundled snapshot on first-run network failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-bundled-'));\n try {\n const result = await loadOpenClawCatalog({\n provider: 'nvidia',\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.cacheStatus, 'bundled');\n assert.ok(result.models.length > 0);\n assert.match(result.warnings[0], /bundled OpenClaw catalog/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync does not replace caller cancellation with a bundled snapshot', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-cancel-'));\n const controller = new AbortController();\n controller.abort();\n try {\n await assert.rejects(loadOpenClawCatalog({\n provider: 'cohere',\n cacheDir,\n signal: controller.signal,\n fetchImpl: async () => { throw new Error('aborted'); },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery merges the daily OpenClaw catalog behind the live NVIDIA feed', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-merge-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n };\n try {\n const result = await nvidia.discover({\n apiKey: 'nvidia-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [{\n model: 'live/model',\n 'model-name': 'Live Model',\n context: 128000,\n 'max-output': 8000,\n }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['live/model', 'static/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery does not replace caller cancellation with its static catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-cancel-'));\n const controller = new AbortController();\n try {\n await assert.rejects(nvidia.discover({\n cacheDir,\n signal: controller.signal,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n controller.abort();\n throw new Error('aborted');\n },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('local Ollama auto-detection reuses tags while remote endpoints resolve as custom without probing', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: 'custom',\n providerResolution: 'custom-url',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return [model];\n });\n assert.equal(first.cacheStatus, 'refreshed');\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache upgrades legacy models with unknown rich capability metadata', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-legacy-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const legacy = normalizeSuppliedModels(['provider/model'])[0];\n delete legacy.outputModalities;\n delete legacy.reasoningLevels;\n delete legacy.metadataSources.outputModalities;\n delete legacy.metadataSources.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 1,\n provider: options.provider,\n endpointDigest: identity.endpointDigest,\n authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000,\n models: [legacy],\n }));\n const fresh = await withProviderCache(options, async () => { throw new Error('must not refresh'); });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(fresh.models[0].outputModalities, null);\n assert.equal(fresh.models[0].reasoningLevels, null);\n assert.equal(fresh.models[0].metadataSources.outputModalities, null);\n assert.equal(fresh.models[0].metadataSources.reasoningLevels, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache writes schema version 2 after upgrading version 1', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 1, now: () => 2000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const legacy = normalizeSuppliedModels(['provider/legacy'])[0];\n delete legacy.outputModalities;\n delete legacy.reasoningLevels;\n delete legacy.metadataSources.outputModalities;\n delete legacy.metadataSources.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 1, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [legacy],\n }));\n await withProviderCache(options, async () => normalizeSuppliedModels(['provider/current']));\n assert.equal(JSON.parse(fs.readFileSync(identity.file, 'utf8')).schemaVersion, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.cacheStatus, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.cacheStatus, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'meta/llama-test',\n name: 'Llama Test',\n input: ['text'],\n contextWindow: 65536,\n maxTokens: 4096,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, [\n OPENCLAW_CATALOGS.nvidia.url,\n 'https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json',\n ]);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, null);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: null,\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its bundled OpenClaw seed', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'openrouter/auto',\n 'moonshotai/kimi-k2.6',\n 'moonshotai/kimi-k2.5',\n ]);\n assert.equal(result.fallback.cacheStatus, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n { name: 'command-a-plus-05-2026', is_deprecated: false },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 128000);\n assert.equal(result.models[0].maxOutputTokens, 64000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches live accessible models from the daily OpenClaw catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-openclaw-enrich-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-synced',\n name: 'Command Synced',\n input: ['text', 'image'],\n contextWindow: 200000,\n maxTokens: 16000,\n reasoning: true,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.cohere.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-synced' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command Synced');\n assert.equal(result.models[0].contextWindow, 200000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: 1000000,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-chat',\n expectedContext: 1000000,\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS[entry.provider].url) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled catalog');\n }\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('static-backed discovery treats a malformed successful payload as refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n const result = await zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response('{\"unexpected\":true}');\n },\n });\n assert.ok(result.models.length > 0);\n assert.match(result.warnings.at(-1), /live catalog refresh failed/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] }));\n },\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery uses the native catalog and keeps only generateContent text models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['gemini-3.1-pro']);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('malformed xAI suppression refresh retains the bundled suppressions', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-malformed-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n if (url.includes('raw.githubusercontent.com')) {\n return new Response(JSON.stringify({ unexpected: true }));\n }\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.match(result.warnings[0], /bundled snapshot/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/allowlisted-provider-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n});\n\ntest('xAI discovery removes OpenClaw-suppressed models without sending its API key to GitHub', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === 'https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/xai/openclaw.plugin.json') {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify({\n modelCatalog: {\n discovery: { xai: 'refreshable' },\n suppressions: [{ provider: 'xai', model: 'grok-multi-agent' }],\n },\n }));\n }\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) => model.id.endsWith(':cloud')));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery does not wait for a stalled cloud catalog refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-nonblocking-'));\n let releaseCloud;\n const cloudBlocked = new Promise((resolve) => { releaseCloud = resolve; });\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n if (String(url).includes('raw.githubusercontent.com')) {\n await cloudBlocked;\n throw new Error('offline');\n }\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n releaseCloud();\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('custom discovery skips the network when no models are supplied', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.cacheStatus, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models, []);\n});\n\ntest('custom discovery retains only supplied model families from noisy catalogs', async () => {\n const unrelated = Array.from({ length: 2000 }, (_, index) => ({ id: `noise/model-${index}` }));\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n apiKey: 'custom-secret',\n suppliedModels: ['deepseek-v4-pro', 'private/model'],\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://custom-provider.example/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer custom-secret');\n return new Response(JSON.stringify({ data: [\n ...unrelated,\n { id: 'deepseek-v4-flash' },\n { id: 'deepseek-v4-pro', context_window: 1000000 },\n { id: 'vendor/deepseek-v4-pro', context_window: 262144 },\n { id: 'deepseek-v4-pro:latest', context_window: 128000 },\n ] }));\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.equal(result.providerResolution, 'custom-url');\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'deepseek-v4-pro',\n 'vendor/deepseek-v4-pro',\n 'deepseek-v4-pro:latest',\n 'private/model',\n ]);\n assert.equal(result.models[0].contextWindow, 1000000);\n});\n\ntest('custom discovery falls back to supplied models when its catalog fails', async () => {\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['deepseek-v4-pro'],\n fetchImpl: async () => {\n throw new Error('offline');\n },\n });\n\n assert.equal(result.provider, 'custom');\n assert.deepEqual(result.models.map((model) => model.id), ['deepseek-v4-pro']);\n assert.match(result.warnings[0], /custom model catalog refresh failed/i);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'nvidia/featured',\n name: 'Featured',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.deepEqual(refreshed.models.map((model) => model.id), [\n 'nvidia/featured',\n 'private/model',\n ]);\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (String(url).startsWith('https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/')) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled metadata');\n }\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/openclaw-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "d2cebdb29891067dc38c9bb67858c1b51cfa12c6": {"t": 1785758839.5337265, "n": 59002, "h": "be52fe95f0745ed8", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst {\n CATALOG_TTL_MS,\n OPENCLAW_CATALOGS,\n loadOpenClawCatalog,\n parseOpenClawCatalog,\n} = require('../src/model-discovery/openclaw-catalog');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('OpenClaw catalog sync includes the extended static providers and preserves Ollama Cloud', () => {\n assert.deepEqual(Object.keys(OPENCLAW_CATALOGS).sort(), [\n 'cohere', 'deepseek', 'moonshot', 'nvidia', 'ollama-cloud', 'zai',\n ]);\n assert.equal(CATALOG_TTL_MS, 24 * 60 * 60 * 1000);\n for (const entry of Object.values(OPENCLAW_CATALOGS)) {\n const url = new URL(entry.url);\n assert.equal(url.protocol, 'https:');\n assert.equal(url.hostname, 'raw.githubusercontent.com');\n assert.match(url.pathname, /^\\/openclaw\\/openclaw\\/main\\/extensions\\//u);\n assert.match(url.pathname, /\\/openclaw\\.plugin\\.json$/u);\n }\n assert.equal(OPENCLAW_CATALOGS.ollama, undefined);\n});\n\ntest('extended OpenClaw static catalogs use bundled first-run fallbacks', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'extended-openclaw-bundled-'));\n try {\n for (const provider of ['zai', 'moonshot', 'deepseek']) {\n const result = await loadOpenClawCatalog({\n provider,\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.cacheStatus, 'bundled');\n assert.ok(result.models.length > 0, `${provider} must bundle model rows`);\n }\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama Cloud catalog parsing requires the distinct cloud provider base URL', () => {\n const payload = {\n modelCatalog: {\n providers: {\n 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [{\n id: 'cloud-test:cloud',\n name: 'Cloud Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8192,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('ollama-cloud', payload);\n assert.deepEqual(models.map((model) => model.id), ['cloud-test:cloud']);\n assert.equal(models[0].toolCalling, true);\n payload.modelCatalog.providers['ollama-cloud'].baseUrl = 'http://localhost:11434';\n assert.throws(() => parseOpenClawCatalog('ollama-cloud', payload), /base URL/i);\n});\n\ntest('bundled provider snapshots preserve provider-native Ollama and Moonshot capabilities', () => {\n const ollamaCloud = require('../src/model-discovery/catalogs/openclaw/ollama-cloud.json');\n const ollamaModels = new Map(\n ollamaCloud.modelCatalog.providers['ollama-cloud'].models.map((model) => [model.id, model]),\n );\n assert.equal(ollamaModels.get('kimi-k2.5:cloud').contextWindow, 262144);\n assert.deepEqual(ollamaModels.get('kimi-k2.5:cloud').input, ['text', 'image']);\n assert.equal(ollamaModels.get('minimax-m2.7:cloud').contextWindow, 196608);\n assert.equal(ollamaModels.get('glm-5.1:cloud').contextWindow, 202752);\n\n const moonshotCatalog = require('../src/model-discovery/catalogs/openclaw/moonshot.json');\n const moonshotModels = new Map(\n moonshotCatalog.modelCatalog.providers.moonshot.models.map((model) => [model.id, model]),\n );\n assert.equal(moonshotModels.get('kimi-k2.6').reasoning, true);\n assert.equal(moonshotModels.get('kimi-k2.5').reasoning, true);\n});\n\ntest('provider-native corrections override stale OpenClaw catalog metadata', () => {\n const ollamaModels = parseOpenClawCatalog('ollama-cloud', {\n modelCatalog: { providers: { 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [\n { id: 'kimi-k2.5:cloud', input: ['text'], contextWindow: 128000 },\n { id: 'minimax-m2.7:cloud', input: ['text'], contextWindow: 128000 },\n { id: 'glm-5.1:cloud', input: ['text'], contextWindow: 128000 },\n ],\n } } },\n });\n assert.deepEqual(ollamaModels.map((model) => ({\n id: model.id,\n contextWindow: model.contextWindow,\n inputModalities: model.inputModalities,\n })), [\n { id: 'kimi-k2.5:cloud', contextWindow: 262144, inputModalities: ['text', 'image'] },\n { id: 'minimax-m2.7:cloud', contextWindow: 196608, inputModalities: ['text'] },\n { id: 'glm-5.1:cloud', contextWindow: 202752, inputModalities: ['text'] },\n ]);\n\n const moonshotModels = parseOpenClawCatalog('moonshot', {\n modelCatalog: { providers: { moonshot: {\n baseUrl: 'https://api.moonshot.ai/v1',\n models: [\n { id: 'kimi-k2.6', input: ['text', 'image'] },\n { id: 'kimi-k2.5', input: ['text', 'image'] },\n ],\n } } },\n });\n assert.deepEqual(moonshotModels.map((model) => model.reasoning), [true, true]);\n});\n\ntest('OpenClaw catalog parsing validates provider identity and drops deprecated models', () => {\n const payload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [\n {\n id: 'vendor/current',\n name: 'Current',\n input: ['text', 'image'],\n contextWindow: 131072,\n maxTokens: 8192,\n reasoning: true,\n compat: { supportsTools: true },\n },\n {\n id: 'vendor/old',\n name: 'Old',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4096,\n status: 'deprecated',\n },\n ],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('nvidia', payload);\n assert.deepEqual(models.map((model) => model.id), ['vendor/current']);\n assert.deepEqual(models[0].inputModalities, ['text', 'image']);\n assert.equal(models[0].reasoning, true);\n assert.equal(models[0].toolCalling, true);\n assert.equal(models[0].source, 'openclaw-static');\n\n payload.modelCatalog.providers.nvidia.baseUrl = 'https://attacker.example/v1';\n assert.throws(() => parseOpenClawCatalog('nvidia', payload), /base URL/i);\n assert.throws(() => parseOpenClawCatalog('ollama', payload), /unsupported OpenClaw catalog/i);\n});\n\ntest('OpenClaw catalog uses supported provider efforts instead of assuming every Codex level', () => {\n const payload = {\n modelCatalog: {\n providers: {\n zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-capable',\n name: 'GLM Capable',\n input: ['text', 'image'],\n output: ['text'],\n reasoning: true,\n contextWindow: 128000,\n maxTokens: 8192,\n thinkingLevelMap: { low: null, high: 'max', max: 'max' },\n compat: { supportsReasoningEffort: true, supportedReasoningEfforts: ['max'] },\n }],\n },\n },\n },\n };\n const [model] = parseOpenClawCatalog('zai', payload);\n assert.deepEqual(model.inputModalities, ['text', 'image']);\n assert.deepEqual(model.outputModalities, ['text']);\n assert.deepEqual(model.reasoningLevels, ['max']);\n assert.equal(model.metadataSources.outputModalities, 'provider-seed');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-seed');\n});\n\ntest('OpenClaw catalog leaves exact reasoning levels unknown when only configurability is known', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{ id: 'glm-unknown-levels', reasoning: true, compat: { supportsReasoningEffort: true } }],\n } } },\n };\n assert.equal(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, null);\n});\n\ntest('OpenClaw catalog normalizes thinking map values when explicit efforts are absent', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-mapped-levels', reasoning: true,\n thinkingLevelMap: { low: null, high: 'max', xhigh: 'max' },\n }],\n } } },\n };\n assert.deepEqual(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, ['max']);\n});\n\ntest('OpenClaw catalog sync refreshes at most daily and retains the last successful file', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-sync-'));\n let calls = 0;\n const payload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-test',\n name: 'Command Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8000,\n }],\n },\n },\n },\n };\n try {\n const options = {\n provider: 'cohere',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, request) => {\n calls += 1;\n assert.equal(url, OPENCLAW_CATALOGS.cohere.url);\n assert.equal(request.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n },\n };\n const refreshed = await loadOpenClawCatalog(options);\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.deepEqual(refreshed.models.map((model) => model.id), ['command-test']);\n\n const fresh = await loadOpenClawCatalog({\n ...options,\n now: () => 1000 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh catalog must not fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 1);\n\n const stale = await loadOpenClawCatalog({\n ...options,\n now: () => 1001 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('offline');\n },\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['command-test']);\n assert.match(stale.warnings[0], /last successful/i);\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync uses its bundled snapshot on first-run network failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-bundled-'));\n try {\n const result = await loadOpenClawCatalog({\n provider: 'nvidia',\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.cacheStatus, 'bundled');\n assert.ok(result.models.length > 0);\n assert.match(result.warnings[0], /bundled OpenClaw catalog/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync does not replace caller cancellation with a bundled snapshot', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-cancel-'));\n const controller = new AbortController();\n controller.abort();\n try {\n await assert.rejects(loadOpenClawCatalog({\n provider: 'cohere',\n cacheDir,\n signal: controller.signal,\n fetchImpl: async () => { throw new Error('aborted'); },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery merges the daily OpenClaw catalog behind the live NVIDIA feed', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-merge-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n };\n try {\n const result = await nvidia.discover({\n apiKey: 'nvidia-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [{\n model: 'live/model',\n 'model-name': 'Live Model',\n context: 128000,\n 'max-output': 8000,\n }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['live/model', 'static/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery does not replace caller cancellation with its static catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-cancel-'));\n const controller = new AbortController();\n try {\n await assert.rejects(nvidia.discover({\n cacheDir,\n signal: controller.signal,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n controller.abort();\n throw new Error('aborted');\n },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('local Ollama auto-detection reuses tags while unknown remote endpoints are not probed', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: null,\n providerResolution: 'unknown',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return [model];\n });\n assert.equal(first.cacheStatus, 'refreshed');\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache upgrades legacy models with unknown rich capability metadata', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-legacy-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const legacy = normalizeSuppliedModels(['provider/model'])[0];\n delete legacy.outputModalities;\n delete legacy.reasoningLevels;\n delete legacy.metadataSources.outputModalities;\n delete legacy.metadataSources.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 1,\n provider: options.provider,\n endpointDigest: identity.endpointDigest,\n authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000,\n models: [legacy],\n }));\n const fresh = await withProviderCache(options, async () => { throw new Error('must not refresh'); });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(fresh.models[0].outputModalities, null);\n assert.equal(fresh.models[0].reasoningLevels, null);\n assert.equal(fresh.models[0].metadataSources.outputModalities, null);\n assert.equal(fresh.models[0].metadataSources.reasoningLevels, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache writes schema version 2 after upgrading version 1', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 1, now: () => 2000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const legacy = normalizeSuppliedModels(['provider/legacy'])[0];\n delete legacy.outputModalities;\n delete legacy.reasoningLevels;\n delete legacy.metadataSources.outputModalities;\n delete legacy.metadataSources.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 1, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [legacy],\n }));\n await withProviderCache(options, async () => normalizeSuppliedModels(['provider/current']));\n assert.equal(JSON.parse(fs.readFileSync(identity.file, 'utf8')).schemaVersion, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.cacheStatus, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.cacheStatus, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'meta/llama-test',\n name: 'Llama Test',\n input: ['text'],\n contextWindow: 65536,\n maxTokens: 4096,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, [\n OPENCLAW_CATALOGS.nvidia.url,\n 'https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json',\n ]);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, null);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: null,\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its bundled OpenClaw seed', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'openrouter/auto',\n 'moonshotai/kimi-k2.6',\n 'moonshotai/kimi-k2.5',\n ]);\n assert.equal(result.fallback.cacheStatus, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n { name: 'command-a-plus-05-2026', is_deprecated: false },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 128000);\n assert.equal(result.models[0].maxOutputTokens, 64000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches live accessible models from the daily OpenClaw catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-openclaw-enrich-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-synced',\n name: 'Command Synced',\n input: ['text', 'image'],\n contextWindow: 200000,\n maxTokens: 16000,\n reasoning: true,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.cohere.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-synced' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command Synced');\n assert.equal(result.models[0].contextWindow, 200000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: 1000000,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-chat',\n expectedContext: 1000000,\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS[entry.provider].url) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled catalog');\n }\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('static-backed discovery treats a malformed successful payload as refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n const result = await zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response('{\"unexpected\":true}');\n },\n });\n assert.ok(result.models.length > 0);\n assert.match(result.warnings.at(-1), /live catalog refresh failed/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] }));\n },\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery uses the native catalog and keeps only generateContent text models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['gemini-3.1-pro']);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('malformed xAI suppression refresh retains the bundled suppressions', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-malformed-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n if (url.includes('raw.githubusercontent.com')) {\n return new Response(JSON.stringify({ unexpected: true }));\n }\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.match(result.warnings[0], /bundled snapshot/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/openai-compatible-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/openai-compatible-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n});\n\ntest('xAI discovery removes OpenClaw-suppressed models without sending its API key to GitHub', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === 'https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/xai/openclaw.plugin.json') {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify({\n modelCatalog: {\n discovery: { xai: 'refreshable' },\n suppressions: [{ provider: 'xai', model: 'grok-multi-agent' }],\n },\n }));\n }\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) => model.id.endsWith(':cloud')));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery does not wait for a stalled cloud catalog refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-nonblocking-'));\n let releaseCloud;\n const cloudBlocked = new Promise((resolve) => { releaseCloud = resolve; });\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n if (String(url).includes('raw.githubusercontent.com')) {\n await cloudBlocked;\n throw new Error('offline');\n }\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n releaseCloud();\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public discovery returns supplied models without probing an unresolved provider', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['custom/b', 'custom/a'],\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, null);\n assert.equal(result.providerResolution, 'unknown');\n assert.equal(result.source, 'supplied');\n assert.equal(result.cacheStatus, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models.map((model) => model.id), ['custom/b', 'custom/a']);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'nvidia/featured',\n name: 'Featured',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.deepEqual(refreshed.models.map((model) => model.id), [\n 'nvidia/featured',\n 'private/model',\n ]);\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (String(url).startsWith('https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/')) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled metadata');\n }\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/openclaw-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "c1a1909be1e2a43c7f5eea7617facd626b87ad33": {"t": 1785758841.5490947, "n": 56691, "h": "1cff3773f8a26ff8", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst {\n CATALOG_TTL_MS,\n OPENCLAW_CATALOGS,\n loadOpenClawCatalog,\n parseOpenClawCatalog,\n} = require('../src/model-discovery/openclaw-catalog');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('OpenClaw catalog sync includes the extended static providers and preserves Ollama Cloud', () => {\n assert.deepEqual(Object.keys(OPENCLAW_CATALOGS).sort(), [\n 'cohere', 'deepseek', 'moonshot', 'nvidia', 'ollama-cloud', 'zai',\n ]);\n assert.equal(CATALOG_TTL_MS, 24 * 60 * 60 * 1000);\n for (const entry of Object.values(OPENCLAW_CATALOGS)) {\n const url = new URL(entry.url);\n assert.equal(url.protocol, 'https:');\n assert.equal(url.hostname, 'raw.githubusercontent.com');\n assert.match(url.pathname, /^\\/openclaw\\/openclaw\\/main\\/extensions\\//u);\n assert.match(url.pathname, /\\/openclaw\\.plugin\\.json$/u);\n }\n assert.equal(OPENCLAW_CATALOGS.ollama, undefined);\n});\n\ntest('extended OpenClaw static catalogs use bundled first-run fallbacks', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'extended-openclaw-bundled-'));\n try {\n for (const provider of ['zai', 'moonshot', 'deepseek']) {\n const result = await loadOpenClawCatalog({\n provider,\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.cacheStatus, 'bundled');\n assert.ok(result.models.length > 0, `${provider} must bundle model rows`);\n }\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama Cloud catalog parsing requires the distinct cloud provider base URL', () => {\n const payload = {\n modelCatalog: {\n providers: {\n 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [{\n id: 'cloud-test:cloud',\n name: 'Cloud Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8192,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('ollama-cloud', payload);\n assert.deepEqual(models.map((model) => model.id), ['cloud-test:cloud']);\n assert.equal(models[0].toolCalling, true);\n payload.modelCatalog.providers['ollama-cloud'].baseUrl = 'http://localhost:11434';\n assert.throws(() => parseOpenClawCatalog('ollama-cloud', payload), /base URL/i);\n});\n\ntest('OpenClaw catalog parsing validates provider identity and drops deprecated models', () => {\n const payload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [\n {\n id: 'vendor/current',\n name: 'Current',\n input: ['text', 'image'],\n contextWindow: 131072,\n maxTokens: 8192,\n reasoning: true,\n compat: { supportsTools: true },\n },\n {\n id: 'vendor/old',\n name: 'Old',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4096,\n status: 'deprecated',\n },\n ],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('nvidia', payload);\n assert.deepEqual(models.map((model) => model.id), ['vendor/current']);\n assert.deepEqual(models[0].inputModalities, ['text', 'image']);\n assert.equal(models[0].reasoning, true);\n assert.equal(models[0].toolCalling, true);\n assert.equal(models[0].source, 'openclaw-static');\n\n payload.modelCatalog.providers.nvidia.baseUrl = 'https://attacker.example/v1';\n assert.throws(() => parseOpenClawCatalog('nvidia', payload), /base URL/i);\n assert.throws(() => parseOpenClawCatalog('ollama', payload), /unsupported OpenClaw catalog/i);\n});\n\ntest('OpenClaw catalog uses supported provider efforts instead of assuming every Codex level', () => {\n const payload = {\n modelCatalog: {\n providers: {\n zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-capable',\n name: 'GLM Capable',\n input: ['text', 'image'],\n output: ['text'],\n reasoning: true,\n contextWindow: 128000,\n maxTokens: 8192,\n thinkingLevelMap: { low: null, high: 'max', max: 'max' },\n compat: { supportsReasoningEffort: true, supportedReasoningEfforts: ['max'] },\n }],\n },\n },\n },\n };\n const [model] = parseOpenClawCatalog('zai', payload);\n assert.deepEqual(model.inputModalities, ['text', 'image']);\n assert.deepEqual(model.outputModalities, ['text']);\n assert.deepEqual(model.reasoningLevels, ['max']);\n assert.equal(model.metadataSources.outputModalities, 'provider-seed');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-seed');\n});\n\ntest('OpenClaw catalog leaves exact reasoning levels unknown when only configurability is known', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{ id: 'glm-unknown-levels', reasoning: true, compat: { supportsReasoningEffort: true } }],\n } } },\n };\n assert.equal(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, null);\n});\n\ntest('OpenClaw catalog normalizes thinking map values when explicit efforts are absent', () => {\n const payload = {\n modelCatalog: { providers: { zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-mapped-levels', reasoning: true,\n thinkingLevelMap: { low: null, high: 'max', xhigh: 'max' },\n }],\n } } },\n };\n assert.deepEqual(parseOpenClawCatalog('zai', payload)[0].reasoningLevels, ['max']);\n});\n\ntest('OpenClaw catalog sync refreshes at most daily and retains the last successful file', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-sync-'));\n let calls = 0;\n const payload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-test',\n name: 'Command Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8000,\n }],\n },\n },\n },\n };\n try {\n const options = {\n provider: 'cohere',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, request) => {\n calls += 1;\n assert.equal(url, OPENCLAW_CATALOGS.cohere.url);\n assert.equal(request.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n },\n };\n const refreshed = await loadOpenClawCatalog(options);\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.deepEqual(refreshed.models.map((model) => model.id), ['command-test']);\n\n const fresh = await loadOpenClawCatalog({\n ...options,\n now: () => 1000 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh catalog must not fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 1);\n\n const stale = await loadOpenClawCatalog({\n ...options,\n now: () => 1001 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('offline');\n },\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['command-test']);\n assert.match(stale.warnings[0], /last successful/i);\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync uses its bundled snapshot on first-run network failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-bundled-'));\n try {\n const result = await loadOpenClawCatalog({\n provider: 'nvidia',\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.cacheStatus, 'bundled');\n assert.ok(result.models.length > 0);\n assert.match(result.warnings[0], /bundled OpenClaw catalog/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync does not replace caller cancellation with a bundled snapshot', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-cancel-'));\n const controller = new AbortController();\n controller.abort();\n try {\n await assert.rejects(loadOpenClawCatalog({\n provider: 'cohere',\n cacheDir,\n signal: controller.signal,\n fetchImpl: async () => { throw new Error('aborted'); },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery merges the daily OpenClaw catalog behind the live NVIDIA feed', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-merge-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n };\n try {\n const result = await nvidia.discover({\n apiKey: 'nvidia-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [{\n model: 'live/model',\n 'model-name': 'Live Model',\n context: 128000,\n 'max-output': 8000,\n }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['live/model', 'static/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery does not replace caller cancellation with its static catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-cancel-'));\n const controller = new AbortController();\n try {\n await assert.rejects(nvidia.discover({\n cacheDir,\n signal: controller.signal,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n controller.abort();\n throw new Error('aborted');\n },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('local Ollama auto-detection reuses tags while unknown remote endpoints are not probed', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: null,\n providerResolution: 'unknown',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return [model];\n });\n assert.equal(first.cacheStatus, 'refreshed');\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache upgrades legacy models with unknown rich capability metadata', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-legacy-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const legacy = normalizeSuppliedModels(['provider/model'])[0];\n delete legacy.outputModalities;\n delete legacy.reasoningLevels;\n delete legacy.metadataSources.outputModalities;\n delete legacy.metadataSources.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 1,\n provider: options.provider,\n endpointDigest: identity.endpointDigest,\n authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000,\n models: [legacy],\n }));\n const fresh = await withProviderCache(options, async () => { throw new Error('must not refresh'); });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(fresh.models[0].outputModalities, null);\n assert.equal(fresh.models[0].reasoningLevels, null);\n assert.equal(fresh.models[0].metadataSources.outputModalities, null);\n assert.equal(fresh.models[0].metadataSources.reasoningLevels, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache writes schema version 2 after upgrading version 1', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 1, now: () => 2000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const legacy = normalizeSuppliedModels(['provider/legacy'])[0];\n delete legacy.outputModalities;\n delete legacy.reasoningLevels;\n delete legacy.metadataSources.outputModalities;\n delete legacy.metadataSources.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 1, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [legacy],\n }));\n await withProviderCache(options, async () => normalizeSuppliedModels(['provider/current']));\n assert.equal(JSON.parse(fs.readFileSync(identity.file, 'utf8')).schemaVersion, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache rejects schema version 2 models missing rich capability fields', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-invalid-v2-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const malformed = normalizeSuppliedModels(['provider/model'])[0];\n delete malformed.outputModalities;\n delete malformed.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 2, provider: options.provider,\n endpointDigest: identity.endpointDigest, authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000, models: [malformed],\n }));\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['provider/refreshed']));\n assert.equal(result.cacheStatus, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.cacheStatus, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'meta/llama-test',\n name: 'Llama Test',\n input: ['text'],\n contextWindow: 65536,\n maxTokens: 4096,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, [\n OPENCLAW_CATALOGS.nvidia.url,\n 'https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json',\n ]);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, null);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: null,\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its bundled OpenClaw seed', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'openrouter/auto',\n 'moonshotai/kimi-k2.6',\n 'moonshotai/kimi-k2.5',\n ]);\n assert.equal(result.fallback.cacheStatus, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n { name: 'command-a-plus-05-2026', is_deprecated: false },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 128000);\n assert.equal(result.models[0].maxOutputTokens, 64000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches live accessible models from the daily OpenClaw catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-openclaw-enrich-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-synced',\n name: 'Command Synced',\n input: ['text', 'image'],\n contextWindow: 200000,\n maxTokens: 16000,\n reasoning: true,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.cohere.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-synced' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command Synced');\n assert.equal(result.models[0].contextWindow, 200000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: 1000000,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-chat',\n expectedContext: 1000000,\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS[entry.provider].url) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled catalog');\n }\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('static-backed discovery treats a malformed successful payload as refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n const result = await zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response('{\"unexpected\":true}');\n },\n });\n assert.ok(result.models.length > 0);\n assert.match(result.warnings.at(-1), /live catalog refresh failed/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] }));\n },\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery uses the native catalog and keeps only generateContent text models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['gemini-3.1-pro']);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-catalog');\n});\n\ntest('malformed xAI suppression refresh retains the bundled suppressions', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-malformed-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n if (url.includes('raw.githubusercontent.com')) {\n return new Response(JSON.stringify({ unexpected: true }));\n }\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.match(result.warnings[0], /bundled snapshot/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/openai-compatible-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/openai-compatible-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n});\n\ntest('xAI discovery removes OpenClaw-suppressed models without sending its API key to GitHub', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === 'https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/xai/openclaw.plugin.json') {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify({\n modelCatalog: {\n discovery: { xai: 'refreshable' },\n suppressions: [{ provider: 'xai', model: 'grok-multi-agent' }],\n },\n }));\n }\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.outputModalities, 'provider-inspection');\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) => model.id.endsWith(':cloud')));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery does not wait for a stalled cloud catalog refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-nonblocking-'));\n let releaseCloud;\n const cloudBlocked = new Promise((resolve) => { releaseCloud = resolve; });\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n if (String(url).includes('raw.githubusercontent.com')) {\n await cloudBlocked;\n throw new Error('offline');\n }\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n releaseCloud();\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public discovery returns supplied models without probing an unresolved provider', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['custom/b', 'custom/a'],\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, null);\n assert.equal(result.providerResolution, 'unknown');\n assert.equal(result.source, 'supplied');\n assert.equal(result.cacheStatus, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models.map((model) => model.id), ['custom/b', 'custom/a']);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'nvidia/featured',\n name: 'Featured',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.deepEqual(refreshed.models.map((model) => model.id), [\n 'nvidia/featured',\n 'private/model',\n ]);\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (String(url).startsWith('https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/')) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled metadata');\n }\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only approved catalog consumers import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/openclaw-catalog/u);\n continue;\n }\n if (name === 'codex-config.js') {\n assert.match(source, /require\\(['\"]\\.\\/model-discovery['\"]\\)/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "c36cff1c6085b067a2ba070510b8644c9c081978": {"t": 1785758844.734348, "n": 53071, "h": "f47c37eb2e386f0c", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst {\n CATALOG_TTL_MS,\n OPENCLAW_CATALOGS,\n loadOpenClawCatalog,\n parseOpenClawCatalog,\n} = require('../src/model-discovery/openclaw-catalog');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('OpenClaw catalog sync includes the extended static providers and preserves Ollama Cloud', () => {\n assert.deepEqual(Object.keys(OPENCLAW_CATALOGS).sort(), [\n 'cohere', 'deepseek', 'moonshot', 'nvidia', 'ollama-cloud', 'zai',\n ]);\n assert.equal(CATALOG_TTL_MS, 24 * 60 * 60 * 1000);\n for (const entry of Object.values(OPENCLAW_CATALOGS)) {\n const url = new URL(entry.url);\n assert.equal(url.protocol, 'https:');\n assert.equal(url.hostname, 'raw.githubusercontent.com');\n assert.match(url.pathname, /^\\/openclaw\\/openclaw\\/main\\/extensions\\//u);\n assert.match(url.pathname, /\\/openclaw\\.plugin\\.json$/u);\n }\n assert.equal(OPENCLAW_CATALOGS.ollama, undefined);\n});\n\ntest('extended OpenClaw static catalogs use bundled first-run fallbacks', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'extended-openclaw-bundled-'));\n try {\n for (const provider of ['zai', 'moonshot', 'deepseek']) {\n const result = await loadOpenClawCatalog({\n provider,\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.cacheStatus, 'bundled');\n assert.ok(result.models.length > 0, `${provider} must bundle model rows`);\n }\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama Cloud catalog parsing requires the distinct cloud provider base URL', () => {\n const payload = {\n modelCatalog: {\n providers: {\n 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [{\n id: 'cloud-test:cloud',\n name: 'Cloud Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8192,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('ollama-cloud', payload);\n assert.deepEqual(models.map((model) => model.id), ['cloud-test:cloud']);\n assert.equal(models[0].toolCalling, true);\n payload.modelCatalog.providers['ollama-cloud'].baseUrl = 'http://localhost:11434';\n assert.throws(() => parseOpenClawCatalog('ollama-cloud', payload), /base URL/i);\n});\n\ntest('OpenClaw catalog parsing validates provider identity and drops deprecated models', () => {\n const payload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [\n {\n id: 'vendor/current',\n name: 'Current',\n input: ['text', 'image'],\n contextWindow: 131072,\n maxTokens: 8192,\n reasoning: true,\n compat: { supportsTools: true },\n },\n {\n id: 'vendor/old',\n name: 'Old',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4096,\n status: 'deprecated',\n },\n ],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('nvidia', payload);\n assert.deepEqual(models.map((model) => model.id), ['vendor/current']);\n assert.deepEqual(models[0].inputModalities, ['text', 'image']);\n assert.equal(models[0].reasoning, true);\n assert.equal(models[0].toolCalling, true);\n assert.equal(models[0].source, 'openclaw-static');\n\n payload.modelCatalog.providers.nvidia.baseUrl = 'https://attacker.example/v1';\n assert.throws(() => parseOpenClawCatalog('nvidia', payload), /base URL/i);\n assert.throws(() => parseOpenClawCatalog('ollama', payload), /unsupported OpenClaw catalog/i);\n});\n\ntest('OpenClaw catalog retains output capabilities and normalized reasoning levels', () => {\n const payload = {\n modelCatalog: {\n providers: {\n zai: {\n baseUrl: 'https://api.z.ai/api/paas/v4',\n models: [{\n id: 'glm-capable',\n name: 'GLM Capable',\n input: ['text', 'image'],\n output: ['text'],\n reasoning: true,\n contextWindow: 128000,\n maxTokens: 8192,\n compat: { supportsReasoningEffort: true },\n }],\n },\n },\n },\n };\n const [model] = parseOpenClawCatalog('zai', payload);\n assert.deepEqual(model.inputModalities, ['text', 'image']);\n assert.deepEqual(model.outputModalities, ['text']);\n assert.deepEqual(model.reasoningLevels, ['low', 'medium', 'high', 'xhigh', 'max']);\n assert.equal(model.metadataSources.outputModalities, 'provider-seed');\n assert.equal(model.metadataSources.reasoningLevels, 'provider-seed');\n});\n\ntest('OpenClaw catalog sync refreshes at most daily and retains the last successful file', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-sync-'));\n let calls = 0;\n const payload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-test',\n name: 'Command Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8000,\n }],\n },\n },\n },\n };\n try {\n const options = {\n provider: 'cohere',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, request) => {\n calls += 1;\n assert.equal(url, OPENCLAW_CATALOGS.cohere.url);\n assert.equal(request.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n },\n };\n const refreshed = await loadOpenClawCatalog(options);\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.deepEqual(refreshed.models.map((model) => model.id), ['command-test']);\n\n const fresh = await loadOpenClawCatalog({\n ...options,\n now: () => 1000 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh catalog must not fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 1);\n\n const stale = await loadOpenClawCatalog({\n ...options,\n now: () => 1001 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('offline');\n },\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['command-test']);\n assert.match(stale.warnings[0], /last successful/i);\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync uses its bundled snapshot on first-run network failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-bundled-'));\n try {\n const result = await loadOpenClawCatalog({\n provider: 'nvidia',\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.cacheStatus, 'bundled');\n assert.ok(result.models.length > 0);\n assert.match(result.warnings[0], /bundled OpenClaw catalog/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync does not replace caller cancellation with a bundled snapshot', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-cancel-'));\n const controller = new AbortController();\n controller.abort();\n try {\n await assert.rejects(loadOpenClawCatalog({\n provider: 'cohere',\n cacheDir,\n signal: controller.signal,\n fetchImpl: async () => { throw new Error('aborted'); },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery merges the daily OpenClaw catalog behind the live NVIDIA feed', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-merge-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n };\n try {\n const result = await nvidia.discover({\n apiKey: 'nvidia-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [{\n model: 'live/model',\n 'model-name': 'Live Model',\n context: 128000,\n 'max-output': 8000,\n }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['live/model', 'static/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery does not replace caller cancellation with its static catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-cancel-'));\n const controller = new AbortController();\n try {\n await assert.rejects(nvidia.discover({\n cacheDir,\n signal: controller.signal,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n controller.abort();\n throw new Error('aborted');\n },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n outputModalities: null,\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('local Ollama auto-detection reuses tags while unknown remote endpoints are not probed', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: null,\n providerResolution: 'unknown',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return [model];\n });\n assert.equal(first.cacheStatus, 'refreshed');\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache round-trips output capabilities and reasoning levels', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-rich-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.outputModalities = ['text'];\n model.reasoning = true;\n model.reasoningLevels = ['low', 'high', 'max'];\n model.metadataSources.outputModalities = 'provider-catalog';\n model.metadataSources.reasoning = 'provider-catalog';\n model.metadataSources.reasoningLevels = 'provider-catalog';\n try {\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1000,\n };\n await withProviderCache(options, async () => [model]);\n const fresh = await withProviderCache({ ...options, now: () => 1500 }, async () => {\n throw new Error('must not refresh');\n });\n assert.deepEqual(fresh.models[0].outputModalities, ['text']);\n assert.deepEqual(fresh.models[0].reasoningLevels, ['low', 'high', 'max']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache upgrades legacy models with unknown rich capability metadata', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-legacy-cache-'));\n const options = {\n provider: 'zai', endpoint: 'https://catalog.example/models', apiKey: 'secret',\n cacheDir, ttlMs: 60000, now: () => 1500,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n const legacy = normalizeSuppliedModels(['provider/model'])[0];\n delete legacy.outputModalities;\n delete legacy.reasoningLevels;\n delete legacy.metadataSources.outputModalities;\n delete legacy.metadataSources.reasoningLevels;\n fs.writeFileSync(identity.file, JSON.stringify({\n schemaVersion: 1,\n provider: options.provider,\n endpointDigest: identity.endpointDigest,\n authScopeDigest: identity.authScopeDigest,\n fetchedAt: 1000,\n models: [legacy],\n }));\n const fresh = await withProviderCache(options, async () => { throw new Error('must not refresh'); });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(fresh.models[0].outputModalities, null);\n assert.equal(fresh.models[0].reasoningLevels, null);\n assert.equal(fresh.models[0].metadataSources.outputModalities, null);\n assert.equal(fresh.models[0].metadataSources.reasoningLevels, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.cacheStatus, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'meta/llama-test',\n name: 'Llama Test',\n input: ['text'],\n contextWindow: 65536,\n maxTokens: 4096,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, [\n OPENCLAW_CATALOGS.nvidia.url,\n 'https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json',\n ]);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n outputModalities: ['text'],\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: null,\n reasoningLevels: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.deepEqual(rich.outputModalities, ['text']);\n assert.deepEqual(rich.reasoningLevels, null);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n outputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n reasoningLevels: null,\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its bundled OpenClaw seed', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'openrouter/auto',\n 'moonshotai/kimi-k2.6',\n 'moonshotai/kimi-k2.5',\n ]);\n assert.equal(result.fallback.cacheStatus, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n { name: 'command-a-plus-05-2026', is_deprecated: false },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 128000);\n assert.equal(result.models[0].maxOutputTokens, 64000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches live accessible models from the daily OpenClaw catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-openclaw-enrich-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-synced',\n name: 'Command Synced',\n input: ['text', 'image'],\n contextWindow: 200000,\n maxTokens: 16000,\n reasoning: true,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.cohere.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-synced' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command Synced');\n assert.equal(result.models[0].contextWindow, 200000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: 1000000,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-chat',\n expectedContext: 1000000,\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS[entry.provider].url) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled catalog');\n }\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('static-backed discovery treats a malformed successful payload as refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n const result = await zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response('{\"unexpected\":true}');\n },\n });\n assert.ok(result.models.length > 0);\n assert.match(result.warnings.at(-1), /live catalog refresh failed/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] }));\n },\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery uses the native catalog and keeps only generateContent text models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['gemini-3.1-pro']);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n});\n\ntest('malformed xAI suppression refresh retains the bundled suppressions', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-malformed-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n if (url.includes('raw.githubusercontent.com')) {\n return new Response(JSON.stringify({ unexpected: true }));\n }\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.match(result.warnings[0], /bundled snapshot/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/openai-compatible-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n assert.deepEqual(audio.outputModalities, ['text']);\n});\n\ntest('OpenAI-compatible live rows normalize explicit reasoning levels', () => {\n const model = require('../src/model-discovery/providers/openai-compatible-catalog').parseLiveRow({\n id: 'reasoning-model',\n output_modalities: ['text'],\n reasoning: true,\n reasoning_levels: ['HIGH', 'low', 'high', 'unsupported'],\n }, 'test-catalog');\n assert.deepEqual(model.reasoningLevels, ['low', 'high']);\n assert.equal(model.metadataSources.reasoningLevels, 'provider-catalog');\n});\n\ntest('xAI discovery removes OpenClaw-suppressed models without sending its API key to GitHub', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === 'https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/xai/openclaw.plugin.json') {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify({\n modelCatalog: {\n discovery: { xai: 'refreshable' },\n suppressions: [{ provider: 'xai', model: 'grok-multi-agent' }],\n },\n }));\n }\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) => model.id.endsWith(':cloud')));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery does not wait for a stalled cloud catalog refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-nonblocking-'));\n let releaseCloud;\n const cloudBlocked = new Promise((resolve) => { releaseCloud = resolve; });\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n if (String(url).includes('raw.githubusercontent.com')) {\n await cloudBlocked;\n throw new Error('offline');\n }\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n releaseCloud();\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public discovery returns supplied models without probing an unresolved provider', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['custom/b', 'custom/a'],\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, null);\n assert.equal(result.providerResolution, 'unknown');\n assert.equal(result.source, 'supplied');\n assert.equal(result.cacheStatus, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models.map((model) => model.id), ['custom/b', 'custom/a']);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'nvidia/featured',\n name: 'Featured',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.deepEqual(refreshed.models.map((model) => model.id), [\n 'nvidia/featured',\n 'private/model',\n ]);\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (String(url).startsWith('https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/')) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled metadata');\n }\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only the approved Ollama cloud pull bridge imports standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/openclaw-catalog/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "287f84d09093da3ddcbe74bc968f12f29e7b4322": {"t": 1785758846.4047644, "n": 48554, "h": "c6530397b3edbb61", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst {\n CATALOG_TTL_MS,\n OPENCLAW_CATALOGS,\n loadOpenClawCatalog,\n parseOpenClawCatalog,\n} = require('../src/model-discovery/openclaw-catalog');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('OpenClaw catalog sync includes the extended static providers and preserves Ollama Cloud', () => {\n assert.deepEqual(Object.keys(OPENCLAW_CATALOGS).sort(), [\n 'cohere', 'deepseek', 'moonshot', 'nvidia', 'ollama-cloud', 'zai',\n ]);\n assert.equal(CATALOG_TTL_MS, 24 * 60 * 60 * 1000);\n for (const entry of Object.values(OPENCLAW_CATALOGS)) {\n const url = new URL(entry.url);\n assert.equal(url.protocol, 'https:');\n assert.equal(url.hostname, 'raw.githubusercontent.com');\n assert.match(url.pathname, /^\\/openclaw\\/openclaw\\/main\\/extensions\\//u);\n assert.match(url.pathname, /\\/openclaw\\.plugin\\.json$/u);\n }\n assert.equal(OPENCLAW_CATALOGS.ollama, undefined);\n});\n\ntest('extended OpenClaw static catalogs use bundled first-run fallbacks', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'extended-openclaw-bundled-'));\n try {\n for (const provider of ['zai', 'moonshot', 'deepseek']) {\n const result = await loadOpenClawCatalog({\n provider,\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.cacheStatus, 'bundled');\n assert.ok(result.models.length > 0, `${provider} must bundle model rows`);\n }\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama Cloud catalog parsing requires the distinct cloud provider base URL', () => {\n const payload = {\n modelCatalog: {\n providers: {\n 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [{\n id: 'cloud-test:cloud',\n name: 'Cloud Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8192,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('ollama-cloud', payload);\n assert.deepEqual(models.map((model) => model.id), ['cloud-test:cloud']);\n assert.equal(models[0].toolCalling, true);\n payload.modelCatalog.providers['ollama-cloud'].baseUrl = 'http://localhost:11434';\n assert.throws(() => parseOpenClawCatalog('ollama-cloud', payload), /base URL/i);\n});\n\ntest('OpenClaw catalog parsing validates provider identity and drops deprecated models', () => {\n const payload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [\n {\n id: 'vendor/current',\n name: 'Current',\n input: ['text', 'image'],\n contextWindow: 131072,\n maxTokens: 8192,\n reasoning: true,\n compat: { supportsTools: true },\n },\n {\n id: 'vendor/old',\n name: 'Old',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4096,\n status: 'deprecated',\n },\n ],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('nvidia', payload);\n assert.deepEqual(models.map((model) => model.id), ['vendor/current']);\n assert.deepEqual(models[0].inputModalities, ['text', 'image']);\n assert.equal(models[0].reasoning, true);\n assert.equal(models[0].toolCalling, true);\n assert.equal(models[0].source, 'openclaw-static');\n\n payload.modelCatalog.providers.nvidia.baseUrl = 'https://attacker.example/v1';\n assert.throws(() => parseOpenClawCatalog('nvidia', payload), /base URL/i);\n assert.throws(() => parseOpenClawCatalog('ollama', payload), /unsupported OpenClaw catalog/i);\n});\n\ntest('OpenClaw catalog sync refreshes at most daily and retains the last successful file', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-sync-'));\n let calls = 0;\n const payload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-test',\n name: 'Command Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8000,\n }],\n },\n },\n },\n };\n try {\n const options = {\n provider: 'cohere',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, request) => {\n calls += 1;\n assert.equal(url, OPENCLAW_CATALOGS.cohere.url);\n assert.equal(request.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n },\n };\n const refreshed = await loadOpenClawCatalog(options);\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.deepEqual(refreshed.models.map((model) => model.id), ['command-test']);\n\n const fresh = await loadOpenClawCatalog({\n ...options,\n now: () => 1000 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh catalog must not fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 1);\n\n const stale = await loadOpenClawCatalog({\n ...options,\n now: () => 1001 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('offline');\n },\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['command-test']);\n assert.match(stale.warnings[0], /last successful/i);\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync uses its bundled snapshot on first-run network failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-bundled-'));\n try {\n const result = await loadOpenClawCatalog({\n provider: 'nvidia',\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.cacheStatus, 'bundled');\n assert.ok(result.models.length > 0);\n assert.match(result.warnings[0], /bundled OpenClaw catalog/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync does not replace caller cancellation with a bundled snapshot', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-cancel-'));\n const controller = new AbortController();\n controller.abort();\n try {\n await assert.rejects(loadOpenClawCatalog({\n provider: 'cohere',\n cacheDir,\n signal: controller.signal,\n fetchImpl: async () => { throw new Error('aborted'); },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery merges the daily OpenClaw catalog behind the live NVIDIA feed', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-merge-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n };\n try {\n const result = await nvidia.discover({\n apiKey: 'nvidia-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [{\n model: 'live/model',\n 'model-name': 'Live Model',\n context: 128000,\n 'max-output': 8000,\n }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['live/model', 'static/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery does not replace caller cancellation with its static catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-cancel-'));\n const controller = new AbortController();\n try {\n await assert.rejects(nvidia.discover({\n cacheDir,\n signal: controller.signal,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n controller.abort();\n throw new Error('aborted');\n },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n reasoning: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n reasoning: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('local Ollama auto-detection reuses tags while unknown remote endpoints are not probed', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: null,\n providerResolution: 'unknown',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return [model];\n });\n assert.equal(first.cacheStatus, 'refreshed');\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache propagates caller cancellation instead of returning stale data', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-cancel-'));\n const controller = new AbortController();\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n try {\n await withProviderCache({ ...common, now: () => 1000 }, async () => normalizeSuppliedModels(['provider/model']));\n controller.abort();\n await assert.rejects(\n withProviderCache({ ...common, now: () => 3000, signal: controller.signal }, async () => {\n const error = new Error('cancelled');\n error.code = 'CANCELLED';\n throw error;\n }),\n (error) => error.code === 'CANCELLED',\n );\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.cacheStatus, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'meta/llama-test',\n name: 'Llama Test',\n input: ['text'],\n contextWindow: 65536,\n maxTokens: 4096,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, [\n OPENCLAW_CATALOGS.nvidia.url,\n 'https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json',\n ]);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n reasoning: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n reasoning: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('OpenRouter first-run failure exposes its bundled OpenClaw seed', async () => {\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.deepEqual(result.models.map((model) => model.id), [\n 'openrouter/auto',\n 'moonshotai/kimi-k2.6',\n 'moonshotai/kimi-k2.5',\n ]);\n assert.equal(result.fallback.cacheStatus, 'bundled');\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n { name: 'command-a-plus-05-2026', is_deprecated: false },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 128000);\n assert.equal(result.models[0].maxOutputTokens, 64000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches live accessible models from the daily OpenClaw catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-openclaw-enrich-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-synced',\n name: 'Command Synced',\n input: ['text', 'image'],\n contextWindow: 200000,\n maxTokens: 16000,\n reasoning: true,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.cohere.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-synced' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command Synced');\n assert.equal(result.models[0].contextWindow, 200000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: 1000000,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-chat',\n expectedContext: 1000000,\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS[entry.provider].url) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled catalog');\n }\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('static-backed discovery treats a malformed successful payload as refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n const result = await zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response('{\"unexpected\":true}');\n },\n });\n assert.ok(result.models.length > 0);\n assert.match(result.warnings.at(-1), /live catalog refresh failed/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('static fallback never replaces the last authenticated model cache', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-live-cache-precedence-'));\n const common = {\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n apiKey: 'zai-secret',\n cacheDir,\n };\n try {\n const first = await discoverModels({\n ...common,\n now: () => 1000,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response(JSON.stringify({ data: [{ id: 'account/private-model' }] }));\n },\n });\n assert.deepEqual(first.models.map((model) => model.id), ['account/private-model']);\n\n const stale = await discoverModels({\n ...common,\n now: () => 62000,\n fetchImpl: async () => { throw new Error('provider offline'); },\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['account/private-model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery uses the native catalog and keeps only generateContent text models', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000');\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'google-secret');\n return new Response(JSON.stringify({\n models: [\n {\n name: 'models/gemini-3.1-pro',\n displayName: 'Gemini 3.1 Pro',\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 1048576,\n outputTokenLimit: 65536,\n },\n {\n name: 'models/text-embedding-004',\n supportedGenerationMethods: ['embedContent'],\n inputTokenLimit: 2048,\n outputTokenLimit: 1,\n },\n {\n name: 'models/imagen-4.0-generate-001',\n supportedGenerationMethods: ['predict'],\n inputTokenLimit: 480,\n outputTokenLimit: 1,\n },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['gemini-3.1-pro']);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n});\n\ntest('malformed xAI suppression refresh retains the bundled suppressions', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-malformed-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url) => {\n if (url.includes('raw.githubusercontent.com')) {\n return new Response(JSON.stringify({ unexpected: true }));\n }\n return new Response(JSON.stringify({ data: [{ id: 'grok-4' }, { id: 'grok-4.20-multi-agent' }] }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n assert.match(result.warnings[0], /bundled snapshot/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenAI-compatible input metadata preserves known modalities instead of inventing text', () => {\n const audio = require('../src/model-discovery/providers/openai-compatible-catalog').parseLiveRow({\n id: 'audio-model',\n input_modalities: ['audio'],\n output_modalities: ['text'],\n }, 'test-catalog');\n assert.deepEqual(audio.inputModalities, ['audio']);\n});\n\ntest('xAI discovery removes OpenClaw-suppressed models without sending its API key to GitHub', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === 'https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/xai/openclaw.plugin.json') {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify({\n modelCatalog: {\n discovery: { xai: 'refreshable' },\n suppressions: [{ provider: 'xai', model: 'grok-multi-agent' }],\n },\n }));\n }\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.equal(result.models[0].id, 'local-model');\n assert.ok(result.models.slice(1).every((model) => model.id.endsWith(':cloud')));\n assert.ok(result.models.length > 1);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama local discovery does not wait for a stalled cloud catalog refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-nonblocking-'));\n let releaseCloud;\n const cloudBlocked = new Promise((resolve) => { releaseCloud = resolve; });\n try {\n const discovery = ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n fetchImpl: async (url) => {\n if (String(url).includes('raw.githubusercontent.com')) {\n await cloudBlocked;\n throw new Error('offline');\n }\n return new Response(JSON.stringify({ capabilities: ['completion'] }));\n },\n });\n const winner = await Promise.race([\n discovery.then(() => 'discovered'),\n new Promise((resolve) => setTimeout(() => resolve('blocked'), 50)),\n ]);\n assert.equal(winner, 'discovered');\n } finally {\n releaseCloud();\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public discovery returns supplied models without probing an unresolved provider', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['custom/b', 'custom/a'],\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, null);\n assert.equal(result.providerResolution, 'unknown');\n assert.equal(result.source, 'supplied');\n assert.equal(result.cacheStatus, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models.map((model) => model.id), ['custom/b', 'custom/a']);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'nvidia/featured',\n name: 'Featured',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.deepEqual(refreshed.models.map((model) => model.id), [\n 'nvidia/featured',\n 'private/model',\n ]);\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (String(url).startsWith('https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/')) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled metadata');\n }\n if (provider === 'google') {\n assert.equal(url, google.ENDPOINT);\n assert.equal(options.headers.Authorization, undefined);\n assert.equal(options.headers['x-goog-api-key'], 'provider-secret');\n return new Response(JSON.stringify({\n models: [{\n name: `models/${liveId}`,\n supportedGenerationMethods: ['generateContent'],\n inputTokenLimit: 100000,\n outputTokenLimit: 8192,\n }],\n }));\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only the approved Ollama cloud pull bridge imports standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/openclaw-catalog/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "a47cde9a2e969191b38a20c17f2e38e15d2f215c": {"t": 1785758849.8431647, "n": 43351, "h": "04d09f8a6474699f", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst {\n CATALOG_TTL_MS,\n OPENCLAW_CATALOGS,\n loadOpenClawCatalog,\n parseOpenClawCatalog,\n} = require('../src/model-discovery/openclaw-catalog');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst zai = require('../src/model-discovery/providers/zai');\nconst moonshot = require('../src/model-discovery/providers/moonshot');\nconst deepseek = require('../src/model-discovery/providers/deepseek');\nconst google = require('../src/model-discovery/providers/google');\nconst xai = require('../src/model-discovery/providers/xai');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('OpenClaw catalog sync includes the extended static providers and preserves Ollama Cloud', () => {\n assert.deepEqual(Object.keys(OPENCLAW_CATALOGS).sort(), [\n 'cohere', 'deepseek', 'moonshot', 'nvidia', 'ollama-cloud', 'zai',\n ]);\n assert.equal(CATALOG_TTL_MS, 24 * 60 * 60 * 1000);\n for (const entry of Object.values(OPENCLAW_CATALOGS)) {\n const url = new URL(entry.url);\n assert.equal(url.protocol, 'https:');\n assert.equal(url.hostname, 'raw.githubusercontent.com');\n assert.match(url.pathname, /^\\/openclaw\\/openclaw\\/main\\/extensions\\//u);\n assert.match(url.pathname, /\\/openclaw\\.plugin\\.json$/u);\n }\n assert.equal(OPENCLAW_CATALOGS.ollama, undefined);\n});\n\ntest('extended OpenClaw static catalogs use bundled first-run fallbacks', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'extended-openclaw-bundled-'));\n try {\n for (const provider of ['zai', 'moonshot', 'deepseek']) {\n const result = await loadOpenClawCatalog({\n provider,\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.cacheStatus, 'bundled');\n assert.ok(result.models.length > 0, `${provider} must bundle model rows`);\n }\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama Cloud catalog parsing requires the distinct cloud provider base URL', () => {\n const payload = {\n modelCatalog: {\n providers: {\n 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [{\n id: 'cloud-test:cloud',\n name: 'Cloud Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8192,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('ollama-cloud', payload);\n assert.deepEqual(models.map((model) => model.id), ['cloud-test:cloud']);\n assert.equal(models[0].toolCalling, true);\n payload.modelCatalog.providers['ollama-cloud'].baseUrl = 'http://localhost:11434';\n assert.throws(() => parseOpenClawCatalog('ollama-cloud', payload), /base URL/i);\n});\n\ntest('OpenClaw catalog parsing validates provider identity and drops deprecated models', () => {\n const payload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [\n {\n id: 'vendor/current',\n name: 'Current',\n input: ['text', 'image'],\n contextWindow: 131072,\n maxTokens: 8192,\n reasoning: true,\n compat: { supportsTools: true },\n },\n {\n id: 'vendor/old',\n name: 'Old',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4096,\n status: 'deprecated',\n },\n ],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('nvidia', payload);\n assert.deepEqual(models.map((model) => model.id), ['vendor/current']);\n assert.deepEqual(models[0].inputModalities, ['text', 'image']);\n assert.equal(models[0].reasoning, true);\n assert.equal(models[0].toolCalling, true);\n assert.equal(models[0].source, 'openclaw-static');\n\n payload.modelCatalog.providers.nvidia.baseUrl = 'https://attacker.example/v1';\n assert.throws(() => parseOpenClawCatalog('nvidia', payload), /base URL/i);\n assert.throws(() => parseOpenClawCatalog('ollama', payload), /unsupported OpenClaw catalog/i);\n});\n\ntest('OpenClaw catalog sync refreshes at most daily and retains the last successful file', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-sync-'));\n let calls = 0;\n const payload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-test',\n name: 'Command Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8000,\n }],\n },\n },\n },\n };\n try {\n const options = {\n provider: 'cohere',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, request) => {\n calls += 1;\n assert.equal(url, OPENCLAW_CATALOGS.cohere.url);\n assert.equal(request.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n },\n };\n const refreshed = await loadOpenClawCatalog(options);\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.deepEqual(refreshed.models.map((model) => model.id), ['command-test']);\n\n const fresh = await loadOpenClawCatalog({\n ...options,\n now: () => 1000 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh catalog must not fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 1);\n\n const stale = await loadOpenClawCatalog({\n ...options,\n now: () => 1001 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('offline');\n },\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['command-test']);\n assert.match(stale.warnings[0], /last successful/i);\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync uses its bundled snapshot on first-run network failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-bundled-'));\n try {\n const result = await loadOpenClawCatalog({\n provider: 'nvidia',\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.cacheStatus, 'bundled');\n assert.ok(result.models.length > 0);\n assert.match(result.warnings[0], /bundled OpenClaw catalog/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync does not replace caller cancellation with a bundled snapshot', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-cancel-'));\n const controller = new AbortController();\n controller.abort();\n try {\n await assert.rejects(loadOpenClawCatalog({\n provider: 'cohere',\n cacheDir,\n signal: controller.signal,\n fetchImpl: async () => { throw new Error('aborted'); },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery merges the daily OpenClaw catalog behind the live NVIDIA feed', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-merge-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n };\n try {\n const result = await nvidia.discover({\n apiKey: 'nvidia-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [{\n model: 'live/model',\n 'model-name': 'Live Model',\n context: 128000,\n 'max-output': 8000,\n }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['live/model', 'static/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery does not replace caller cancellation with its static catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-cancel-'));\n const controller = new AbortController();\n try {\n await assert.rejects(nvidia.discover({\n cacheDir,\n signal: controller.signal,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n controller.abort();\n throw new Error('aborted');\n },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n reasoning: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n reasoning: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('five extended providers resolve from canonical URLs and explicit aliases without fetching', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n const canonical = [\n ['https://api.z.ai/api/paas/v4/', 'zai'],\n ['https://api.moonshot.ai/v1', 'moonshot'],\n ['https://api.moonshot.cn/v1/', 'moonshot'],\n ['https://api.deepseek.com', 'deepseek'],\n ['https://api.deepseek.com/v1/', 'deepseek'],\n ['https://generativelanguage.googleapis.com/v1beta/openai', 'google'],\n ['https://api.x.ai/v1/', 'xai'],\n ];\n for (const [baseUrl, provider] of canonical) {\n const result = await resolveProvider({ baseUrl, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'canonical-url');\n }\n for (const [alias, provider] of [['z-ai', 'zai'], ['z.ai', 'zai'], ['grok', 'xai']]) {\n const result = await resolveProvider({ provider: alias, fetchImpl });\n assert.equal(result.provider, provider);\n assert.equal(result.providerResolution, 'explicit');\n }\n assert.equal(fetchCalls, 0);\n});\n\ntest('local Ollama auto-detection reuses tags while unknown remote endpoints are not probed', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: null,\n providerResolution: 'unknown',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return [model];\n });\n assert.equal(first.cacheStatus, 'refreshed');\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.cacheStatus, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'meta/llama-test',\n name: 'Llama Test',\n input: ['text'],\n contextWindow: 65536,\n maxTokens: 4096,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, [\n OPENCLAW_CATALOGS.nvidia.url,\n 'https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json',\n ]);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n reasoning: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n reasoning: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n { name: 'command-a-plus-05-2026', is_deprecated: false },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 128000);\n assert.equal(result.models[0].maxOutputTokens, 64000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches live accessible models from the daily OpenClaw catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-openclaw-enrich-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-synced',\n name: 'Command Synced',\n input: ['text', 'image'],\n contextWindow: 200000,\n maxTokens: 16000,\n reasoning: true,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.cohere.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-synced' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command Synced');\n assert.equal(result.models[0].contextWindow, 200000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('static-backed compatible providers expose authenticated ids and enrich exact matches', async () => {\n const cases = [\n {\n adapter: zai,\n provider: 'zai',\n baseUrl: 'https://api.z.ai/api/paas/v4',\n staticId: 'glm-5.2',\n expectedContext: 1000000,\n },\n {\n adapter: moonshot,\n provider: 'moonshot',\n baseUrl: 'https://api.moonshot.cn/v1',\n staticId: 'kimi-k2.6',\n expectedContext: 262144,\n },\n {\n adapter: deepseek,\n provider: 'deepseek',\n baseUrl: 'https://api.deepseek.com/v1',\n staticId: 'deepseek-chat',\n expectedContext: 1000000,\n },\n ];\n for (const entry of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${entry.provider}-discovery-`));\n try {\n const result = await entry.adapter.discover({\n baseUrl: entry.baseUrl,\n apiKey: `${entry.provider}-secret`,\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS[entry.provider].url) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled catalog');\n }\n assert.equal(url, `${entry.baseUrl.replace(/\\/+$/u, '')}/models`);\n assert.equal(options.headers.Authorization, `Bearer ${entry.provider}-secret`);\n return new Response(JSON.stringify({\n data: [\n { id: entry.staticId },\n { id: 'account/custom', owned_by: 'account' },\n { id: 'bad embedding model' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), [entry.staticId, 'account/custom']);\n assert.equal(result.models[0].contextWindow, entry.expectedContext);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, null);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('static-backed discovery treats a malformed successful payload as refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zai-malformed-live-'));\n try {\n const result = await zai.discover({\n cacheDir,\n apiKey: 'zai-secret',\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.zai.url) throw new Error('use bundled catalog');\n return new Response('{\"unexpected\":true}');\n },\n });\n assert.ok(result.models.length > 0);\n assert.match(result.warnings.at(-1), /live catalog refresh failed/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Google discovery uses only its authenticated runtime model list', async () => {\n const result = await google.discover({\n apiKey: 'google-secret',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://generativelanguage.googleapis.com/v1beta/openai/models');\n assert.equal(options.headers.Authorization, 'Bearer google-secret');\n return new Response(JSON.stringify({\n data: [\n { id: 'gemini-3.1-pro', input_modalities: ['text', 'image'] },\n { id: 'text-embedding-004' },\n ],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['gemini-3.1-pro']);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n});\n\ntest('xAI discovery removes OpenClaw-suppressed models without sending its API key to GitHub', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xai-suppressions-'));\n try {\n const result = await xai.discover({\n apiKey: 'xai-secret',\n cacheDir,\n fetchImpl: async (url, options) => {\n if (url === 'https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/xai/openclaw.plugin.json') {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify({\n modelCatalog: {\n discovery: { xai: 'refreshable' },\n suppressions: [{ provider: 'xai', model: 'grok-multi-agent' }],\n },\n }));\n }\n assert.equal(url, 'https://api.x.ai/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer xai-secret');\n return new Response(JSON.stringify({\n data: [{ id: 'grok-4' }, { id: 'grok-multi-agent' }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['grok-4']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.slice(0, 3).map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.equal(result.warnings.some((warning) => /broken-model/u.test(warning)), true);\n});\n\ntest('Ollama discovery appends cloud candidates without inspecting or pulling them', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ollama-cloud-catalog-'));\n const calls = [];\n try {\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: { models: [{ name: 'local-model' }] },\n cacheDir,\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl: async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (String(url) === 'https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/ollama/openclaw.plugin.json') {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n 'ollama-cloud': {\n baseUrl: 'https://ollama.com',\n models: [{\n id: 'cloud-model:cloud',\n name: 'Cloud Model',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8192,\n }],\n },\n },\n },\n }));\n }\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(JSON.parse(options.body).name, 'local-model');\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n capabilities: ['completion'],\n }));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), ['local-model', 'cloud-model:cloud']);\n assert.deepEqual(calls.map((call) => call.authorization), [undefined, undefined]);\n assert.equal(calls.some((call) => call.url.endsWith('/api/pull')), false);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public discovery returns supplied models without probing an unresolved provider', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['custom/b', 'custom/a'],\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, null);\n assert.equal(result.providerResolution, 'unknown');\n assert.equal(result.source, 'supplied');\n assert.equal(result.cacheStatus, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models.map((model) => model.id), ['custom/b', 'custom/a']);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'nvidia/featured',\n name: 'Featured',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.deepEqual(refreshed.models.map((model) => model.id), [\n 'nvidia/featured',\n 'private/model',\n ]);\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('public discovery dispatches all five extended providers and retains supplied ids', async () => {\n const cases = [\n ['zai', 'https://api.z.ai/api/paas/v4', 'glm-5.2'],\n ['moonshot', 'https://api.moonshot.ai/v1', 'kimi-k2.6'],\n ['deepseek', 'https://api.deepseek.com', 'deepseek-chat'],\n ['google', 'https://generativelanguage.googleapis.com/v1beta/openai', 'gemini-test'],\n ['xai', 'https://api.x.ai/v1', 'grok-test'],\n ];\n for (const [provider, baseUrl, liveId] of cases) {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), `${provider}-public-`));\n try {\n const result = await discoverModels({\n provider,\n baseUrl,\n apiKey: 'provider-secret',\n suppliedModels: ['private/model'],\n cacheDir,\n fetchImpl: async (url, options) => {\n if (String(url).startsWith('https://raw.githubusercontent.com/openclaw/openclaw/main/extensions/')) {\n assert.equal(options.headers.Authorization, undefined);\n throw new Error('use bundled metadata');\n }\n assert.equal(url, `${baseUrl}/models`);\n assert.equal(options.headers.Authorization, 'Bearer provider-secret');\n return new Response(JSON.stringify({ data: [{ id: liveId }] }));\n },\n });\n assert.equal(result.provider, provider);\n assert.equal(result.discoverySkipped, false);\n assert.deepEqual(result.models.map((model) => model.id), [liveId, 'private/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n});\n\ntest('only the approved Ollama cloud pull bridge imports standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n if (name === 'ollama-cloud-pull.js') {\n assert.match(source, /model-discovery\\/openclaw-catalog/u);\n continue;\n }\n assert.doesNotMatch(\n source,\n /require\\([^)]*model-discovery/u,\n `${name} must not import standalone discovery`,\n );\n }\n});\n"}, "5d229d55d27a106643e18d12ece49dbab3dc4397": {"t": 1785758851.2190287, "n": 32177, "h": "44dca3bdf0179ae7", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst {\n CATALOG_TTL_MS,\n OPENCLAW_CATALOGS,\n loadOpenClawCatalog,\n parseOpenClawCatalog,\n} = require('../src/model-discovery/openclaw-catalog');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('OpenClaw catalog sync is allowlisted to NVIDIA and Cohere only', () => {\n assert.deepEqual(Object.keys(OPENCLAW_CATALOGS).sort(), ['cohere', 'nvidia']);\n assert.equal(CATALOG_TTL_MS, 24 * 60 * 60 * 1000);\n for (const entry of Object.values(OPENCLAW_CATALOGS)) {\n const url = new URL(entry.url);\n assert.equal(url.protocol, 'https:');\n assert.equal(url.hostname, 'raw.githubusercontent.com');\n assert.match(url.pathname, /^\\/openclaw\\/openclaw\\/main\\/extensions\\//u);\n assert.match(url.pathname, /\\/openclaw\\.plugin\\.json$/u);\n }\n assert.equal(OPENCLAW_CATALOGS.ollama, undefined);\n assert.equal(OPENCLAW_CATALOGS['ollama-cloud'], undefined);\n});\n\ntest('OpenClaw catalog parsing validates provider identity and drops deprecated models', () => {\n const payload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [\n {\n id: 'vendor/current',\n name: 'Current',\n input: ['text', 'image'],\n contextWindow: 131072,\n maxTokens: 8192,\n reasoning: true,\n compat: { supportsTools: true },\n },\n {\n id: 'vendor/old',\n name: 'Old',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4096,\n status: 'deprecated',\n },\n ],\n },\n },\n },\n };\n\n const models = parseOpenClawCatalog('nvidia', payload);\n assert.deepEqual(models.map((model) => model.id), ['vendor/current']);\n assert.deepEqual(models[0].inputModalities, ['text', 'image']);\n assert.equal(models[0].reasoning, true);\n assert.equal(models[0].toolCalling, true);\n assert.equal(models[0].source, 'openclaw-static');\n\n payload.modelCatalog.providers.nvidia.baseUrl = 'https://attacker.example/v1';\n assert.throws(() => parseOpenClawCatalog('nvidia', payload), /base URL/i);\n assert.throws(() => parseOpenClawCatalog('ollama', payload), /unsupported OpenClaw catalog/i);\n});\n\ntest('OpenClaw catalog sync refreshes at most daily and retains the last successful file', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-sync-'));\n let calls = 0;\n const payload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-test',\n name: 'Command Test',\n input: ['text'],\n contextWindow: 128000,\n maxTokens: 8000,\n }],\n },\n },\n },\n };\n try {\n const options = {\n provider: 'cohere',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, request) => {\n calls += 1;\n assert.equal(url, OPENCLAW_CATALOGS.cohere.url);\n assert.equal(request.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n },\n };\n const refreshed = await loadOpenClawCatalog(options);\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.deepEqual(refreshed.models.map((model) => model.id), ['command-test']);\n\n const fresh = await loadOpenClawCatalog({\n ...options,\n now: () => 1000 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh catalog must not fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 1);\n\n const stale = await loadOpenClawCatalog({\n ...options,\n now: () => 1001 + CATALOG_TTL_MS,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('offline');\n },\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((model) => model.id), ['command-test']);\n assert.match(stale.warnings[0], /last successful/i);\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync uses its bundled snapshot on first-run network failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-bundled-'));\n try {\n const result = await loadOpenClawCatalog({\n provider: 'nvidia',\n cacheDir,\n fetchImpl: async () => { throw new Error('offline'); },\n });\n assert.equal(result.cacheStatus, 'bundled');\n assert.ok(result.models.length > 0);\n assert.match(result.warnings[0], /bundled OpenClaw catalog/i);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('OpenClaw catalog sync does not replace caller cancellation with a bundled snapshot', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openclaw-catalog-cancel-'));\n const controller = new AbortController();\n controller.abort();\n try {\n await assert.rejects(loadOpenClawCatalog({\n provider: 'cohere',\n cacheDir,\n signal: controller.signal,\n fetchImpl: async () => { throw new Error('aborted'); },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery merges the daily OpenClaw catalog behind the live NVIDIA feed', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-merge-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n };\n try {\n const result = await nvidia.discover({\n apiKey: 'nvidia-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, nvidia.ENDPOINT);\n return new Response(JSON.stringify({\n 'featured-models': [{\n model: 'live/model',\n 'model-name': 'Live Model',\n context: 128000,\n 'max-output': 8000,\n }],\n }));\n },\n });\n assert.deepEqual(result.models.map((model) => model.id), ['live/model', 'static/model']);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery does not replace caller cancellation with its static catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-openclaw-cancel-'));\n const controller = new AbortController();\n try {\n await assert.rejects(nvidia.discover({\n cacheDir,\n signal: controller.signal,\n fetchImpl: async (url) => {\n if (url === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'static/model',\n name: 'Static Model',\n input: ['text'],\n contextWindow: 64000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n controller.abort();\n throw new Error('aborted');\n },\n }), (error) => error.code === 'CANCELLED');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n reasoning: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n reasoning: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('local Ollama auto-detection reuses tags while unknown remote endpoints are not probed', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url, options) => {\n calls.push(String(url));\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n apiKey: 'must-not-reach-local-ollama',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: null,\n providerResolution: 'unknown',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return [model];\n });\n assert.equal(first.cacheStatus, 'refreshed');\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.cacheStatus, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nvidia-featured-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n cacheDir,\n fetchImpl: async (url) => {\n calls.push(String(url));\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'meta/llama-test',\n name: 'Llama Test',\n input: ['text'],\n contextWindow: 65536,\n maxTokens: 4096,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, [\n OPENCLAW_CATALOGS.nvidia.url,\n 'https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json',\n ]);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n reasoning: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n reasoning: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async (t) => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-catalog-'));\n t.after(() => fs.rmSync(cacheDir, { recursive: true, force: true }));\n const payload = {\n models: [\n { name: 'command-a-plus-05-2026', is_deprecated: false },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n cacheDir,\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 128000);\n assert.equal(result.models[0].maxOutputTokens, 64000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery enriches live accessible models from the daily OpenClaw catalog', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cohere-openclaw-enrich-'));\n const staticPayload = {\n modelCatalog: {\n providers: {\n cohere: {\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n models: [{\n id: 'command-synced',\n name: 'Command Synced',\n input: ['text', 'image'],\n contextWindow: 200000,\n maxTokens: 16000,\n reasoning: true,\n compat: { supportsTools: true },\n }],\n },\n },\n },\n };\n try {\n const result = await cohere.discover({\n baseUrl: cohere.BASE_URL,\n apiKey: 'cohere-secret',\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url, options) => {\n if (url === OPENCLAW_CATALOGS.cohere.url) {\n assert.equal(options.headers.Authorization, undefined);\n return new Response(JSON.stringify(staticPayload));\n }\n assert.equal(url, cohere.ENDPOINT);\n assert.equal(options.headers.Authorization, 'Bearer cohere-secret');\n return new Response(JSON.stringify({ models: [{ name: 'command-synced' }] }));\n },\n });\n assert.equal(result.models.length, 1);\n assert.equal(result.models[0].displayName, 'Command Synced');\n assert.equal(result.models[0].contextWindow, 200000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n assert.equal(options.headers.Authorization, undefined);\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n apiKey: 'must-not-reach-local-ollama',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.match(result.warnings[0], /broken-model/);\n});\n\ntest('public discovery returns supplied models without probing an unresolved provider', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['custom/b', 'custom/a'],\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, null);\n assert.equal(result.providerResolution, 'unknown');\n assert.equal(result.source, 'supplied');\n assert.equal(result.cacheStatus, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models.map((model) => model.id), ['custom/b', 'custom/a']);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async (url) => {\n calls += 1;\n if (String(url) === OPENCLAW_CATALOGS.nvidia.url) {\n return new Response(JSON.stringify({\n modelCatalog: {\n providers: {\n nvidia: {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n models: [{\n id: 'nvidia/featured',\n name: 'Featured',\n input: ['text'],\n contextWindow: 32000,\n maxTokens: 4000,\n }],\n },\n },\n },\n }));\n }\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.deepEqual(refreshed.models.map((model) => model.id), [\n 'nvidia/featured',\n 'private/model',\n ]);\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 2);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('existing production modules do not import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n assert.doesNotMatch(source, /model-discovery/u, `${name} must not import standalone discovery`);\n }\n});\n"}, "f8952145a49f2d381179d113bdabbe7f65d1f18e": {"t": 1785758852.4747005, "n": 20855, "h": "830ecde442883591", "c": "'use strict';\n\nconst assert = require('node:assert/strict');\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst test = require('node:test');\n\nconst {\n mergeDiscoveredWithSupplied,\n normalizeSuppliedModels,\n} = require('../src/model-discovery/normalize');\nconst { resolveProvider } = require('../src/model-discovery/provider-resolution');\nconst { fetchJson } = require('../src/model-discovery/live-catalog');\nconst { cacheIdentity, withProviderCache } = require('../src/model-discovery/file-cache');\nconst nvidia = require('../src/model-discovery/providers/nvidia');\nconst openrouter = require('../src/model-discovery/providers/openrouter');\nconst cohere = require('../src/model-discovery/providers/cohere');\nconst ollama = require('../src/model-discovery/providers/ollama');\nconst { discoverModels } = require('../src/model-discovery');\n\ntest('supplied model ids are validated, deduplicated, and retain unknown metadata', () => {\n const models = normalizeSuppliedModels([' first/model ', 'second:model', 'first/model']);\n\n assert.deepEqual(models.map((model) => model.id), ['first/model', 'second:model']);\n assert.deepEqual(models[0], {\n id: 'first/model',\n displayName: 'first/model',\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n reasoning: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: null,\n maxOutputTokens: null,\n inputModalities: null,\n reasoning: null,\n toolCalling: null,\n },\n source: 'supplied',\n });\n assert.throws(() => normalizeSuppliedModels(['bad model']), /unsafe model id/i);\n assert.throws(() => normalizeSuppliedModels(['']), /unsafe model id/i);\n});\n\ntest('exact discovered rows enrich supplied ids and unmatched supplied ids append in CLI order', () => {\n const supplied = normalizeSuppliedModels(['extra/z', 'known/a', 'extra/b']);\n const discovered = [\n {\n ...supplied[1],\n displayName: 'Known A',\n contextWindow: 131072,\n metadataSources: { ...supplied[1].metadataSources, contextWindow: 'provider-catalog' },\n source: 'https://provider.example/catalog',\n },\n ];\n\n const models = mergeDiscoveredWithSupplied(discovered, supplied);\n\n assert.deepEqual(models.map((model) => model.id), ['known/a', 'extra/z', 'extra/b']);\n assert.equal(models[0].contextWindow, 131072);\n assert.equal(models[0].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('explicit and canonical provider resolution are deterministic and do not fetch', async () => {\n let fetchCalls = 0;\n const fetchImpl = async () => {\n fetchCalls += 1;\n throw new Error('unexpected fetch');\n };\n\n assert.deepEqual(await resolveProvider({ provider: 'nvidia', fetchImpl }), {\n provider: 'nvidia',\n providerResolution: 'explicit',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://openrouter.ai/v1/',\n fetchImpl,\n }), {\n provider: 'openrouter',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.deepEqual(await resolveProvider({\n baseUrl: 'https://api.cohere.ai/compatibility/v1',\n fetchImpl,\n }), {\n provider: 'cohere',\n providerResolution: 'canonical-url',\n detectionPayload: null,\n });\n assert.equal(fetchCalls, 0);\n await assert.rejects(resolveProvider({ provider: 'nvidai', fetchImpl }), /unknown provider/i);\n});\n\ntest('local Ollama auto-detection reuses tags while unknown remote endpoints are not probed', async () => {\n const calls = [];\n const payload = { models: [{ name: 'qwen3:8b' }] };\n const fetchImpl = async (url) => {\n calls.push(String(url));\n return new Response(JSON.stringify(payload));\n };\n\n const local = await resolveProvider({\n baseUrl: 'http://localhost:11434/v1/',\n fetchImpl,\n });\n assert.deepEqual(local, {\n provider: 'ollama',\n providerResolution: 'ollama-native',\n detectionPayload: payload,\n });\n assert.deepEqual(calls, ['http://localhost:11434/api/tags']);\n\n const remote = await resolveProvider({\n baseUrl: 'https://gateway.example.com/v1',\n suppliedModels: ['custom/model'],\n fetchImpl,\n });\n assert.deepEqual(remote, {\n provider: null,\n providerResolution: 'unknown',\n detectionPayload: null,\n });\n assert.equal(calls.length, 1);\n});\n\ntest('bounded JSON fetching rejects oversized responses without exposing credentials', async () => {\n const apiKey = 'super-secret-provider-key';\n await assert.rejects(\n fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n apiKey,\n maxBytes: 8,\n fetchImpl: async () => new Response('{\"models\":[1,2,3]}'),\n }),\n (error) => {\n assert.equal(error.code, 'RESPONSE_TOO_LARGE');\n assert.equal(error.provider, 'test');\n assert.doesNotMatch(error.message, new RegExp(apiKey));\n return true;\n },\n );\n});\n\ntest('bounded JSON fetching strips authorization on a cross-origin redirect', async () => {\n const calls = [];\n const fetchImpl = async (url, options) => {\n calls.push({ url: String(url), authorization: options.headers.Authorization });\n if (calls.length === 1) {\n return new Response('', {\n status: 302,\n headers: { Location: 'https://cdn.example/catalog.json' },\n });\n }\n return new Response('{\"models\":[]}');\n };\n\n const result = await fetchJson({\n url: 'https://provider.example/models',\n provider: 'test',\n apiKey: 'redirect-secret',\n fetchImpl,\n });\n\n assert.deepEqual(result, { models: [] });\n assert.deepEqual(calls, [\n { url: 'https://provider.example/models', authorization: 'Bearer redirect-secret' },\n { url: 'https://cdn.example/catalog.json', authorization: undefined },\n ]);\n});\n\ntest('bounded JSON fetching reports timeout, caller cancellation, and invalid JSON distinctly', async () => {\n const waitForAbort = async (_url, options) => new Promise((resolve, reject) => {\n if (options.signal.aborted) {\n reject(options.signal.reason || new Error('aborted'));\n return;\n }\n options.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true });\n });\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n timeoutMs: 5,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'TIMEOUT');\n\n const controller = new AbortController();\n controller.abort();\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n signal: controller.signal,\n fetchImpl: waitForAbort,\n }), (error) => error.code === 'CANCELLED');\n\n await assert.rejects(fetchJson({\n url: 'https://catalog.example/models',\n provider: 'test',\n fetchImpl: async () => new Response('{not-json'),\n }), (error) => error.code === 'INVALID_JSON');\n});\n\ntest('provider cache returns fresh data then the last successful stale data on refresh failure', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-cache-'));\n const model = normalizeSuppliedModels(['provider/model'])[0];\n model.source = 'https://catalog.example/models';\n try {\n let refreshes = 0;\n const common = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'cache-secret',\n cacheDir,\n ttlMs: 1000,\n };\n const first = await withProviderCache({ ...common, now: () => 1000 }, async () => {\n refreshes += 1;\n return [model];\n });\n assert.equal(first.cacheStatus, 'refreshed');\n\n const fresh = await withProviderCache({ ...common, now: () => 1500 }, async () => {\n refreshes += 1;\n throw new Error('must not refresh');\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(refreshes, 1);\n\n const stale = await withProviderCache({ ...common, now: () => 3000 }, async () => {\n refreshes += 1;\n throw new Error('provider offline');\n });\n assert.equal(stale.cacheStatus, 'stale');\n assert.deepEqual(stale.models.map((entry) => entry.id), ['provider/model']);\n assert.match(stale.warnings[0], /refresh failed/i);\n\n const files = fs.readdirSync(path.join(cacheDir, 'nvidia'));\n assert.equal(files.length, 1);\n const cacheText = fs.readFileSync(path.join(cacheDir, 'nvidia', files[0]), 'utf8');\n assert.doesNotMatch(cacheText, /cache-secret|catalog\\.example/u);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia')).mode & 0o077, 0);\n assert.equal(fs.statSync(path.join(cacheDir, 'nvidia', files[0])).mode & 0o077, 0);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache isolates endpoint and authentication scopes', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-scope-'));\n try {\n const refresh = async () => normalizeSuppliedModels(['scope/model']);\n const base = { provider: 'openrouter', cacheDir, ttlMs: 60000, now: () => 1000 };\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://two.example/models', apiKey: 'one' }, refresh);\n await withProviderCache({ ...base, endpoint: 'https://one.example/models', apiKey: 'two' }, refresh);\n\n assert.equal(fs.readdirSync(path.join(cacheDir, 'openrouter')).length, 3);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('provider cache ignores a corrupt matching file and replaces it after a successful refresh', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-corrupt-'));\n const options = {\n provider: 'nvidia',\n endpoint: 'https://catalog.example/models',\n apiKey: 'scope',\n cacheDir,\n ttlMs: 60000,\n now: () => 1000,\n };\n try {\n const identity = cacheIdentity(options);\n fs.mkdirSync(identity.directory, { recursive: true });\n fs.writeFileSync(identity.file, '{broken', 'utf8');\n const result = await withProviderCache(options, async () => normalizeSuppliedModels(['new/model']));\n assert.equal(result.cacheStatus, 'refreshed');\n assert.match(result.warnings[0], /invalid provider discovery cache/i);\n assert.doesNotThrow(() => JSON.parse(fs.readFileSync(identity.file, 'utf8')));\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('NVIDIA discovery maps bounded featured rows and preserves feed order', async () => {\n const calls = [];\n const payload = {\n 'featured-models': [\n { model: 'nemotron-test', 'model-name': 'Nemotron Test', context: 131072, 'max-output': 8192 },\n { model: 'meta/llama-test', 'model-name': 'Llama Test', context: 65536, 'max-output': 4096 },\n { model: 'bad model', 'model-name': 'Bad', context: 1, 'max-output': 1 },\n { model: 'missing-context', 'model-name': 'Missing', 'max-output': 1 },\n ],\n };\n const result = await nvidia.discover({\n fetchImpl: async (url) => {\n calls.push(String(url));\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(calls, ['https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json']);\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), ['nvidia/nemotron-test', 'meta/llama-test']);\n assert.deepEqual(models[0], {\n id: 'nvidia/nemotron-test',\n displayName: 'Nemotron Test',\n contextWindow: 131072,\n maxOutputTokens: 8192,\n inputModalities: ['text'],\n reasoning: null,\n toolCalling: null,\n metadataSources: {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n reasoning: null,\n toolCalling: null,\n },\n source: 'nvidia-featured',\n });\n});\n\ntest('OpenRouter discovery preserves authoritative metadata and rejects non-text output models', async () => {\n const payload = {\n data: [\n {\n id: 'vendor/z-model',\n name: 'Z Model',\n context_length: 128000,\n max_output_tokens: 4096,\n architecture: {\n input_modalities: ['text', 'image'],\n output_modalities: ['text'],\n },\n supported_parameters: ['reasoning', 'tools', 'tool_choice'],\n top_provider: { context_length: 200000, max_completion_tokens: 16384 },\n },\n {\n id: 'vendor/image-only',\n architecture: { input_modalities: ['text'], output_modalities: ['image'] },\n },\n {\n id: 'vendor/a-model',\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/a-model', context_length: 999 },\n {\n id: 'vendor/huge-model',\n context_length: 20000000,\n max_output_tokens: 2000000,\n architecture: { modality: 'text->text' },\n },\n { id: 'vendor/text-embedding-3-small' },\n { id: 'vendor/deprecated-chat', deprecated: true },\n ],\n };\n const result = await openrouter.discover({\n apiKey: 'openrouter-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://openrouter.ai/api/v1/models');\n assert.equal(options.headers.Authorization, 'Bearer openrouter-key');\n return new Response(JSON.stringify(payload));\n },\n });\n const models = result.models;\n\n assert.deepEqual(result.warnings, []);\n assert.deepEqual(models.map((model) => model.id), [\n 'vendor/a-model',\n 'vendor/huge-model',\n 'vendor/z-model',\n ]);\n const rich = models[2];\n assert.equal(rich.contextWindow, 200000);\n assert.equal(rich.maxOutputTokens, 16384);\n assert.deepEqual(rich.inputModalities, ['text', 'image']);\n assert.equal(rich.reasoning, true);\n assert.equal(rich.toolCalling, true);\n assert.deepEqual(rich.metadataSources, {\n contextWindow: 'provider-catalog',\n maxOutputTokens: 'provider-catalog',\n inputModalities: 'provider-catalog',\n reasoning: 'provider-catalog',\n toolCalling: 'provider-catalog',\n });\n assert.equal(models[0].contextWindow, null);\n assert.equal(models[0].maxOutputTokens, null);\n assert.equal(models[1].contextWindow, null);\n assert.equal(models[1].maxOutputTokens, null);\n});\n\ntest('Cohere discovery rejects deprecated rows and fills only exact-model seed metadata', async () => {\n const payload = {\n models: [\n { name: 'command-a-plus-05-2026', is_deprecated: false },\n {\n name: 'custom-chat-model',\n context_window: 99999,\n max_output_tokens: 1234,\n input_modalities: ['text'],\n reasoning: false,\n supports_tools: true,\n },\n { name: 'old-command', is_deprecated: true },\n ],\n };\n const result = await cohere.discover({\n baseUrl: 'https://api.cohere.ai/compatibility/v1/',\n apiKey: 'cohere-key',\n fetchImpl: async (url, options) => {\n assert.equal(url, 'https://api.cohere.com/v1/models?endpoint=chat&page_size=1000');\n assert.equal(options.headers.Authorization, 'Bearer cohere-key');\n return new Response(JSON.stringify(payload));\n },\n });\n\n assert.deepEqual(result.models.map((model) => model.id), [\n 'command-a-plus-05-2026',\n 'custom-chat-model',\n ]);\n assert.equal(result.models[0].contextWindow, 128000);\n assert.equal(result.models[0].maxOutputTokens, 64000);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].metadataSources.contextWindow, 'provider-seed');\n assert.equal(result.models[1].contextWindow, 99999);\n assert.equal(result.models[1].toolCalling, true);\n assert.equal(result.models[1].metadataSources.contextWindow, 'provider-catalog');\n});\n\ntest('Cohere discovery skips noncanonical base URLs without probing them', async () => {\n let fetched = false;\n const result = await cohere.discover({\n baseUrl: 'https://cohere-gateway.example/v1',\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n assert.equal(fetched, false);\n assert.deepEqual(result.models, []);\n assert.match(result.warnings[0], /noncanonical/i);\n});\n\ntest('Ollama discovery combines native context metadata with num_ctx and tolerates partial failures', async () => {\n const tagsPayload = {\n models: [\n { name: 'vision-model', digest: 'one' },\n { name: 'broken-model', digest: 'two' },\n ],\n };\n let active = 0;\n let maxActive = 0;\n const fetchImpl = async (url, options) => {\n assert.equal(url, 'http://localhost:11434/api/show');\n const body = JSON.parse(options.body);\n active += 1;\n maxActive = Math.max(maxActive, active);\n await new Promise((resolve) => setTimeout(resolve, 5));\n active -= 1;\n if (body.name === 'broken-model') return new Response('failure', { status: 500 });\n if (body.name === 'vision-model') {\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 8192 },\n parameters: 'num_ctx 4096\\nnum_ctx 32768',\n capabilities: ['completion', 'vision', 'thinking', 'tools'],\n }));\n }\n return new Response(JSON.stringify({\n model_info: { 'test.context_length': 131072 },\n parameters: 'num_ctx 4096',\n capabilities: ['completion'],\n }));\n };\n\n const result = await ollama.discover({\n baseUrl: 'http://localhost:11434/v1',\n detectionPayload: tagsPayload,\n suppliedModels: ['extra-model'],\n concurrency: 2,\n fetchImpl,\n });\n\n assert.equal(maxActive, 2);\n assert.deepEqual(result.models.map((model) => model.id), [\n 'vision-model',\n 'broken-model',\n 'extra-model',\n ]);\n assert.equal(result.models[0].contextWindow, 32768);\n assert.deepEqual(result.models[0].inputModalities, ['text', 'image']);\n assert.equal(result.models[0].reasoning, true);\n assert.equal(result.models[0].toolCalling, true);\n assert.equal(result.models[0].maxOutputTokens, null);\n assert.equal(result.models[2].contextWindow, 131072);\n assert.deepEqual(result.models[2].inputModalities, ['text']);\n assert.equal(result.models[2].reasoning, false);\n assert.equal(result.models[2].toolCalling, false);\n assert.equal(result.models[1].contextWindow, null);\n assert.equal(result.models[1].inputModalities, null);\n assert.match(result.warnings[0], /broken-model/);\n});\n\ntest('public discovery returns supplied models without probing an unresolved provider', async () => {\n let fetched = false;\n const result = await discoverModels({\n baseUrl: 'https://custom-provider.example/v1',\n suppliedModels: ['custom/b', 'custom/a'],\n fetchImpl: async () => {\n fetched = true;\n throw new Error('must not fetch');\n },\n });\n\n assert.equal(fetched, false);\n assert.equal(result.provider, null);\n assert.equal(result.providerResolution, 'unknown');\n assert.equal(result.source, 'supplied');\n assert.equal(result.cacheStatus, 'none');\n assert.equal(result.discoverySkipped, true);\n assert.deepEqual(result.models.map((model) => model.id), ['custom/b', 'custom/a']);\n});\n\ntest('public discovery auto-resolves NVIDIA, caches its catalog, and retains unmatched supplied ids', async () => {\n const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'model-discovery-public-'));\n let calls = 0;\n try {\n const options = {\n baseUrl: 'https://integrate.api.nvidia.com/v1',\n suppliedModels: ['private/model'],\n cacheDir,\n now: () => 1000,\n fetchImpl: async () => {\n calls += 1;\n return new Response(JSON.stringify({\n 'featured-models': [\n { model: 'featured', 'model-name': 'Featured', context: 32000, 'max-output': 4000 },\n ],\n }));\n },\n };\n const refreshed = await discoverModels(options);\n assert.equal(refreshed.provider, 'nvidia');\n assert.equal(refreshed.providerResolution, 'canonical-url');\n assert.equal(refreshed.cacheStatus, 'refreshed');\n assert.equal(refreshed.discoverySkipped, false);\n assert.deepEqual(refreshed.models.map((model) => model.id), [\n 'nvidia/featured',\n 'private/model',\n ]);\n\n const fresh = await discoverModels({\n ...options,\n now: () => 1500,\n fetchImpl: async () => {\n calls += 1;\n throw new Error('fresh cache should avoid fetch');\n },\n });\n assert.equal(fresh.cacheStatus, 'fresh');\n assert.equal(calls, 1);\n } finally {\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n});\n\ntest('existing production modules do not import standalone model discovery', () => {\n const sourceDir = path.join(__dirname, '..', 'src');\n const productionFiles = fs.readdirSync(sourceDir)\n .filter((name) => name.endsWith('.js'));\n for (const name of productionFiles) {\n const source = fs.readFileSync(path.join(sourceDir, name), 'utf8');\n assert.doesNotMatch(source, /model-discovery/u, `${name} must not import standalone discovery`);\n }\n});\n"}}, "src/model-discovery/provider-registry.js": {"3b65cc0144db5b7508dd93aadc3f8fe063d73171": {"t": 1785746695.4313767, "n": 3878, "h": "54cc1917497808c4", "c": "'use strict';\n\nconst anthropic = require('./providers/anthropic');\nconst cohere = require('./providers/cohere');\nconst custom = require('./providers/custom');\nconst deepseek = require('./providers/deepseek');\nconst google = require('./providers/google');\nconst moonshot = require('./providers/moonshot');\nconst nvidia = require('./providers/nvidia');\nconst ollama = require('./providers/ollama');\nconst openai = require('./providers/openai');\nconst openrouter = require('./providers/openrouter');\nconst xai = require('./providers/xai');\nconst zai = require('./providers/zai');\n\nconst PROVIDERS = Object.freeze({\n anthropic: definition(anthropic, {\n aliases: ['claude'],\n canonicalUrls: ['https://api.anthropic.com/v1'],\n }),\n nvidia: definition(nvidia, {\n canonicalUrls: ['https://integrate.api.nvidia.com/v1'],\n cacheEndpoint: () => nvidia.ENDPOINT,\n }),\n openrouter: definition(openrouter, {\n canonicalUrls: ['https://openrouter.ai/api/v1', 'https://openrouter.ai/v1'],\n cacheEndpoint: () => openrouter.ENDPOINT,\n }),\n cohere: definition(cohere, {\n canonicalUrls: ['https://api.cohere.ai/compatibility/v1'],\n cacheEndpoint: ({ baseUrl }) => normalizeUrl(baseUrl || cohere.BASE_URL) === cohere.BASE_URL\n ? cohere.ENDPOINT\n : null,\n }),\n ollama: definition(ollama, {\n traits: { inventoryComplete: true, nativeInspection: true },\n cacheEndpoint: ({ baseUrl }) => `${ollama.resolveApiBase(baseUrl)}/api/tags`,\n }),\n openai: definition(openai, {\n canonicalUrls: ['https://api.openai.com/v1'],\n }),\n zai: definition(zai, {\n aliases: ['z-ai', 'z.ai'],\n canonicalUrls: ['https://api.z.ai/api/paas/v4'],\n }),\n moonshot: definition(moonshot, {\n canonicalUrls: ['https://api.moonshot.ai/v1', 'https://api.moonshot.cn/v1'],\n }),\n deepseek: definition(deepseek, {\n canonicalUrls: ['https://api.deepseek.com', 'https://api.deepseek.com/v1'],\n }),\n google: definition(google, {\n aliases: ['aistudio', 'gemini', 'google-ai-studio', 'vertexai', 'vertex-ai', 'vertex'],\n canonicalUrls: ['https://generativelanguage.googleapis.com/v1beta/openai'],\n }),\n xai: definition(xai, {\n aliases: ['grok'],\n canonicalUrls: ['https://api.x.ai/v1'],\n }),\n custom: definition(custom),\n});\n\nfunction definition(adapter, options = {}) {\n return Object.freeze({\n adapter,\n aliases: Object.freeze([...(options.aliases || [])]),\n canonicalUrls: Object.freeze([...(options.canonicalUrls || [])]),\n cacheEndpoint: options.cacheEndpoint\n || (({ baseUrl }) => typeof adapter.endpointFor === 'function'\n ? adapter.endpointFor(baseUrl)\n : null),\n traits: Object.freeze({\n inventoryComplete: false,\n nativeInspection: false,\n ...(options.traits || {}),\n }),\n });\n}\n\nfunction normalizedEndpoint(url) {\n const pathname = url.pathname.replace(/\\/+$/u, '') || '/';\n return url.origin + (pathname === '/' ? '' : pathname);\n}\n\nfunction normalizeUrl(value) {\n try {\n return normalizedEndpoint(new URL(value));\n } catch {\n return '';\n }\n}\n\nconst ALIASES = new Map();\nconst CANONICAL_URLS = new Map();\nfor (const [provider, definitionValue] of Object.entries(PROVIDERS)) {\n for (const alias of definitionValue.aliases) ALIASES.set(alias, provider);\n for (const url of definitionValue.canonicalUrls) CANONICAL_URLS.set(url, provider);\n}\n\nfunction providerForAlias(value) {\n return ALIASES.get(value) || null;\n}\n\nfunction providerForCanonicalUrl(url) {\n if (!(url instanceof URL) || url.search || url.hash) return null;\n return CANONICAL_URLS.get(normalizedEndpoint(url)) || null;\n}\n\nfunction cacheEndpointFor(provider, options = {}) {\n const providerDefinition = PROVIDERS[provider];\n return providerDefinition ? providerDefinition.cacheEndpoint(options) : null;\n}\n\nmodule.exports = {\n PROVIDERS,\n cacheEndpointFor,\n providerForAlias,\n providerForCanonicalUrl,\n};\n"}, "6745d842778c429be9ce76fd04582ce1f52f215a": {"t": 1785758803.226061, "n": 3878, "h": "54cc1917497808c4", "c": "'use strict';\n\nconst anthropic = require('./providers/anthropic');\nconst cohere = require('./providers/cohere');\nconst custom = require('./providers/custom');\nconst deepseek = require('./providers/deepseek');\nconst google = require('./providers/google');\nconst moonshot = require('./providers/moonshot');\nconst nvidia = require('./providers/nvidia');\nconst ollama = require('./providers/ollama');\nconst openai = require('./providers/openai');\nconst openrouter = require('./providers/openrouter');\nconst xai = require('./providers/xai');\nconst zai = require('./providers/zai');\n\nconst PROVIDERS = Object.freeze({\n anthropic: definition(anthropic, {\n aliases: ['claude'],\n canonicalUrls: ['https://api.anthropic.com/v1'],\n }),\n nvidia: definition(nvidia, {\n canonicalUrls: ['https://integrate.api.nvidia.com/v1'],\n cacheEndpoint: () => nvidia.ENDPOINT,\n }),\n openrouter: definition(openrouter, {\n canonicalUrls: ['https://openrouter.ai/api/v1', 'https://openrouter.ai/v1'],\n cacheEndpoint: () => openrouter.ENDPOINT,\n }),\n cohere: definition(cohere, {\n canonicalUrls: ['https://api.cohere.ai/compatibility/v1'],\n cacheEndpoint: ({ baseUrl }) => normalizeUrl(baseUrl || cohere.BASE_URL) === cohere.BASE_URL\n ? cohere.ENDPOINT\n : null,\n }),\n ollama: definition(ollama, {\n traits: { inventoryComplete: true, nativeInspection: true },\n cacheEndpoint: ({ baseUrl }) => `${ollama.resolveApiBase(baseUrl)}/api/tags`,\n }),\n openai: definition(openai, {\n canonicalUrls: ['https://api.openai.com/v1'],\n }),\n zai: definition(zai, {\n aliases: ['z-ai', 'z.ai'],\n canonicalUrls: ['https://api.z.ai/api/paas/v4'],\n }),\n moonshot: definition(moonshot, {\n canonicalUrls: ['https://api.moonshot.ai/v1', 'https://api.moonshot.cn/v1'],\n }),\n deepseek: definition(deepseek, {\n canonicalUrls: ['https://api.deepseek.com', 'https://api.deepseek.com/v1'],\n }),\n google: definition(google, {\n aliases: ['aistudio', 'gemini', 'google-ai-studio', 'vertexai', 'vertex-ai', 'vertex'],\n canonicalUrls: ['https://generativelanguage.googleapis.com/v1beta/openai'],\n }),\n xai: definition(xai, {\n aliases: ['grok'],\n canonicalUrls: ['https://api.x.ai/v1'],\n }),\n custom: definition(custom),\n});\n\nfunction definition(adapter, options = {}) {\n return Object.freeze({\n adapter,\n aliases: Object.freeze([...(options.aliases || [])]),\n canonicalUrls: Object.freeze([...(options.canonicalUrls || [])]),\n cacheEndpoint: options.cacheEndpoint\n || (({ baseUrl }) => typeof adapter.endpointFor === 'function'\n ? adapter.endpointFor(baseUrl)\n : null),\n traits: Object.freeze({\n inventoryComplete: false,\n nativeInspection: false,\n ...(options.traits || {}),\n }),\n });\n}\n\nfunction normalizedEndpoint(url) {\n const pathname = url.pathname.replace(/\\/+$/u, '') || '/';\n return url.origin + (pathname === '/' ? '' : pathname);\n}\n\nfunction normalizeUrl(value) {\n try {\n return normalizedEndpoint(new URL(value));\n } catch {\n return '';\n }\n}\n\nconst ALIASES = new Map();\nconst CANONICAL_URLS = new Map();\nfor (const [provider, definitionValue] of Object.entries(PROVIDERS)) {\n for (const alias of definitionValue.aliases) ALIASES.set(alias, provider);\n for (const url of definitionValue.canonicalUrls) CANONICAL_URLS.set(url, provider);\n}\n\nfunction providerForAlias(value) {\n return ALIASES.get(value) || null;\n}\n\nfunction providerForCanonicalUrl(url) {\n if (!(url instanceof URL) || url.search || url.hash) return null;\n return CANONICAL_URLS.get(normalizedEndpoint(url)) || null;\n}\n\nfunction cacheEndpointFor(provider, options = {}) {\n const providerDefinition = PROVIDERS[provider];\n return providerDefinition ? providerDefinition.cacheEndpoint(options) : null;\n}\n\nmodule.exports = {\n PROVIDERS,\n cacheEndpointFor,\n providerForAlias,\n providerForCanonicalUrl,\n};\n"}, "5b8f9c2a0758538f9c3f7787cdee3bf7d271f7e6": {"t": 1785758804.5018587, "n": 3572, "h": "79b378eb6a237dd2", "c": "'use strict';\n\nconst cohere = require('./providers/cohere');\nconst custom = require('./providers/custom');\nconst deepseek = require('./providers/deepseek');\nconst google = require('./providers/google');\nconst moonshot = require('./providers/moonshot');\nconst nvidia = require('./providers/nvidia');\nconst ollama = require('./providers/ollama');\nconst openrouter = require('./providers/openrouter');\nconst xai = require('./providers/xai');\nconst zai = require('./providers/zai');\n\nconst PROVIDERS = Object.freeze({\n nvidia: definition(nvidia, {\n canonicalUrls: ['https://integrate.api.nvidia.com/v1'],\n cacheEndpoint: () => nvidia.ENDPOINT,\n }),\n openrouter: definition(openrouter, {\n canonicalUrls: ['https://openrouter.ai/api/v1', 'https://openrouter.ai/v1'],\n cacheEndpoint: () => openrouter.ENDPOINT,\n }),\n cohere: definition(cohere, {\n canonicalUrls: ['https://api.cohere.ai/compatibility/v1'],\n cacheEndpoint: ({ baseUrl }) => normalizeUrl(baseUrl || cohere.BASE_URL) === cohere.BASE_URL\n ? cohere.ENDPOINT\n : null,\n }),\n ollama: definition(ollama, {\n traits: { inventoryComplete: true, nativeInspection: true },\n cacheEndpoint: ({ baseUrl }) => `${ollama.resolveApiBase(baseUrl)}/api/tags`,\n }),\n zai: definition(zai, {\n aliases: ['z-ai', 'z.ai'],\n canonicalUrls: ['https://api.z.ai/api/paas/v4'],\n }),\n moonshot: definition(moonshot, {\n canonicalUrls: ['https://api.moonshot.ai/v1', 'https://api.moonshot.cn/v1'],\n }),\n deepseek: definition(deepseek, {\n canonicalUrls: ['https://api.deepseek.com', 'https://api.deepseek.com/v1'],\n }),\n google: definition(google, {\n aliases: ['aistudio', 'gemini', 'google-ai-studio', 'vertexai', 'vertex-ai', 'vertex'],\n canonicalUrls: ['https://generativelanguage.googleapis.com/v1beta/openai'],\n }),\n xai: definition(xai, {\n aliases: ['grok'],\n canonicalUrls: ['https://api.x.ai/v1'],\n }),\n custom: definition(custom),\n});\n\nfunction definition(adapter, options = {}) {\n return Object.freeze({\n adapter,\n aliases: Object.freeze([...(options.aliases || [])]),\n canonicalUrls: Object.freeze([...(options.canonicalUrls || [])]),\n cacheEndpoint: options.cacheEndpoint\n || (({ baseUrl }) => typeof adapter.endpointFor === 'function'\n ? adapter.endpointFor(baseUrl)\n : null),\n traits: Object.freeze({\n inventoryComplete: false,\n nativeInspection: false,\n ...(options.traits || {}),\n }),\n });\n}\n\nfunction normalizedEndpoint(url) {\n const pathname = url.pathname.replace(/\\/+$/u, '') || '/';\n return url.origin + (pathname === '/' ? '' : pathname);\n}\n\nfunction normalizeUrl(value) {\n try {\n return normalizedEndpoint(new URL(value));\n } catch {\n return '';\n }\n}\n\nconst ALIASES = new Map();\nconst CANONICAL_URLS = new Map();\nfor (const [provider, definitionValue] of Object.entries(PROVIDERS)) {\n for (const alias of definitionValue.aliases) ALIASES.set(alias, provider);\n for (const url of definitionValue.canonicalUrls) CANONICAL_URLS.set(url, provider);\n}\n\nfunction providerForAlias(value) {\n return ALIASES.get(value) || null;\n}\n\nfunction providerForCanonicalUrl(url) {\n if (!(url instanceof URL) || url.search || url.hash) return null;\n return CANONICAL_URLS.get(normalizedEndpoint(url)) || null;\n}\n\nfunction cacheEndpointFor(provider, options = {}) {\n const providerDefinition = PROVIDERS[provider];\n return providerDefinition ? providerDefinition.cacheEndpoint(options) : null;\n}\n\nmodule.exports = {\n PROVIDERS,\n cacheEndpointFor,\n providerForAlias,\n providerForCanonicalUrl,\n};\n"}, "3851d1757ed2bb129fbddb1b2fa8dfda51566944": {"t": 1785758805.9211578, "n": 3480, "h": "9ed58bd1085bbf5d", "c": "'use strict';\n\nconst cohere = require('./providers/cohere');\nconst custom = require('./providers/custom');\nconst deepseek = require('./providers/deepseek');\nconst google = require('./providers/google');\nconst moonshot = require('./providers/moonshot');\nconst nvidia = require('./providers/nvidia');\nconst ollama = require('./providers/ollama');\nconst openrouter = require('./providers/openrouter');\nconst xai = require('./providers/xai');\nconst zai = require('./providers/zai');\n\nconst PROVIDERS = Object.freeze({\n nvidia: definition(nvidia, {\n canonicalUrls: ['https://integrate.api.nvidia.com/v1'],\n cacheEndpoint: () => nvidia.ENDPOINT,\n }),\n openrouter: definition(openrouter, {\n canonicalUrls: ['https://openrouter.ai/api/v1', 'https://openrouter.ai/v1'],\n cacheEndpoint: () => openrouter.ENDPOINT,\n }),\n cohere: definition(cohere, {\n canonicalUrls: ['https://api.cohere.ai/compatibility/v1'],\n cacheEndpoint: ({ baseUrl }) => normalizeUrl(baseUrl || cohere.BASE_URL) === cohere.BASE_URL\n ? cohere.ENDPOINT\n : null,\n }),\n ollama: definition(ollama, {\n traits: { inventoryComplete: true, nativeInspection: true },\n cacheEndpoint: ({ baseUrl }) => `${ollama.resolveApiBase(baseUrl)}/api/tags`,\n }),\n zai: definition(zai, {\n aliases: ['z-ai', 'z.ai'],\n canonicalUrls: ['https://api.z.ai/api/paas/v4'],\n }),\n moonshot: definition(moonshot, {\n canonicalUrls: ['https://api.moonshot.ai/v1', 'https://api.moonshot.cn/v1'],\n }),\n deepseek: definition(deepseek, {\n canonicalUrls: ['https://api.deepseek.com', 'https://api.deepseek.com/v1'],\n }),\n google: definition(google, {\n canonicalUrls: ['https://generativelanguage.googleapis.com/v1beta/openai'],\n }),\n xai: definition(xai, {\n aliases: ['grok'],\n canonicalUrls: ['https://api.x.ai/v1'],\n }),\n custom: definition(custom),\n});\n\nfunction definition(adapter, options = {}) {\n return Object.freeze({\n adapter,\n aliases: Object.freeze([...(options.aliases || [])]),\n canonicalUrls: Object.freeze([...(options.canonicalUrls || [])]),\n cacheEndpoint: options.cacheEndpoint\n || (({ baseUrl }) => typeof adapter.endpointFor === 'function'\n ? adapter.endpointFor(baseUrl)\n : null),\n traits: Object.freeze({\n inventoryComplete: false,\n nativeInspection: false,\n ...(options.traits || {}),\n }),\n });\n}\n\nfunction normalizedEndpoint(url) {\n const pathname = url.pathname.replace(/\\/+$/u, '') || '/';\n return url.origin + (pathname === '/' ? '' : pathname);\n}\n\nfunction normalizeUrl(value) {\n try {\n return normalizedEndpoint(new URL(value));\n } catch {\n return '';\n }\n}\n\nconst ALIASES = new Map();\nconst CANONICAL_URLS = new Map();\nfor (const [provider, definitionValue] of Object.entries(PROVIDERS)) {\n for (const alias of definitionValue.aliases) ALIASES.set(alias, provider);\n for (const url of definitionValue.canonicalUrls) CANONICAL_URLS.set(url, provider);\n}\n\nfunction providerForAlias(value) {\n return ALIASES.get(value) || null;\n}\n\nfunction providerForCanonicalUrl(url) {\n if (!(url instanceof URL) || url.search || url.hash) return null;\n return CANONICAL_URLS.get(normalizedEndpoint(url)) || null;\n}\n\nfunction cacheEndpointFor(provider, options = {}) {\n const providerDefinition = PROVIDERS[provider];\n return providerDefinition ? providerDefinition.cacheEndpoint(options) : null;\n}\n\nmodule.exports = {\n PROVIDERS,\n cacheEndpointFor,\n providerForAlias,\n providerForCanonicalUrl,\n};\n"}, "25a0f55664650458236a53de60f5041463c11499": {"t": 1785758807.3524706, "n": 3509, "h": "0d3d0e8744b2af08", "c": "'use strict';\n\nconst cohere = require('./providers/cohere');\nconst custom = require('./providers/custom');\nconst deepseek = require('./providers/deepseek');\nconst google = require('./providers/google');\nconst moonshot = require('./providers/moonshot');\nconst nvidia = require('./providers/nvidia');\nconst ollama = require('./providers/ollama');\nconst openrouter = require('./providers/openrouter');\nconst xai = require('./providers/xai');\nconst zai = require('./providers/zai');\n\nconst PROVIDERS = Object.freeze({\n nvidia: definition(nvidia, {\n canonicalUrls: ['https://integrate.api.nvidia.com/v1'],\n cacheEndpoint: () => nvidia.ENDPOINT,\n }),\n openrouter: definition(openrouter, {\n canonicalUrls: ['https://openrouter.ai/api/v1', 'https://openrouter.ai/v1'],\n cacheEndpoint: () => openrouter.ENDPOINT,\n }),\n cohere: definition(cohere, {\n canonicalUrls: ['https://api.cohere.ai/compatibility/v1'],\n cacheEndpoint: ({ baseUrl }) => normalizeUrl(baseUrl || cohere.BASE_URL) === cohere.BASE_URL\n ? cohere.ENDPOINT\n : null,\n }),\n ollama: definition(ollama, {\n traits: { inventoryComplete: true, nativeInspection: true },\n cacheEndpoint: ({ baseUrl }) => `${ollama.resolveApiBase(baseUrl)}/api/tags`,\n }),\n zai: definition(zai, {\n aliases: ['z-ai', 'z.ai'],\n canonicalUrls: ['https://api.z.ai/api/paas/v4'],\n }),\n moonshot: definition(moonshot, {\n canonicalUrls: ['https://api.moonshot.ai/v1', 'https://api.moonshot.cn/v1'],\n }),\n deepseek: definition(deepseek, {\n canonicalUrls: ['https://api.deepseek.com', 'https://api.deepseek.com/v1'],\n }),\n google: definition(google, {\n canonicalUrls: ['https://generativelanguage.googleapis.com/v1beta/openai'],\n }),\n xai: definition(xai, {\n aliases: ['grok'],\n canonicalUrls: ['https://api.x.ai/v1'],\n }),\n custom: definition(custom),\n});\n\nfunction definition(adapter, options = {}) {\n return Object.freeze({\n adapter,\n aliases: Object.freeze([...(options.aliases || [])]),\n canonicalUrls: Object.freeze([...(options.canonicalUrls || [])]),\n cacheEndpoint: options.cacheEndpoint\n || (({ baseUrl }) => typeof adapter.endpointFor === 'function'\n ? adapter.endpointFor(baseUrl)\n : null),\n traits: Object.freeze({\n inventoryComplete: false,\n nativeInspection: false,\n ...(options.traits || {}),\n }),\n });\n}\n\nfunction normalizedEndpoint(url) {\n const pathname = url.pathname.replace(/\\/+$/u, '') || '/';\n return url.origin + (pathname === '/' ? '' : pathname);\n}\n\nfunction normalizeUrl(value) {\n try {\n return normalizedEndpoint(new URL(value));\n } catch {\n return '';\n }\n}\n\nconst ALIASES = new Map();\nconst CANONICAL_URLS = new Map();\nfor (const [provider, definitionValue] of Object.entries(PROVIDERS)) {\n for (const alias of definitionValue.aliases) ALIASES.set(alias, provider);\n for (const url of definitionValue.canonicalUrls) CANONICAL_URLS.set(url, provider);\n}\n\nfunction providerForAlias(value) {\n return ALIASES.get(value) || null;\n}\n\nfunction providerForCanonicalUrl(url) {\n if (!(url instanceof URL) || url.search || url.hash) return null;\n return CANONICAL_URLS.get(normalizedEndpoint(url)) || null;\n}\n\nfunction cacheEndpointFor(provider, options = {}) {\n const providerDefinition = PROVIDERS[provider];\n return providerDefinition ? providerDefinition.cacheEndpoint(options) : null;\n}\n\nmodule.exports = {\n ALIASES,\n CANONICAL_URLS,\n PROVIDERS,\n cacheEndpointFor,\n providerForAlias,\n providerForCanonicalUrl,\n};\n"}}}} |