SIGN IN SIGN UP

feat: unified model registry using models.dev metadata (#647)

* feat: add unified model registry using models.dev as metadata source

Replace the backend API enrichment (getProviderModelsInfo) with a local
model registry powered by models.dev data. This provides zero-latency
model metadata lookups for context windows, capabilities, and more.

- Bundle a build-time snapshot (364 models, 9 providers) from models.dev
- Runtime cache chain: memory → localStorage (7-day TTL) → snapshot
- Enrich provider models with capabilities, contextWindow, maxOutput
- Add curated model ID lists to 10 built-in provider definitions
- Surface newly discovered models with "New" badge in model selectors
- Fall back to registry when official provider API returns empty
- Deprecate model-context module (thin re-export wrapper retained)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: update builtin provider model lists and fix registry issues

- OpenRouter: comprehensive model list with top models from Anthropic,
  Google, OpenAI, xAI, DeepSeek, Moonshot, and free Llama/Kimi options
- OpenAI: replace deprecated o3 with o3-pro in curated list
- Groq: add Llama 4 Maverick, update to kimi-k2-instruct-0905,
  add llama-3.1-8b-instant
- Claude, Gemini, xAI, Mistral, Perplexity, DeepSeek: verify all
  curated IDs map to models.dev snapshot
- Registry fixes: add 15s fetch timeout, fix prefix matching boundary
  check, fix cold start localStorage lookup, skip discovered models
  in fallback path

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: add models.dev mappings for Chinese providers and enrich saved models

- Add provider mappings for minimax, moonshot, siliconflow, chatglm (zhipuai),
  qwen (alibaba) to PROVIDER_ID_MAP and build script
- Set modelsDevProviderId on 6 provider definitions (minimax, moonshot,
  siliconflow, chatglm, qwen, qwen-portal) so their models get enriched
- Fix Settings page: locally saved model lists now display enriched metadata
  (capabilities, contextWindow, maxOutput) from registry without requiring reset
- Regenerate snapshot: 16 providers, 504 models (up from 10 providers, ~200 models)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: enrich model capabilities at call time via shared registry

Previously, enriched metadata (capabilities, contextWindow, maxOutput)
only appeared in Settings UI but was lost during actual model calls.
getModelConfig() read raw stored data, so isSupportToolUse() etc.
could return incorrect results.

- Add src/shared/model-registry/enrich.ts with enrichModelFromRegistry()
  that works in the shared layer using build-time snapshot
- Apply enrichment in getModelConfig() before returning the model
- Wire renderer's runtime registry (localStorage/fetch) into the shared
  enrich module via setRuntimeRegistry() for freshest available data

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: use platform blob storage for model registry cache

Replace raw localStorage with platform.getStoreBlob/setStoreBlob for
registry caching. Each platform now uses its optimal storage backend:
- Desktop: file via IPC to main process
- Web/Mobile: IndexedDB via localforage

Remove localStorage access from shared layer (enrich.ts) to avoid
cross-layer browser API dependency.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: wire model registry runtime control plane

* test: harden model registry settings validation

* refactor: deduplicate model registry lookup by reusing shared findModelInRegistry

Resolve merge conflicts by keeping the refactored version that eliminates
duplicate prefix-matching logic in the renderer layer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor provider model control plane

* docs: update provider model control plane technical documentation

Add comprehensive model registry section covering multi-level cache,
enrichment strategy, provider ID mapping, model matching algorithm,
and contract tests. Update precedence table to reflect registry
overwrites for factual metadata.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address PR review findings for model registry

- Fix grok-4-fast context window (256K → 2M) per xAI docs
- Fix magistral-small → magistral-small-latest for valid Mistral API ID
- Add tool_use capability to Groq llama-3.1-8b-instant
- Remove '.' from prefix match separators to prevent gpt-4.1 mismatching gpt-4
- Add fetch timeout (15s) and type validation to snapshot generator script
- Reuse shared transformModelEntry instead of duplicated local copy
- Add curatedModelIds to qwen-portal provider definition
- Add missing maxOutput to openrouter llama-3.3-70b-instruct:free
- Use pnpm exec tsx instead of npx tsx for reproducibility
- Fix moonshot-cn to share moonshotai provider ID (no separate models.dev entry)
- Return defensive copy from getChatboxProviderIds

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: remove duplicate getBuiltinProviderIds export that broke compilation

The re-export from registry conflicted with the local function definition,
causing esbuild to fail and 9 test suites to error out.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: update curated model IDs for OpenAI, OpenAI Responses, and Gemini

- OpenAI: add gpt-5.4 (1.05M context, 128K output), remove superseded
  gpt-5.1/gpt-5/gpt-5-chat-latest/gpt-5-nano, update gpt-5-mini output to 128K
- OpenAI Responses: add gpt-5.4, remove gpt-5.1/gpt-5/gpt-5-pro
- Gemini: remove deprecated gemini-3-pro-preview and gemini-2.0-flash,
  update maxOutput to 65536 for 2.5/3.x models

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Z
Zeng Xian committed
8d82082ea3a385f55751aac4c5612be02b08d011
Parent: 8863c5d