Compare commits

...

684 Commits

Author SHA1 Message Date
Dax Raad f96f94b8cb fix: move models site to opencode domain 2026-07-30 13:56:24 +00:00
Aiden Cline c837f4d34e fix: add OpenCode models domain (#3849)
* fix: add OpenCode models domain

* fix: remove computed custom domain field
2026-07-29 22:51:31 -05:00
Asmae_ELAZRAK 762d7feef9 feat: add kimi K3 to cortecs (#3835)
* feat: add kimi K3 to cortecs

* fix: correct Cortecs Kimi K3 metadata

---------

Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2026-07-29 22:09:54 -05:00
Cas Burggraaf b424381291 Add GreenPT provider (#3726)
* Add GreenPT provider (26 models)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Add GreenPT provider logo

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Use base_model for Mistral Small 3.2 / Medium 3.5 and Green L (review)

Reference existing models/ metadata via base_model instead of
re-declaring provider-agnostic facts inline, per review feedback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Add required description field to full-def models

Upstream schema now requires a non-empty description on models;
base_model entries inherit it, so add it to the self-contained ones.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Refresh GreenPT catalog against production

Reconciles every GreenPT entry with the live production catalog and addresses
the data-accuracy review:

- Context limits: add provider-specific limit.context where GreenPT serves a
  smaller window than the base metadata (gemma-3-27b-it 40k, devstral-2 200k,
  llama-3.3-70b 100k, qwen3-coder-30b 128k).
- Speech-to-text: reprice green-s / green-s-pro to the current EUR 0.12/hour
  pre-recorded rate, with the standard EUR 0.23/hour noted inline.
- Modalities: override attachment and modalities.input so each entry advertises
  exactly what GreenPT serves. Adds image input to gpt-oss-120b, green-r,
  green-r-raw, green-l, green-l-raw and mistral-small-3.2; drops the inherited
  video/audio modalities from qwen3.6-35b-a3b, qwen3.5-397b-a17b and the Kimi
  entries.
- Reasoning controls: reasoning_options now lists the full accepted effort set
  (none, minimal, low, medium, high) on every reasoning model.
- Token costs: refresh prices, including glm-5.2, glm-5.1, minimax-m2.5 and the
  three Kimi entries.

* Rename gemma-4-26b-a4b-it to gemma4

The GreenPT API serves this model under the id `gemma4`; the previous filename
did not resolve against the live endpoint. The upstream weights are still
referenced through base_model.

* Address automated review feedback

- Add the required top-of-file cost-conversion comment (rate 1.14 USD/EUR,
  captured 2026-07-24, with sources) to every EUR-sourced file, per the
  AGENTS.md cost schema rule.
- Scope reasoning_options to the GreenPT-hosted models whose reasoning control
  is documented first-party (gemma4, green-r, green-r-raw). The third-party
  pass-through endpoints forward reasoning_effort upstream unchanged and their
  per-model accepted values are not verified, so they now declare [] rather
  than an assumed effort enum.
- Publish the standard EUR 0.23/hour speech-to-text rate (USD 0.00437/minute)
  instead of the temporary promotional rate, so the catalog stays correct after
  the promotion ends on 2026-08-31. The promotion is documented in the header.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-29 22:02:09 -05:00
Matthew Feroz e6d37bdcae feat(sync): add Merge Gateway model sync (#3249)
* feat(sync): add Merge Gateway model sync

* fix(merge-gateway): document reasoning controls

* fix(sync): preserve partial Merge Gateway metadata

* fix(merge-gateway): align route metadata sync

* fix(merge-gateway): treat supports_reasoning as a positive-only signal

The public /v1/models schema does not document supports_reasoning, and the
live catalog populates it inconsistently across vendor routes: the same
model reports true on one route and false on another (claude-opus-4-6 is
false via anthropic, true via bedrock), and reasoning-only models such as
deepseek-r1 report false on their sole route. Flipping reasoning = false
from that field erased curated reasoning metadata on 42 models.

- only confirm reasoning when an available route reports
  supports_reasoning = true (always accompanied by route reasoning
  metadata), defaulting reasoning_options to [] when none are curated
- preserve curated reasoning metadata when routes report false or omit
  the field
- restore the 42 erased reasoning entries (claude, deepseek-r1, gpt-oss,
  gemma, qwen, glm, nemotron, fugu) from curated values
- re-sync against the live catalog: gemini-embedding-001 added, route
  cache_read prices and display names ingested, qwen3.5-27b limits and
  modalities updated

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(merge-gateway): refresh model catalog

* fix(merge-gateway): align synced model metadata

* docs(sync): trim Merge Gateway notes

* fix(merge-gateway): remove stale Qwen aliases

* test(merge-gateway): document sync coverage

* fix(merge-gateway): mark chat models as non-reasoning

---------

Co-authored-by: Matthew Feroz <matt.feroz@merge.dev>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2026-07-29 21:58:24 -05:00
Kassie Povinelli bebd608155 feat(llmgateway): add reasoning effort levels for kimi-k3 (#3843)
* feat(llmgateway): add reasoning effort levels for kimi-k3

The kimi-k3 entry declared no reasoning options. Verified against the
live gateway that reasoning_effort accepts
minimal|low|medium|high|xhigh|max and returns thinking traces in
message.reasoning, with depth scaling low < medium < high ~= max.
There is no working off switch ('none', reasoning.enabled=false,
thinking.type=disabled, and reasoning.exclude=true all still reason),
so 'none' is omitted and no toggle is declared.

* refactor(llmgateway): move kimi-k3 API mapping note into header comment

Inline comments on TOML entries are dropped by the sync re-serializer;
keep the reasoning_effort/reasoning.effort mapping note in the leading
comment block per repo convention.
2026-07-29 12:58:18 -05:00
github-actions[bot] 6a308dfbf7 chore(sync): update Venice model catalog (#3827)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-29 11:17:35 -05:00
github-actions[bot] 6455db8f76 chore(sync): update Chutes model catalog (#3802)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-29 11:17:25 -05:00
github-actions[bot] ebcf1c5136 chore(sync): update Baseten model catalog (#3821)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-29 11:09:49 -05:00
github-actions[bot] 6f4163d814 chore(sync): update CrossModel model catalog (#3819)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-29 11:09:42 -05:00
github-actions[bot] 05c55247fa chore(sync): update EmpirioLabs AI model catalog (#3803)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-29 11:09:34 -05:00
github-actions[bot] 83b4abd291 chore(sync): update OpenRouter model catalog (#3796)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-29 11:09:13 -05:00
github-actions[bot] 5a66940016 chore(sync): update Deep Infra model catalog (#3825)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-29 11:08:57 -05:00
github-actions[bot] 3516638e90 chore(sync): update Vercel AI Gateway model catalog (#3828)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-29 11:08:47 -05:00
github-actions[bot] 214e4198af chore(sync): update Weights & Biases model catalog (#3829)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-29 11:00:50 -05:00
github-actions[bot] f4ecada627 chore(sync): update LLM Gateway model catalog (#3838)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-29 10:27:48 -05:00
github-actions[bot] fe06f6b0b8 chore(sync): update Charm Hyper model catalog (#3837)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-29 10:27:37 -05:00
huggix bddb089b85 feat(sync): add safe NanoGPT model catalog sync (#3342)
* Add safe NanoGPT model sync provider

* Address NanoGPT canonical model review

* Fix remaining NanoGPT canonical variants

* Harden NanoGPT canonical model sync

* Preserve NanoGPT overrides during factoring
2026-07-29 10:24:57 -05:00
github-actions[bot] 2605c54574 fix: dev CI failure (#3839)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-29 11:24:03 -04:00
Dax Raad f412635d8c Add models.opencode.ai domain 2026-07-29 11:13:33 -04:00
Deven Navani b6a79f21e5 Add Modal as an inference provider (#3760)
* Add Modal as an inference provider

* Use Modal inference gateway
2026-07-28 17:29:14 -05:00
Aiden Cline 814f7e04e0 fix(openrouter): temporarily skip :batch model routes (#3822)
Batch endpoints are not catalog targets; filter them out during sync.
2026-07-28 13:54:24 -05:00
Fenil Modi 3e74f55316 fix(aiand): fix logo.svg not rendering in provider catalog (#3800)
* fix(aiand): rescale logo.svg to 24x24 icon format

The previous logo used a 1280x1280 viewBox with a translate(0 430)
transform, causing it to render blank/broken at small icon sizes in
OpenCode's provider catalog. Rescaled to 24x24 following the convention
used by fireworks-ai, nebius, and other providers.

* fix(aiand): fix logo.svg rendering at icon sizes

Crop viewBox to the actual content bounding box (0 471 1280 430)
and add explicit width/height="24" so the logo renders correctly
at small icon sizes in OpenCode's provider catalog.
Original paths are unchanged.

* fix(aiand): fix logo.svg not rendering in provider catalog

Add width/height="24" and crop viewBox to "0 471 1280 430" —
the exact bounding box of the logo content after translate(0 430).
No path data changed.
2026-07-28 13:42:28 -05:00
github-actions[bot] 185a4f4cc1 chore(sync): update Vercel AI Gateway model catalog (#3807)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-28 12:02:06 -05:00
github-actions[bot] b209b33ce1 chore(sync): update Charm Hyper model catalog (#3801)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-28 12:01:55 -05:00
Fenil Modi 3e72fc6374 fix(aiand): remove glm-5.1 and kimi-k2.6 — not in live catalog (#3806)
* fix(aiand): remove glm-5.1 — not in live catalog (superseded by glm-5.2)

* fix(aiand): remove kimi-k2.6 — not in live catalog (superseded by kimi-k2.7-code and kimi-k3)
2026-07-28 12:01:34 -05:00
Suat-B adfe923c2c Add Xpersona premium model lineup (#3817)
* Add Xpersona premium model lineup

* Fix GPT-5.4 Mini limit inheritance

* Fix GPT-5.4 and GPT-5.5 input limit inheritance

* Align Xpersona serving limits and reasoning metadata

* Restore inherited context field for GPT-5.4 Mini
2026-07-28 11:59:50 -05:00
Christian Landgren 7343d8b35c feat(berget): add Kimi K3 (#3810)
* feat(berget): add Kimi K3

Moonshot AI's 2.8T-parameter open-weights model, served on Berget AI's
Swedish infrastructure (NVIDIA B300, SGLang with DSpark speculative
decoding).

- reasoning_effort none/low/medium/high/max mapped to K3's native
  low/high/max; reasoning returned in message.reasoning_content
- 320k context window, 32k max output
- Multimodal input (text + image)
- Pricing: $3 input / $15 output per 1M tokens, $0.30 cache read

* fix(berget): drop cache_read price, tidy reasoning comment

- Remove cache_read: no separate cache-read price on Berget
- Move reasoning comment to file top and drop xhigh mention
  (Copilot review)

* fix(berget): Kimi K3 reasoning_effort to native low/high/max

K3 only has three native reasoning levels (low/high/max, default max) and
cannot disable thinking. The previous list (none/low/medium/high/max) mixed
in clamped OpenAI-compat values and implied a granularity the model does not
have — and 'none' is misleading since K3 always thinks. The Berget API still
accepts the full OpenAI effort set and clamps it, but only the three distinct
levels are advertised. Matches the 'distinct functional levels' convention
used by our other models.

---------

Co-authored-by: berget-code <noreply@berget.ai>
Co-authored-by: berget <dev@berget.ai>
2026-07-28 11:59:23 -05:00
github-actions[bot] 69a5617db0 chore(sync): update Venice model catalog (#3818)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-28 11:57:33 -05:00
David Knaack 42f0d9ff3f chore(sap-ai-core): add gemini-embedding (version: 001/latest) (#3811) 2026-07-28 11:57:24 -05:00
Billy Cao 52d5045ee7 feat(synthetic): Add Kimi K3 model (#3794)
Deploy / deploy (push) Has been cancelled
* Add Synthetic's Kimi K3 offering

* Update cache read price

* fix(synthetic): declare effort-only reasoning for Kimi K3 per Synthetic API docs

Synthetic's OpenAI-compatible chat completions API documents reasoning_effort
with values low | medium | high and no reasoning on/off toggle, so drop the
toggle option and align effort values with the documented surface (matching
the existing Synthetic Kimi K2.6 / K2.7-Code entries).

https://dev.synthetic.new/docs/openai/chat-completions

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Remove unnecessary comment

* Retrigger transient actions failure

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 23:36:15 -05:00
github-actions[bot] 4faf76317a chore(sync): update Venice model catalog (#3791)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-27 23:36:01 -05:00
github-actions[bot] efb5d8ea0d chore(sync): update Baseten model catalog (#3798)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-27 23:35:53 -05:00
Fenil Modi 0273194a65 feat(aiand): add Kimi K3 (#3799)
* feat(aiand): add Kimi K3

* fix(aiand): remove pdf from kimi-k3 modalities, text+image only

* fix(aiand): restore pdf modality for kimi-k3 based on /v1/models evidence

PDF was removed to match fireworks/ollama-cloud, but that is not valid
evidence for aiand. Sibling aiand entries (kimi-k2.6, kimi-k2.7-code)
keep pdf after catalog/probe evidence. Restoring pdf per original
GET /v1/models data which showed document support.
2026-07-27 23:35:42 -05:00
Abliteration AI a034112075 Add abliterated-model-large (#3793)
* Add abliterated-model-large

* Fix reasoning abliterated-model-large.toml

* fix provider

* Update abliterated-model-large.toml

* removed interleaved reasoning

* fixed docs and effort

* Address review: verified reasoning controls, citations, provider docs

- abliterated-model: reasoning = true with effort ladder and toggle,
  per docs.abliteration.ai/capabilities/thinking
- abliterated-model-large: replace unverified effort values with the
  documented ladder (none..max via reasoning_effort) plus thinking
  toggle; add API-syntax comments; move all source citations into the
  leading header block; align max output with docs (999,990)
- provider.toml: restore reasoning notes with the current verified
  per-endpoint request fields

* Narrow abliterated-model-large effort values to distinct modes

The API maps minimal-high -> high and xhigh-max -> max, so only none,
high, and max are distinct outcomes. Alias mapping kept as a comment.
2026-07-27 23:27:01 -05:00
Oskar b91080aa0e feat(hyper): add Charm Hyper provider and sync module (#3352)
* feat(hyper): add Charm Hyper provider and sync module

* feat: resync models

* fix: remove references to /provider endpoint

* feat: simplify model resolution

* fix logo

* feat: add base model resolution

* update models

* feat: add reasoning_options with base model fallback

* fix: undo env relaxation

* feat: round prices

* fix(hyper): sync modalities from vision

* .

* fix(hyper): remove base model reasoning fallback
2026-07-27 23:23:43 -05:00
Aiden Cline 6fda2e07c2 fix(nvidia): add missing NIM chat models and correct API ids (#3744)
* fix(nvidia): add missing NIM chat models and correct API ids

Add high-demand NVIDIA NIM models used by OpenCode (Nemotron Super/Ultra/Nano,
Inkling, Laguna XS, Mistral Medium 3.5, Ministral 14B, Gemma 3, Cosmos Reason2)
and rename catalog ids that used underscores so they match integrate.api.nvidia.com.

Fixes anomalyco/opencode#38865

* fix(nvidia): audit NIM reasoning_options against infer docs

Keep only verified controls (mistral-medium-3.5-128b reasoning_effort
none|high). Set reasoning_options=[] and drop interleaved where NIM OpenAPI
does not document a control. Narrow inkling modalities to text+image and cite
max_tokens bounds for Super/Laguna output limits.

* fix(nvidia): restore verified Nemotron prompt toggles and Inkling audio

First-party NIM model cards document reasoning ON/OFF via system prompts for
Super v1/v1.5, Ultra 253B, and Nano 8B. NVIDIA's Inkling card lists text/image/audio
inputs. Keep empty reasoning_options only where no control is documented (Laguna,
VL models). Align max_tokens with infer OpenAPI bounds.
2026-07-27 20:45:13 -05:00
github-actions[bot] 24b7a2aa4c chore(sync): update OpenRouter model catalog (#3758)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-27 20:44:47 -05:00
Vladimir Glafirov d1d08289ac feat: add gitlab duo-chat-opus-5 model (#3765) 2026-07-27 20:44:27 -05:00
rakshith1928 9875219078 feat(kimi-k3): add Kimi K3 model configuration with pricing and modalities (#3789) 2026-07-27 20:43:33 -05:00
amrrs ec23529c0c fix(nebius): fix Kimi K3 reasoning_options for Nebius Token Factory (#3792)
* fix(nebius): curate Kimi K3 reasoning_options from verified API behavior

PR #3780 merged Kimi K3 for Nebius with reasoning_options = [] (no
verified control surface). Live testing against
api.tokenfactory.nebius.com/v1/chat/completions shows reasoning_effort
is a real, validated parameter: invalid values 422, and valid values
visibly change reasoning_content length. Curate the accepted literal
list instead of leaving it empty.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(nebius): narrow Kimi K3 reasoning_options to backend-verified values

Live testing invoking each literal (not just triggering the generic
gateway validator) shows the sglang model backend itself rejects
"minimal" and "xhigh" with a 400: "Input should be 'none', 'low',
'medium', 'high' or 'max'". Those two were only accepted by the
gateway's shared schema, not by this model. Narrow the list to the
5 values that actually work end-to-end.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-27 20:43:18 -05:00
KiKaraage 62ef55a446 feat(crof): add Kimi K3 (#3795)
* feat(crof): add Kimi K3

* fix(crof): change reasoning levels to low-high-max

* fix(crof): add "none" reasoning back for Kimi K3
2026-07-27 20:42:40 -05:00
github-actions[bot] 6eaf975918 chore(sync): update Venice model catalog (#3786)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-27 16:06:11 -05:00
rakshith1928 f8ac4b4fb1 feat(ollama-cloud): add kimi k3 model (#3787)
* feat(ollama-cloud): add kimi k3 model

* update ollama reasoning

* Revise Kimi K3 model documentation and sources
2026-07-27 16:06:00 -05:00
github-actions[bot] 03e2178662 chore(sync): update Baseten model catalog (#3770)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-27 14:50:15 -05:00
github-actions[bot] 03e495d946 chore(sync): update Ambient model catalog (#3771)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-27 14:46:40 -05:00
github-actions[bot] 1f5a03df40 chore(sync): update Vercel AI Gateway model catalog (#3772)
* chore(sync): update Vercel AI Gateway model catalog

* fix(vercel): set Kimi K3 Fast reasoning effort options

K3 always reasons; expose verified low/high/max via reasoning_effort.

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2026-07-27 14:46:30 -05:00
github-actions[bot] 0968fea09f chore(sync): update LLM Gateway model catalog (#3779)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-27 14:43:34 -05:00
github-actions[bot] 1fb770040a chore(sync): update Deep Infra model catalog (#3782)
* chore(sync): update Deep Infra model catalog

* fix(deepinfra): set Kimi-K3 reasoning effort options

K3 always reasons; expose verified low/high/max via reasoning_effort.

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2026-07-27 14:43:20 -05:00
Kevin 1efc768ae5 Add Kimi K3 to Nebius Token Factory (#3780)
Register moonshotai/Kimi-K3 with Nebius pricing and limits from
https://tokenfactory.nebius.com/api/public/models_info.
2026-07-27 14:42:37 -05:00
github-actions[bot] c3aab14477 chore(sync): update Hugging Face model catalog (#3784)
* chore(sync): update Hugging Face model catalog

* fix(huggingface): set Kimi-K3 reasoning effort options

K3 always reasons; expose verified low/high/max via reasoning_effort.

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2026-07-27 14:42:20 -05:00
Zain Hasan 236d2dd99a add kimi k3 (#3783) 2026-07-27 14:37:56 -05:00
github-actions[bot] ad211c8f8f chore(sync): update Venice model catalog (#3781)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-27 14:37:42 -05:00
Jack 38ccccc20d add kimi k3 to Zen 2026-07-28 01:08:00 +08:00
github-actions[bot] cce20188e5 chore(sync): update Venice model catalog (#3775)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-27 11:33:49 -05:00
Ahmad Shahzad 2acddd4818 feat(fireworks-ai): add Kimi K3 and Kimi K3 Fast (#3777) 2026-07-27 11:33:33 -05:00
Ahmad Shahzad c67dbc2e02 fix(fireworks-ai): remove deprecated GLM 5.1 and GLM 5.1 Fast (#3730)
Deploy / deploy (push) Has been cancelled
Fireworks AI will decommission GLM 5.1 and GLM 5.1 Fast serverless
endpoints on 2026-07-26, with GLM 5.2 and GLM 5.2 Fast serving as
their recommended replacements:

  GLM 5.1      -> GLM 5.2      (accounts/fireworks/models/glm-5p2)
  GLM 5.1 Fast -> GLM 5.2 Fast (accounts/fireworks/routers/glm-5p2-fast)

Remove the two model files ahead of the decommission date. Dedicated
deployments are unaffected.
2026-07-26 22:48:41 -05:00
github-actions[bot] 790e5cb842 chore(sync): update Ambient model catalog (#3747)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-26 22:48:00 -05:00
github-actions[bot] 73160c42bd chore(sync): update OpenRouter model catalog (#3748)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-26 22:47:50 -05:00
Carlo Francisco ff9bc91921 fix(thinkingmachines): name 256K variant "Inkling (256K)" (#3755)
Both Tinker Inkling tiers rendered with the same display name "Inkling"
because the :peft:262144 variant inherits it via base_model. Downstream
consumers (e.g. opencode) show two indistinguishable entries despite
different context windows and pricing. Override the name to match
the "Inkling (256K)" label used on Tinker's pricing page.
2026-07-26 22:47:35 -05:00
Nathan Nguyen 9c249c78cb feat(cloudflare-ai-gateway): add Claude Opus 5 (#3736) 2026-07-26 15:33:34 -05:00
github-actions[bot] c40d2ae925 chore(sync): update OpenRouter model catalog (#3733)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-25 22:57:04 -05:00
github-actions[bot] 71b3ca345d chore(sync): update Vercel AI Gateway model catalog (#3732)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-25 22:56:55 -05:00
github-actions[bot] 0b0414d78e chore(sync): update Weights & Biases model catalog (#3731)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-25 22:56:49 -05:00
github-actions[bot] f5edd52931 chore(sync): update Ambient model catalog (#3745)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-25 22:34:31 -05:00
opencode-agent[bot] d53651e3d9 fix(reviewer): compare reasoning options by API surface (#3746)
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2026-07-25 22:34:20 -05:00
Aiden Cline 2e25bad01c chore(azure): remove retired models, mark deprecated still-serving (#3729)
* chore(azure): remove retired models, mark deprecated still-serving

Delete Foundry models past retirement (chat snapshots, Phi-3, old GPT-4,
retired Meta/Cohere/DeepSeek/Mistral/xAI/Moonshot entries). Clean broken
azure-cognitive-services symlinks that pointed at deleted azure models.

Mark still-serving Deprecated/Legacy models with status = "deprecated"
(gpt-4.1*, gpt-4o*, o1/o3-mini/o4-mini, codex-mini, gpt-image-1,
deepseek-r1, claude-opus-4-1).

Sources:
- https://learn.microsoft.com/en-us/azure/foundry/openai/concepts/model-retirement-schedule
- https://learn.microsoft.com/en-us/azure/foundry/openai/concepts/retired-models

* fix(azure): address review — Preview status + Nov-2025 cohort

- Remove status=deprecated from gpt-image-1 and claude-opus-4-1
  (official lifecycle is Preview, not Deprecated)
- Delete remaining Nov-2025 OpenAI cohort for consistency with o1-mini:
  gpt-3.5-turbo-0125/1106/instruct, gpt-4-turbo, gpt-4-turbo-vision
- Drop broken azure-cognitive-services symlinks

* fix(azure): restore Nov-2025 OpenAI cohort as deprecated

Azure schedule/retired-models pages do not list gpt-4-turbo or
gpt-3.5-turbo-0125/1106/instruct as Retired. OpenAI still serves the
turbo family (catalog marks deprecated). Restore these IDs with
status=deprecated instead of deleting, matching OpenAI catalog policy.

Keep o1-mini deleted (long shut down on OpenAI API).
2026-07-25 15:04:01 -05:00
github-actions[bot] fcf16dcf64 chore(sync): update Ambient model catalog (#3727)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-25 13:52:39 -05:00
github-actions[bot] 8a61715de2 chore(sync): update CrossModel model catalog (#3743)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-25 13:14:58 -05:00
github-actions[bot] 5d913d45eb chore(sync): update OpenRouter model catalog (#3723)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-24 20:26:19 -05:00
github-actions[bot] b975c94c43 chore(sync): update LLM Gateway model catalog (#3724)
Deploy / deploy (push) Has been cancelled
* chore(sync): update LLM Gateway model catalog

* fix(llmgateway): set opus-5 reasoning_options to match anthropic effort

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2026-07-24 14:22:20 -05:00
github-actions[bot] daafb34595 chore(sync): update Vercel AI Gateway model catalog (#3722)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-24 14:19:36 -05:00
m3 dac8dfdf3c feat(github-copilot): add Claude Opus 5 (#3720) 2026-07-24 14:19:25 -05:00
github-actions[bot] efa65bbef6 chore(sync): update Anthropic model catalog (#3725)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-24 14:19:15 -05:00
Aiden Cline f8ab14d0d5 chore(vertex): remove shut-down Claude 3.5 Haiku, deprecate open MaaS (#3721)
Delete claude-3-5-haiku@20241022 from google-vertex and
google-vertex-anthropic — partner model shut down 2026-07-05.

Mark open MaaS models deprecated (notice 2026-07-21, retire 2026-10-21)
that we still list and that remain serving until retirement.

Sources:
- https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/deprecations/partner-models
- https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/deprecations/open-models
2026-07-24 14:17:42 -05:00
Aiden Cline 2284981d9d fix(anthropic): factor base_model fields and preserve fast mode (#3718)
Models API has no fast-mode surface; keep authored experimental/provider.
Use factorBaseModel so attachment/reasoning/limit/modalities are not
rewritten when they already match models/ metadata.
2026-07-24 13:34:17 -05:00
github-actions[bot] 0f697e2027 chore(sync): update Weights & Biases model catalog (#3711)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-24 13:22:58 -05:00
github-actions[bot] b42b2c5a43 chore(sync): update EmpirioLabs AI model catalog (#3709)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-24 13:22:47 -05:00
github-actions[bot] ee6c6dcf5f chore(sync): update Venice model catalog (#3712)
* chore(sync): update Venice model catalog

* fix(venice): factor claude-opus-5-fast onto base opus-5

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2026-07-24 13:22:37 -05:00
Frank 13f35a9f26 Merge branch 'dev' of github.com:anomalyco/models.dev into dev 2026-07-24 14:22:28 -04:00
github-actions[bot] 565cdf4e15 chore(sync): update Chutes model catalog (#3715)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-24 13:22:26 -05:00
github-actions[bot] 4dfe1920d5 chore(sync): update CrossModel model catalog (#3716)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-24 13:22:16 -05:00
Frank e3ae24cdd7 update zen models 2026-07-24 14:22:12 -04:00
Aiden Cline 617bba5ee3 fix(sync): factor Claude Opus fast variants onto base_model (#3717)
OpenRouter preserves fast variant names when stripping -fast to resolve
canonical metadata. Venice resolves -fast IDs/names to base model
metadata without hardcoding each alias. Fix openrouter opus-5-fast TOML.
2026-07-24 13:22:06 -05:00
github-actions[bot] 32ce0b9947 chore(sync): update OpenRouter model catalog (#3710)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-24 13:14:47 -05:00
github-actions[bot] 44f2b60192 chore(sync): update Vercel AI Gateway model catalog (#3713)
* chore(sync): update Vercel AI Gateway model catalog

* fix(vercel): factor opus-5-fast onto base opus and match fable reasoning_options

Strip -fast when resolving canonical base models so Claude Opus fast
variants inherit models/ metadata. Set vercel opus-5 reasoning_options to
match fable (toggle + effort low/medium/high/xhigh).

* fix(vercel): match anthropic opus-5 effort-only reasoning_options

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2026-07-24 13:14:31 -05:00
Aiden Cline 91b5ee80f2 chore(bedrock): mark Claude Opus 4.1 as deprecated (#3708)
Bedrock moved Claude Opus 4.1 to Legacy on 2026-07-08 (EOL 2027-01-08).
Still serves traffic — mark status = "deprecated" on base and US variants.

Source: https://docs.aws.amazon.com/bedrock/latest/userguide/model-lifecycle.html
2026-07-24 13:06:16 -05:00
Aiden Cline 7be7cc0d3f fix(openai): remove shut-down models, mark upcoming deprecations (#3707)
OpenAI shut down several API models on 2026-07-23 (including
gpt-5.1-codex-mini from anomalyco/opencode#38665). Delete those from
providers/openai since they no longer serve traffic.

Mark models still available but scheduled for 2026-10-23 shutdown as
status = "deprecated".

Source: https://developers.openai.com/api/docs/deprecations
2026-07-24 12:36:19 -05:00
Aiden Cline 342b5572a0 feat: add Claude Opus 5 (#3706)
* feat: add Claude Opus 5 across Anthropic and cloud providers

Add Claude Opus 5 (claude-opus-5) released 2026-07-24: base metadata,
Anthropic API with effort + fast mode, Amazon Bedrock (global/US/EU/AU/JP),
Google Vertex, Azure Foundry, OpenCode, and GitHub Copilot.

* fix: drop Claude Opus 5 from opencode provider

Not confirmed supported on OpenCode yet.

* fix: drop Claude Opus 5 from github-copilot

Not listed in GitHub Copilot supported models yet.
2026-07-24 12:20:57 -05:00
github-actions[bot] 6ad4f0a5cd chore(sync): update OpenRouter model catalog (#3703)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-24 12:15:21 -05:00
github-actions[bot] ccc8c233a0 chore(sync): update Baseten model catalog (#3704)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-24 12:15:12 -05:00
Oliver Mee 8b351ba0bd fix(models): correct attachment on 3 multimodal models + qwen3.7-plus video input (#3705)
These three model files set attachment = false while their own description and
modalities.input both say the model is multimodal, so the flag contradicts the
record it sits next to:

- alibaba/qwen3.7-plus  - description: "Multimodal Qwen workhorse for long-context
  agents, visual inputs, and coding"; input = ["text", "image"]; attachment = false.
- alibaba/qwen3.6-plus  - description: "Earlier Qwen multimodal workhorse...";
  input = ["text", "image", "video"]; attachment = false.
- moonshotai/kimi-k2.5  - description: "...coding, and multimodal work";
  input = ["text", "image", "video"]; attachment = false.

Sibling models that are already correct (qwen3.8-max-preview, qwen3.6-flash,
kimi-k2.6, kimi-k2.7-code) all pair image/video input with attachment = true.
This change makes these three consistent with that convention and with their own
declared modalities.

qwen3.7-plus also gains "video" input. Its siblings qwen3.6-plus and qwen3.6-flash
already list video, its description says "visual inputs", and I verified it live:
against the Alibaba/Qwen Cloud Token Plan gateway (Singapore, 2026-07-24)
qwen3.7-plus accepted a real image and a 10-second video and described both
correctly, on the same endpoint where the text-only sibling qwen3.7-max returns
"Unexpected item type in content".

bun validate passes; git diff --check clean. Only attachment (x3) and one
modalities.input line changed.
2026-07-24 12:14:33 -05:00
github-actions[bot] 712d41fa7c chore(sync): update Ambient model catalog (#3351)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-24 10:11:41 -05:00
github-actions[bot] ce4d097c49 chore(sync): update EmpirioLabs AI model catalog (#3359)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-24 10:11:27 -05:00
PedroACosta 0b14c410cf feat(dinference): add GLM-5.2 model (#3378) 2026-07-24 10:11:13 -05:00
github-actions[bot] 7dc6b8def4 chore(sync): update Google model catalog (#3687)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-24 10:10:42 -05:00
github-actions[bot] dd79e60e32 chore(sync): update OpenRouter model catalog (#3684)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-24 10:10:14 -05:00
github-actions[bot] 04ca479ae4 chore(sync): update Vercel AI Gateway model catalog (#3685)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-24 10:10:02 -05:00
Alex a822bef6cd Add Baseten provider entry for GLM 5.2 Fast (#3688)
Document zai-org/GLM-5.2-Fast pricing and limits alongside the existing GLM 5.2 entry.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 10:09:43 -05:00
github-actions[bot] 1b69a9c4ca chore(sync): update xAI model catalog (#3692)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-24 10:09:27 -05:00
github-actions[bot] 7d63db3d45 chore(sync): update Venice model catalog (#3689)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-24 10:09:15 -05:00
Oliver Mee cdf538ad29 fix(alibaba-token-plan): correct model capabilities and limits against the live gateway, add HappyHorse video (#3695)
* fix(alibaba-token-plan): correct capabilities and limits against the live gateway

Probed the Token Plan gateway directly (2026-07-24); several values were wrong
in both region providers:

- kimi-k2.5/k2.6: drop base_model_omit=["structured_output"] — the gateway
  accepts response_format json_schema on both.
- kimi-k2.6: remove the [limit] output=16_384 override (inherits base 262_144).
  A max_tokens=17,000 request truncated at exactly 17,000 (finish_reason=length)
  and a real run emitted 33,718 tokens (finish_reason=stop), disproving the
  console/price-sheet "16K". max_tokens accepts up to 262,144, rejects 262,145.
- kimi-k2.5: [limit] output 32_768 -> 98_304 (its enforced max_tokens ceiling).
- qwen3.8-max-preview, qwen3.7-max, qwen3.7-plus, qwen3.6-plus, glm-5: add
  structured_output=true (json_schema works though base/console report none;
  qwen3.6-plus gained json_schema since the 2026-07-17 probe, matching flash).
- qwen3.7-max/plus, qwen3.6-plus/flash: add [interleaved] reasoning_content.
- deepseek-v4-pro/flash: add cache_write=0.

Citations are in each file's leading comment block.

* feat(alibaba-token-plan): add HappyHorse 1.1 video models (both regions)

happyhorse-1.1-{t2v,i2v,r2v} are Token Plan supported models served on the async
video-synthesis endpoint (POST .../api/v1/services/aigc/video-generation/
video-synthesis, X-DashScope-Async), not the OpenAI-compatible /models list.
Entitlement confirmed live 2026-07-24 on both tiers (Personal and Team keys each
accepted a t2v job: task_id + PENDING->RUNNING). Credit-billed, so cost is 0.

* fix(alibaba-token-plan): attachment=true on image-input HappyHorse models

The reviewer bot correctly flagged happyhorse-1.1-i2v and -r2v: they take an
image as input, so attachment should be true, not false. Consumers that gate
image upload on attachment would otherwise treat them as text-only. t2v stays
false (text input only).

* fix(alibaba-token-plan): happyhorse i2v takes image + text prompt

The Alibaba image-to-video API takes an image (anchors the first frame) plus a
text prompt (drives the motion), so input is ["image", "text"], not ["image"]
alone. This matches sibling r2v. Confirmed against the HappyHorse i2v API docs.

* fix(alibaba-token-plan): correct four more capabilities/limits vs live gateway

Re-probing the full chat catalogue on 2026-07-24 surfaced four values the
providers still got wrong. All verified by probing the live gateway directly.

- kimi-k2.7-code: drop base_model_omit = ["structured_output"]. The gateway now
  honours a strict response_format json_schema (a strict-schema request returned
  exactly {"name":"Alice","age":30} with finish_reason=stop, with and without the
  "json" keyword), so inheriting the base model's structured_output = true is
  correct. This capability was absent at the earlier probe and has since appeared.
- qwen3.7-max: add [limit] output = 131_072. The gateway accepts max_tokens up to
  131,072 and rejects 131,073 - double the inherited 65,536 and double its sibling
  qwen3.7-plus, so the inherited value under-reports by half.
- qwen3.7-plus: add [limit] output = 65_536. The gateway accepts max_tokens up to
  65,536 and rejects 65,537; the inherited model-metadata value is 64,000.
- MiniMax-M2.5: [limit] output 24_576 -> 32_768, its enforced max_tokens ceiling
  (accepts 32,768, rejects 32,769). structured_output stays absent: a json_schema
  request came back wrapped in markdown fences, i.e. free-form, not enforced.

Both region providers updated identically. Sources cited in each file header.

* fix(alibaba-token-plan): qwen3.6 thinking_budget max 81_920 -> 131_072

The gateway enforces a thinking_budget ceiling of 131,072 on qwen3.6-plus and
qwen3.6-flash (probed 2026-07-24: max_tokens/thinking_budget accepts 131,072 and
rejects 131,073). Alibaba's docs state 81,920, but the live gateway accepts up to
131,072, so the documented figure under-reports the real limit. Both region
providers updated; the leading comment records the doc-vs-gateway difference.
2026-07-24 10:08:51 -05:00
github-actions[bot] 317bf46e4c chore(sync): update Chutes model catalog (#3700)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-24 10:08:13 -05:00
Derzsi Dániel 4c4cb5c8c7 feat: add Hetzner provider (#3701)
* feat: add Hetzner provider

* fix: Hetzner provider cannot disable reasoning, can only use text/image for Qwen3.6 input
2026-07-24 10:07:56 -05:00
Jetha Chan 2e815adfbb Add ai& provider (#3327)
* Add ai& provider

ai& (https://aiand.com) serves open-weight LLMs through an OpenAI-compatible
API at https://api.aiand.com/v1, authenticated with a standard Bearer
AIAND_API_KEY. Adds the provider plus 9 models verified against ai&'s live
catalog page (https://docs.aiand.com/models/catalog/): openai/gpt-oss-120b,
qwen/qwen3.6-27b, deepseek-ai/deepseek-v4-flash, deepseek-ai/deepseek-v4-pro,
google/gemma-4-31b-it, moonshotai/kimi-k2.6, moonshotai/kimi-k2.7-code,
zai-org/glm-5.1, and zai-org/glm-5.2. Each entry reuses existing shared model
metadata via base_model and overrides only cost (and, where confirmed,
modalities) with figures read from the live catalog table and JSON examples.
reasoning_options on every model mirrors the reasoning_effort values ai&'s
own Chat Completions docs list (none/minimal/low/medium/high/xhigh).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Verify ai& models against live API and docs; fix modalities and context

- gemma-4-31b-it: image, video, and PDF input all verified by direct
  probe (PDF via Files API purpose=document, referenced by file_id;
  ai& rasterizes PDFs to per-page images server-side). Add pdf modality.
- kimi-k2.7-code: video input rejected by the API; image and PDF
  verified. Override modalities to text+image+pdf.
- kimi-k2.6: catalog lists vision+document without video; same override
  (org-scoped access prevented a runtime probe).
- qwen3.6-27b: image input rejected by the API; override modalities to
  text-only.
- deepseek-v4-flash/-pro, glm-5.2: GET /v1/models reports
  context_window 1048576; override the base models' rounded 1_000_000.

Prices remain the catalog's public USD list prices. Per-org /v1/models
pricing is denominated in the org's billing currency, and cached-input
rates have no public USD listing, so cache_read stays omitted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Address review action items: logo, attachment, reasoning_options, glm-5.1

- Add providers/aiand/logo.svg: official ai& wordmark converted to
  currentColor with no fixed size, centered in a square viewBox.
- qwen3.6-27b: set attachment = false to match the text-only modalities.
- reasoning_options verified per model by live probe (all six documented
  values plus an invalid negative control against each accessible model):
  - gpt-oss-120b narrowed to low/medium/high; the backend 400s "none",
    "minimal", and "xhigh" ("Supported values are: high, medium, low").
  - deepseek-v4-flash/-pro, gemma-4-31b-it, kimi-k2.7-code, qwen3.6-27b,
    glm-5.2 accept all six; invalid values 400. Spot-checked meaningful:
    effort "none" emits no reasoning content, "high" does.
  - kimi-k2.6 and glm-5.1 are org-scoped and not probeable with our key;
    reasoning_options set to [] rather than assumed, per review guidance.
- glm-5.1: documented why context stays inherited (catalog rounds to
  "203K"; exact context_window only visible to orgs with model access).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 10:07:06 -05:00
Jack 7894073d7d Merge pull request #3698 from 7Sageer/feat/kimi-for-coding-k3-256k
feat(kimi-for-coding): add k3-256k model
2026-07-24 19:59:28 +08:00
7Sageer b5d64935a1 feat(kimi-for-coding): add k3-256k model 2026-07-24 19:43:47 +08:00
Jack d2f42e9fb6 add reasoning effort to ling-3.0-flash-free on opencode zen & openrouter 2026-07-24 16:00:17 +08:00
github-actions[bot] 4ed6341d04 fix: [missing-model] xai: grok-imagine-video-1.5 (#3653)
* fix: [missing-model] xai: grok-imagine-video-1.5

* fix: inherit Grok Imagine Video metadata

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2026-07-23 21:58:12 -05:00
Jack 1111c28f60 add ling-3.0-flash-free to opencode go 2026-07-24 10:13:46 +08:00
github-actions[bot] 98657bdc55 fix: [missing-model] google: lyria-3-clip-preview (#3680)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-23 18:30:52 -05:00
github-actions[bot] ebcf28f7be fix: [missing-model] google: veo-3.1-fast-generate-preview (#3679)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-23 18:30:49 -05:00
github-actions[bot] 2bcedfddcb fix: [missing-model] google: lyria-3-pro-preview (#3678)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-23 18:30:45 -05:00
github-actions[bot] 63f35780d3 fix: [missing-model] google: gemini-3.1-flash-live-preview (#3677)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-23 18:30:41 -05:00
github-actions[bot] c83101b6b0 fix: [missing-model] google: gemini-2.5-computer-use-preview-10-2025 (#3673)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-23 18:30:38 -05:00
github-actions[bot] d84194b62d fix: [missing-model] google: gemini-3.1-flash-lite-image (#3671)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-23 18:30:34 -05:00
github-actions[bot] eed1ca26ab fix: [missing-model] google: veo-3.1-lite-generate-preview (#3669)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-23 18:30:30 -05:00
github-actions[bot] 5fd1300905 fix: [missing-model] google: deep-research-max-preview-04-2026 (#3667)
* fix: [missing-model] google: deep-research-max-preview-04-2026

* fix: inherit Deep Research Max metadata

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2026-07-23 18:30:27 -05:00
github-actions[bot] 3263d558f3 fix: [missing-model] google: gemini-3.5-live-translate-preview (#3664)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-23 18:30:23 -05:00
github-actions[bot] f133b51d55 fix: [missing-model] google: veo-3.1-generate-preview (#3662)
* fix: [missing-model] google: veo-3.1-generate-preview

* fix: inherit Veo metadata

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2026-07-23 18:30:20 -05:00
github-actions[bot] c744edfc3c fix: [missing-model] google: deep-research-preview-04-2026 (#3661)
* fix: [missing-model] google: deep-research-preview-04-2026

* fix: inherit Deep Research metadata

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2026-07-23 18:30:16 -05:00
github-actions[bot] e4f8447930 fix: [missing-model] google: gemini-embedding-2 (#3660)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-23 18:30:12 -05:00
github-actions[bot] 22e4bf2620 fix: [missing-model] google: gemini-robotics-er-1.6-preview (#3659)
* fix: [missing-model] google: gemini-robotics-er-1.6-preview

* fix: declare Robotics reasoning toggle

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2026-07-23 18:30:08 -05:00
github-actions[bot] 4c2589610b fix: [missing-model] google: gemini-3-pro-image (#3658)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-23 18:30:04 -05:00
github-actions[bot] 39f13cbe92 fix: [missing-model] google: gemini-3.1-flash-tts-preview (#3655)
* fix: [missing-model] google: gemini-3.1-flash-tts-preview

* fix: inherit Gemini TTS metadata

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2026-07-23 18:30:01 -05:00
github-actions[bot] cbecae3f83 fix: [missing-model] google: gemini-3.1-flash-image (#3654)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-23 18:29:57 -05:00
Aiden Cline 573c757bd2 fix(sync): disable Google missing-model tracking (#3686) 2026-07-23 18:24:31 -05:00
Aiden Cline 8735bc603b fix(sync): dispatch missing models to issue fixer (#3652) 2026-07-23 17:05:29 -05:00
github-actions[bot] 6b1c5b0814 chore(sync): update OpenRouter model catalog (#3430)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-23 16:54:01 -05:00
Aiden Cline f5ce9c666f fix(sync): stop unreliable missing-model issue spam (#3651) 2026-07-23 16:46:15 -05:00
Aiden Cline d3498a124c Merge pull request #3490 from rorynolan/fix-fireworks-minimax-m3-modalities
fix(fireworks-ai): mark MiniMax-M3 as multimodal (text, image, video)
2026-07-23 16:01:58 -05:00
Rory Nolan 06af063255 fix(fireworks-ai): mark MiniMax-M3 as multimodal (text, image, video)
Fireworks and MiniMax both document MiniMax-M3 as natively multimodal, and
every other provider entry for this model lists image (and usually video)
input. The fireworks-ai entry lists input = ["text"] only, so downstream
clients (e.g. opencode) refuse image input for this model ("Image read not
supported by this model") even though the Fireworks API accepts and correctly
interprets images. Align modalities.input with the model's actual capability.
2026-07-23 13:13:34 -07:00
Aiden Cline 9e9d1e7208 Merge pull request #3406 from anomalyco/automation/sync-models-chutes
chore(sync): update Chutes model catalog
2026-07-23 14:53:37 -05:00
github-actions[bot] 824e1f14d1 chore(sync): update Chutes model catalog 2026-07-23 19:46:54 +00:00
Aiden Cline 31ac5f5ef1 Merge pull request #3387 from anomalyco/automation/sync-models-crossmodel
chore(sync): update CrossModel model catalog
2026-07-23 14:24:36 -05:00
Aiden Cline 5c92290660 fix(crossmodel): add hy3 reasoning_options effort none|low|high
Match hy3-preview and upstream Hy3 reasoning_effort (no_think→none, low, high).
2026-07-23 14:23:25 -05:00
Aiden Cline 39f788d5e5 Merge pull request #3407 from anomalyco/automation/sync-models-baseten
chore(sync): update Baseten model catalog
2026-07-23 14:20:46 -05:00
Aiden Cline 5262d3c98f Merge pull request #3408 from anomalyco/automation/sync-models-venice
chore(sync): update Venice model catalog
2026-07-23 14:20:35 -05:00
Aiden Cline 273ab770f5 Merge pull request #3409 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-23 14:20:26 -05:00
Aiden Cline 9053be3218 Merge pull request #3389 from anomalyco/feat/sync-open-issues-for-missing
feat(sync): open deduped GitHub issues for missing models
2026-07-23 14:20:10 -05:00
github-actions[bot] 2f06d99dcc chore(sync): update OpenRouter model catalog 2026-07-23 18:42:13 +00:00
github-actions[bot] 97851e4021 chore(sync): update CrossModel model catalog 2026-07-23 18:42:10 +00:00
github-actions[bot] 09c5d27354 chore(sync): update Venice model catalog 2026-07-23 18:42:10 +00:00
github-actions[bot] 78acd348c7 chore(sync): update Baseten model catalog 2026-07-23 18:42:09 +00:00
Aiden Cline 28d474d5b2 fix(sync): guarantee xAI alias marker is internal; annotate issue-open failures
- Strip API-provided canonical_id from top-level xAI rows in parseModels
  so sourceID's silent-skip marker can only be set by the synthetic alias
  expansion; an API row carrying canonical_id would otherwise suppress a
  genuinely missing model with no signal
- Emit a ::error:: workflow annotation when opening missing-model issues
  fails in Actions, so broken tokens or a full dedupe window are visible
  on green no-change runs
2026-07-23 13:07:53 -05:00
Aiden Cline 8b50f98de3 fix(sync): harden missing-model issue dedupe and label failures
- Fail closed with a clear error when gh label create fails, instead of
  surfacing one opaque issue-create error per model
- Raise the dedupe list window to 1000 and refuse to create issues when
  the window is full, since older closed titles could be truncated and
  create duplicates
- Document the accepted one-time first-run issue volume for skipCreates
  providers in sync.md
2026-07-23 12:36:36 -05:00
Aiden Cline 759ea015b2 fix(sync): do not open missing-model issues for xAI alias IDs
Alias rows expanded in parseModels exist only to update already-cataloged
alias TOMLs. Their canonical row carries the missing-model signal, so
sourceID now returns undefined for alias rows and the sync runner skips
undefined source IDs, preventing false-positive [missing-model] issues
like 'xai: <model>-latest' for models cataloged under canonical IDs.
2026-07-23 12:17:15 -05:00
Aiden Cline 5c3c6c76ff Merge pull request #3391 from anomalyco/automation/sync-models-llmgateway
chore(sync): update LLM Gateway model catalog
2026-07-23 11:33:43 -05:00
Aiden Cline 6301a767ef fix(llmgateway): document toggle/effort API syntax in comments
Add exact request-field syntax next to reasoning_options so callers
know how to disable or set effort via the gateway.
2026-07-23 11:30:10 -05:00
Aiden Cline 0360a1d239 fix(llmgateway): correct reasoning_options on synced models
Audit PR #3391 model reasoning controls against LLM Gateway docs and
/v1/models providers[].reasoning_efforts.
2026-07-23 11:25:38 -05:00
Aiden Cline 44c89b7256 Merge pull request #3402 from tonimelisma/agent/fix-thinking-machines-inkling
Deploy / deploy (push) Has been cancelled
fix(thinkingmachines): correct Inkling endpoint, IDs, and variants
2026-07-23 11:17:56 -05:00
Aiden Cline 168230d28a Merge pull request #3393 from anomalyco/automation/sync-models-vercel
chore(sync): update Vercel AI Gateway model catalog
2026-07-23 11:17:38 -05:00
Aiden Cline 06e16ed3db Merge pull request #3396 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-23 11:14:30 -05:00
github-actions[bot] d69212b0c1 chore(sync): update Vercel AI Gateway model catalog 2026-07-23 15:55:27 +00:00
github-actions[bot] e8f9c6f2ea chore(sync): update OpenRouter model catalog 2026-07-23 15:55:25 +00:00
github-actions[bot] d2c944568a chore(sync): update LLM Gateway model catalog 2026-07-23 15:55:24 +00:00
Toni Melisma 023a01a015 fix Thinking Machines Inkling metadata 2026-07-22 22:46:31 -07:00
Aiden Cline cd925adab8 refactor(sync): simplify missing-model issues and fix ops hazards
- Shrink helper to title-based dedupe (open+closed); drop marker parser
- Opt-in openIssues (=== true); enable only under GITHUB_ACTIONS by default
- Issue-fixer skips [missing-model] titles (hand-authored metadata only)
- Docs match the leaner behavior
2026-07-22 23:19:59 -05:00
Aiden Cline 4a14b64ce3 Merge pull request #3254 from celeste1900/add-ofox-13models
feat(ofox): add Ofox provider (13 top-tier models)
2026-07-22 22:36:15 -05:00
Aiden Cline e8e0057b12 test(sync): drop missing-model issue unit tests
gh-backed issue opens are operational glue; keep the suite focused on catalog sync.
2026-07-22 22:24:33 -05:00
celeste1900 6f3ae40ade fix(ofox): declare reasoning_options — provider forwards native reasoning params across all three protocols 2026-07-23 10:56:28 +08:00
Aiden Cline 3e4aae9ab7 fix(sync): harden missing-model GitHub issue opens
- Parse marker null-safely; only accept double-quoted JSON attrs
- Dedupe via labeled issue list + in-memory match (fail closed on list errors)
- Per-model create errors keep notices; ensureLabel checks exit code
- Open issues by default only in CI; require --open-issues locally
- Pass GH_TOKEN to the sync workflow step so hourly runs can create issues
2026-07-22 20:54:32 -05:00
Aiden Cline 76c38ce9c4 Merge pull request #3397 from skaldebane/poolside-logo
feat(poolside): add poolside lab description and logo
2026-07-22 20:52:17 -05:00
Aiden Cline 46343b601a Merge pull request #3399 from anomalyco/issue-3398
fix: cline-pass/kimi-k3 is missing from the ClinePass provider page
2026-07-22 20:52:05 -05:00
Aiden Cline 0ff5e36ef7 refactor(sync): drop openIssuesForMissing; skipCreates opens issues
skipCreates already means we won't auto-create TOMLs, so missing remote
models should always open deduped GitHub issues. One flag is enough.
2026-07-22 20:23:06 -05:00
github-actions[bot] 8d4fe2543e fix: cline-pass/kimi-k3 is missing from the ClinePass provider page 2026-07-22 23:41:34 +00:00
Houssam Elbadissi 0e4381d2a9 feat(poolside): add poolside lab description and logo 2026-07-22 23:19:05 +01:00
Aiden Cline 40efa93574 Merge pull request #3392 from anomalyco/automation/sync-models-venice
chore(sync): update Venice model catalog
2026-07-22 15:36:29 -05:00
Aiden Cline 8b8c8b3d09 Merge pull request #3394 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-22 15:36:19 -05:00
Aiden Cline c945a5f2cc Merge pull request #3395 from skaldebane/poolside-update
feat(poolside): add laguna-s-2.1, remove laguna-xs.2
2026-07-22 15:36:08 -05:00
github-actions[bot] 05536f4034 chore(sync): update OpenRouter model catalog 2026-07-22 19:46:28 +00:00
github-actions[bot] 6d6bd2c0b8 chore(sync): update Venice model catalog 2026-07-22 19:46:25 +00:00
Houssam Elbadissi 4a2080e2bc fix(poolside): add reasoning toggle to poolside provider models 2026-07-22 20:10:35 +01:00
Houssam Elbadissi 0a71b251c4 feat(poolside): add laguna-s-2.1, remove laguna-xs.2 2026-07-22 19:51:54 +01:00
Aiden Cline 5b2e20cdea feat(sync): open deduped GitHub issues for missing models
Add openIssuesForMissing for providers that cannot auto-create TOMLs.
Each skipped remote model ID opens one labeled issue with a stable
title/marker so reruns do not duplicate, and the issue fixer can PR adds.
2026-07-22 13:25:15 -05:00
Aiden Cline f63b5ce78d Merge pull request #3386 from davidcharbonnier/dev
feat(google-vertex): add gemini 3.6 flash and 3.5 flash lite models
2026-07-22 12:55:20 -05:00
Aiden Cline 2346146631 fix(google-vertex): align Gemini 3.6/3.5 Flash Lite costs with pricing
Drop incorrect cost.reasoning and cache_write fields. Thinking tokens are
billed as output; Vertex lists no per-token cache write for these models.
Match sibling google/vertex configs and add pricing/docs citations.
2026-07-22 12:53:41 -05:00
David Charbonnier 93316c1f9a feat(google-vertex): add gemini 3.6 flash and 3.5 flash lite models 2026-07-22 12:53:32 -05:00
Aiden Cline 5aef4ad9e9 Merge pull request #3358 from anomalyco/automation/sync-models-vercel
chore(sync): update Vercel AI Gateway model catalog
2026-07-22 12:51:09 -05:00
Aiden Cline 86eb924115 fix(vercel): set reasoning_options for laguna-s-2.1 and hy3
Laguna S 2.1 exposes per-request thinking via enable_thinking (toggle).
Hy3 exposes reasoning_effort no_think|low|high (mapped to none|low|high).
2026-07-22 12:49:33 -05:00
Aiden Cline d0ac7a447b Merge pull request #3377 from anomalyco/automation/sync-models-huggingface
chore(sync): update Hugging Face model catalog
2026-07-22 12:47:13 -05:00
Aiden Cline 7f98a9100b Merge pull request #3375 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-22 12:46:13 -05:00
Aiden Cline e0b2ffde94 fix(huggingface): restore MiMo reasoning_options after sync wipe
Toggle via reasoning.enabled; effort via reasoning_effort
(none|low|medium|high|xhigh). Top-of-file comments document wire format.
2026-07-22 12:45:48 -05:00
github-actions[bot] 23053dfabb chore(sync): update Hugging Face model catalog 2026-07-22 17:44:33 +00:00
github-actions[bot] 5423b5ac78 chore(sync): update Vercel AI Gateway model catalog 2026-07-22 17:44:31 +00:00
github-actions[bot] e3ee48788b chore(sync): update OpenRouter model catalog 2026-07-22 17:44:27 +00:00
Jack b013d94872 add hy3 to go 2026-07-23 00:36:51 +08:00
Aiden Cline 5736bbd70d Merge pull request #3380 from doedja/chore/kenari-catalog-refresh
chore(kenari): refresh model catalog to current live endpoint
2026-07-22 10:07:01 -05:00
Aiden Cline dc1e4c8620 Merge pull request #3385 from anomalyco/fix/pr-3384-cortecs-hy3
fix(cortecs): add Hy3 via tencent base_model
2026-07-22 10:05:09 -05:00
Aiden Cline 8f12116a06 docs(agents): require catalog costs in USD per million tokens 2026-07-22 10:02:21 -05:00
Aiden Cline d86fb803b6 fix(cortecs): convert Hy3 costs from EUR to USD
Cortecs API returns EUR; catalog schema requires USD per 1M tokens.
2026-07-22 10:01:08 -05:00
Aiden Cline e3b1a320c9 fix(cortecs): add Hy3 via tencent base_model
PR #3384 was incomplete (missing required fields, wrong model id).
Add models/tencent/hy3.toml and wire Cortecs/OpenRouter/TokenHub/Token
Plan through base_model so Tencent lab metadata is shared.
2026-07-22 09:56:31 -05:00
Snat3r a2bf402116 Create tencent-hy3.toml for Tencent Hy3 model
Add configuration for Tencent Hy3 model with options.
2026-07-22 16:51:29 +02:00
Nur Ad-Duja 83040e034b chore(kenari): refresh model catalog to live /v1/models
Adds 18 models and removes 3 no longer served, generated by running the
kenari sync adapter (PR #3171) against the current dev branch. Cost stays
0 by policy (IDR prepaid wallet), reasoning_options come verbatim from
the endpoint.
2026-07-22 21:05:46 +07:00
Aiden Cline 387f25aa5b Merge pull request #3363 from anomalyco/automation/sync-models-venice
chore(sync): update Venice model catalog
2026-07-22 00:06:13 -05:00
Aiden Cline 963dc16868 Merge pull request #3368 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-22 00:06:00 -05:00
Aiden Cline 708341dba2 Merge pull request #3374 from anomalyco/explore/ci-automation-models
chore(ci): switch automation models to opencode/grok-4.5
2026-07-22 00:05:46 -05:00
Aiden Cline ddc2a950f3 chore(ci): switch automation models to opencode/grok-4.5
Use grok-4.5 for opencode comments, CI fixer, issue fixer, and PR reviewer.
2026-07-22 00:04:36 -05:00
github-actions[bot] 889bd835ca chore(sync): update Venice model catalog 2026-07-22 03:24:04 +00:00
github-actions[bot] 6ff3db4e81 chore(sync): update OpenRouter model catalog 2026-07-22 03:24:04 +00:00
Aiden Cline 675e65417f Merge pull request #3369 from Prashanth-InferX/patch-3
fix(inferx): flatten model directory structure
2026-07-21 20:44:01 -05:00
Aiden Cline cf46b400dd Merge pull request #3362 from anomalyco/automation/sync-models-wandb
chore(sync): update Weights & Biases model catalog
2026-07-21 20:33:44 -05:00
Prashanth-InferX 16c0e329e2 fix: move 1m variant to models root. 2026-07-21 18:17:06 -07:00
Prashanth-InferX a63af7da95 fix(inferx): flatten model directory structure 2026-07-21 18:05:04 -07:00
github-actions[bot] 1812b10f71 chore(sync): update Weights & Biases model catalog 2026-07-22 00:52:27 +00:00
Aiden Cline 7d7b9053ac Merge pull request #3356 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-21 19:46:14 -05:00
Aiden Cline 7138e748ef Merge pull request #3367 from aki-io-team/provider_aki_io_pr4
adds AKI.IO as provider
2026-07-21 19:18:58 -05:00
github-actions[bot] 7d87da885e chore(sync): update OpenRouter model catalog 2026-07-21 23:36:14 +00:00
Toine 7c49a655cf adds AKI.IO as provider 2026-07-22 01:16:01 +02:00
Aiden Cline f2a80d69d9 Merge pull request #3360 from anomalyco/automation/sync-models-venice
chore(sync): update Venice model catalog
2026-07-21 14:19:55 -05:00
Aiden Cline 4c9f3ef677 Merge pull request #3361 from anomalyco/fix/llmgateway-gemini-reasoning-options
fix(llmgateway): Gemini 3.6/3.5 Flash Lite reasoning_options
2026-07-21 14:19:46 -05:00
Aiden Cline c71de45508 fix(llmgateway): set Gemini 3.6/3.5 Flash Lite effort options
New factored creates defaulted to reasoning_options = [] because the
gateway adapter does not emit options. Match sibling gemini-3.5-flash
and gemini-3.1-flash-lite (minimal|low|medium|high).
2026-07-21 14:18:07 -05:00
github-actions[bot] c356460a71 chore(sync): update Venice model catalog 2026-07-21 18:44:26 +00:00
github-actions[bot] c61a0f9163 chore(sync): update LLM Gateway model catalog 2026-07-21 18:44:22 +00:00
Frank 180a9a5d2a update zen models 2026-07-21 13:16:13 -04:00
Frank dd4571595a update zen models 2026-07-21 13:09:47 -04:00
Frank 72749afeb6 add laguna s 2.1 model 2026-07-21 13:03:58 -04:00
Aiden Cline 2bf7d0ce8d Merge pull request #3354 from anomalyco/automation/sync-models-vercel
chore(sync): update Vercel AI Gateway model catalog
2026-07-21 11:07:10 -05:00
Aiden Cline bc7639a3bd fix(vercel): set reasoning_options for gemini-3.5-flash-lite and gemini-3.6-flash
Both models support thinkingLevel minimal/low/medium/high via Vercel AI Gateway.
2026-07-21 10:59:51 -05:00
Aiden Cline fff8e0169f Merge pull request #3353 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-21 10:59:48 -05:00
Aiden Cline 97af27c2d9 Merge pull request #3355 from anomalyco/feat/google-gemini-3.6-flash-and-3.5-flash-lite
feat(google): add Gemini 3.6 Flash and 3.5 Flash Lite
2026-07-21 10:59:34 -05:00
Aiden Cline 7a344d9155 feat(google): add Gemini 3.6 Flash and 3.5 Flash Lite
Wire up provider entries for today's Gemini API releases using
existing models/google metadata and official pricing.
2026-07-21 10:58:16 -05:00
github-actions[bot] 4b96a909c3 chore(sync): update Vercel AI Gateway model catalog 2026-07-21 15:51:24 +00:00
github-actions[bot] 0bab3e10b7 chore(sync): update OpenRouter model catalog 2026-07-21 15:51:20 +00:00
Aiden Cline 91eee91ce6 Merge pull request #3348 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-21 10:19:12 -05:00
Aiden Cline 01737a716a Merge pull request #2941 from kxiserino/add-cline-pass-provider
Add ClinePass provider
2026-07-21 10:18:51 -05:00
Frank 93546d8e0a update zen models 2026-07-21 11:11:11 -04:00
Frank 974fa55ea5 Add gemini 3.6 and 3.5 flash lite 2026-07-21 11:08:21 -04:00
github-actions[bot] 60129bebc6 chore(sync): update OpenRouter model catalog 2026-07-21 14:57:07 +00:00
Jack d4189e71d9 chore: deprecate Hy3 Free 2026-07-21 11:50:15 +08:00
Aiden Cline 956d3ef2d6 Merge pull request #3349 from BaronCyrus/codex/add-qwen3.8-max-preview
feat(alibaba-token-plan): add qwen3.8-max-preview
2026-07-20 14:55:57 -05:00
张洋凡 fb2a2353b3 fix(alibaba-token-plan): address qwen3.8 review feedback 2026-07-21 00:02:53 +08:00
张洋凡 b9a7514100 fix(alibaba-token-plan): use native qwen3.8 effort tiers 2026-07-20 23:47:20 +08:00
张洋凡 9f1772cc66 fix(alibaba-token-plan): align qwen3.8 effort with opencode 2026-07-20 23:30:33 +08:00
张洋凡 8657ff5d23 fix(alibaba-token-plan): correct qwen3.8 token limits 2026-07-20 23:24:57 +08:00
张洋凡 3e786e8339 fix(alibaba-token-plan): add qwen3.8 reasoning controls 2026-07-20 23:07:55 +08:00
张洋凡 2698c88c5f feat(alibaba-token-plan): add qwen3.8-max-preview 2026-07-20 23:00:05 +08:00
Aiden Cline 84d0f286b6 Merge pull request #3347 from anomalyco/fix/muse-spark-omit-none-reasoning
fix(muse-spark): omit none from reasoning effort options
2026-07-20 09:52:38 -05:00
Aiden Cline 022185b0fc fix(muse-spark): omit none from reasoning effort options
Muse Spark does not support disabling reasoning via effort "none".
Align meta, vercel, and llmgateway with openrouter/empiriolabs.
2026-07-20 09:49:56 -05:00
Aiden Cline c5962a12f7 Merge pull request #3339 from anomalyco/automation/sync-models-vercel
chore(sync): update Vercel AI Gateway model catalog
2026-07-20 09:35:10 -05:00
Aiden Cline 1d7c74d2db Merge pull request #3340 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-20 09:34:59 -05:00
Aiden Cline 2212a7034e Merge pull request #3344 from quantverse/dev
feat(novita): Add Kimi K2.7 code and Kimi K3
2026-07-20 09:34:22 -05:00
Aiden Cline 9f07595945 Merge pull request #3345 from arshadbarves/add-zenmux-kimi-k3-free
Add moonshotai/kimi-k3-free to ZenMux provider
2026-07-20 09:34:03 -05:00
Arshad Barves 1b61b6d90a Fix ZenMux kimi-k3-free base_model to inherit from moonshotai/kimi-k3 2026-07-20 19:37:46 +05:30
Arshad Barves 1b5e70c69c Add moonshotai/kimi-k3-free to ZenMux provider 2026-07-20 19:33:03 +05:30
github-actions[bot] 6a431dd1dd chore(sync): update OpenRouter model catalog 2026-07-20 13:56:17 +00:00
github-actions[bot] a64f2d2cb5 chore(sync): update Vercel AI Gateway model catalog 2026-07-20 13:56:14 +00:00
Karel Vavra 8ad2931241 feat(novita): Add kimi-k3 to novita.ai 2026-07-20 15:47:15 +02:00
Karel Vávra 2673c42681 feat(novita): Add kimi-k2.7-code to novita.ai 2026-07-20 15:42:02 +02:00
Aiden Cline ca21350243 Merge pull request #3336 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-19 23:27:28 -05:00
Aiden Cline 9adacdb03f Merge pull request #3338 from anomalyco/fix/kimi-for-coding-official-id
fix(kimi-for-coding): use official k2.7 model id
2026-07-19 23:26:59 -05:00
Aiden Cline 3bc0c6ddf7 fix(kimi-for-coding): use official k2.7 model id
Rename k2p7 → kimi-for-coding to match Moonshot's documented API IDs.
Unofficial names are being rejected; wrong IDs silently fall back to the
default model and mislead users.

Closes #1441
2026-07-19 23:25:56 -05:00
github-actions[bot] 6532730857 chore(sync): update OpenRouter model catalog 2026-07-20 03:24:48 +00:00
Frank bb22b6c979 fix: use OpenAI SDK for Zen Grok 4.5 2026-07-19 02:31:28 -04:00
Aiden Cline 0795b333b7 Merge pull request #3325 from anomalyco/issue-3324
fix: Mark 6 removed Together.ai serverless models as status = "deprecated"
2026-07-19 00:10:41 -05:00
Aiden Cline 3c5c10dd7a fix: restore removed Together.ai models as deprecated
Follow repo convention: models no longer served stay in the catalog
with status = "deprecated" so pricing/limits/history and external ID
references are preserved. Reverts the deletion approach.
2026-07-19 00:00:13 -05:00
Aiden Cline 0e66972fc6 fix: delete removed Together.ai serverless models
Five models are absent from Together.ai's serverless catalog and are no
longer served. Delete them instead of marking deprecated. Leave
Qwen/Qwen3.6-Plus active — it is still listed in the catalog.

Closes #3324
2026-07-18 23:36:38 -05:00
Aiden Cline 5b615d271d Merge pull request #3314 from anomalyco/automation/sync-models-vercel
chore(sync): update Vercel AI Gateway model catalog
2026-07-18 23:27:31 -05:00
Aiden Cline c7e82182af Merge pull request #3330 from anomalyco/automation/sync-models-crossmodel
chore(sync): update CrossModel model catalog
2026-07-18 23:27:19 -05:00
Aiden Cline 98f8abc6d9 Merge pull request #3335 from anomalyco/automation/sync-models-venice
chore(sync): update Venice model catalog
2026-07-18 23:24:00 -05:00
Aiden Cline 66dad824a7 Merge pull request #3326 from anomalyco/automation/sync-models-ambient
chore(sync): update Ambient model catalog
2026-07-18 23:23:51 -05:00
Aiden Cline 7a54b684cc Merge pull request #3323 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-18 23:23:37 -05:00
Aiden Cline 8a45b33246 Merge pull request #3333 from anomalyco/automation/sync-models-xai
chore(sync): update xAI model catalog
2026-07-18 23:20:56 -05:00
github-actions[bot] 39dd66c818 chore(sync): update OpenRouter model catalog 2026-07-19 03:24:36 +00:00
github-actions[bot] 03ca9dfe5f chore(sync): update Vercel AI Gateway model catalog 2026-07-19 03:24:35 +00:00
github-actions[bot] d395d4fa5c chore(sync): update CrossModel model catalog 2026-07-19 03:24:35 +00:00
github-actions[bot] ab98fd3a72 chore(sync): update Ambient model catalog 2026-07-19 03:24:33 +00:00
github-actions[bot] 41aed22b78 chore(sync): update xAI model catalog 2026-07-19 03:24:31 +00:00
github-actions[bot] a92ce1c6b8 chore(sync): update Venice model catalog 2026-07-19 03:24:30 +00:00
Aiden Cline 1e752d78d7 Merge pull request #3329 from kevinxdev/agent/add-nebius-models
Add Kimi K2.7-Code and MiniMax-M3 to Nebius Token Factory
2026-07-18 12:01:46 -05:00
Aiden Cline c6b8283234 Merge pull request #3331 from anomalyco/fix/kimi-k3-temperature
fix: mark Kimi K3 temperature as unsupported
2026-07-18 11:52:12 -05:00
Aiden Cline 36ee4db354 fix(vercel): stop hardcoding temperature on synced models
Vercel has no sampling-parameter signal. Hardcoding temperature=true
would reassert true on factored models like kimi-k3 whenever sync
rewrites the file, undoing base_model temperature=false. Inherit from
existing/base instead.
2026-07-18 11:49:12 -05:00
Aiden Cline a31cc6dcbd fix: mark Kimi K3 temperature as unsupported
Moonshot fixes K3 sampling server-side (temperature locked at 1.0);
passing any other value returns HTTP 400. Correct the base model so
all providers inherit temperature=false instead of per-provider overrides.
2026-07-18 11:38:42 -05:00
kevin eb199f20a2 Add Kimi K2.7-Code and MiniMax-M3 to Nebius Token Factory
Register the two new Nebius endpoints with pricing and limits from
https://tokenfactory.nebius.com/endpoints (models_info API).
2026-07-18 13:05:53 +02:00
github-actions[bot] ef75e88af5 fix: Mark 6 removed Together.ai serverless models as status = "deprecated" 2026-07-18 05:22:34 +00:00
Aiden Cline 2f0d4cb935 Merge pull request #3322 from anomalyco/fix/copilot-gpt-5.6-cache-write
fix(github-copilot): add cache_write cost for GPT-5.6 models
2026-07-17 23:59:09 -05:00
Aiden Cline a5631d2abc fix(github-copilot): add cache_write cost for GPT-5.6 models
GPT-5.6 family bills cache writes at 1.25× uncached input. Match OpenAI
pricing on Copilot Sol/Terra/Luna (including long-context tiers).

Closes #3282
2026-07-17 23:56:28 -05:00
Aiden Cline 195e59863b Merge pull request #3321 from anomalyco/add/kimi-k3-cloudflare
feat: add Kimi K3 to Cloudflare AI Gateway
2026-07-17 23:53:15 -05:00
Aiden Cline 48c0e324f5 fix: drop Kimi K3 from Workers AI
K3 is proxied third-party (hosting=proxied, no @cf/ ID), not
Cloudflare-hosted Workers AI. Keep only AI Gateway entry.
2026-07-17 23:52:33 -05:00
Aiden Cline f51ef90caf feat: add Kimi K3 to Cloudflare AI Gateway and Workers AI
Cloudflare hosts moonshotai/kimi-k3 on the unified AI catalog.
Azure Foundry, Bedrock, and Vertex do not list K3 yet.
2026-07-17 23:47:27 -05:00
Aiden Cline eec5e00e4f Merge pull request #3320 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-17 23:43:59 -05:00
Aiden Cline 128ab75fbe Merge pull request #3319 from anomalyco/automation/sync-models-ambient
chore(sync): update Ambient model catalog
2026-07-17 23:43:45 -05:00
Aiden Cline 4800af7a79 fix(ambient): add verified reasoning controls 2026-07-17 23:12:45 -05:00
github-actions[bot] fa0ab66970 chore(sync): update Ambient model catalog 2026-07-18 03:22:11 +00:00
github-actions[bot] 3dbcaf3b6b chore(sync): update OpenRouter model catalog 2026-07-18 03:22:10 +00:00
Aiden Cline 5cb56b71ca Merge pull request #3311 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-17 22:04:23 -05:00
Aiden Cline b7888f028a Merge pull request #3316 from anomalyco/automation/sync-models-deepinfra
chore(sync): update Deep Infra model catalog
2026-07-17 22:04:03 -05:00
Aiden Cline 6193ecf774 Merge pull request #3318 from anomalyco/automation/sync-models-venice
chore(sync): update Venice model catalog
2026-07-17 21:58:33 -05:00
github-actions[bot] 3c5e3ed70b chore(sync): update Venice model catalog 2026-07-18 01:56:17 +00:00
github-actions[bot] 7eaf6972b2 chore(sync): update OpenRouter model catalog 2026-07-18 01:56:16 +00:00
github-actions[bot] bf1a01ec85 chore(sync): update Deep Infra model catalog 2026-07-18 01:56:14 +00:00
Frank 112f21b145 Merge branch 'dev' of github.com:anomalyco/models.dev into dev 2026-07-17 16:00:15 -04:00
Frank c27b2ce71d update go models 2026-07-17 16:00:13 -04:00
Aiden Cline 800bbc1253 Merge pull request #3312 from anomalyco/fix/azure-claude-1m-context
fix: Azure Foundry context limits (Claude + non-Claude)
2026-07-17 11:51:28 -05:00
Aiden Cline 7574a882fe revert: restore Cohere Embed v4 context to 128K on Azure
Azure catalog documents embed-v-4-0 at 128k/131.072k context.
The Learn "sold by Azure" table listing 512 text tokens matches
Embed v3 and was misapplied to v4.
2026-07-17 11:48:49 -05:00
Aiden Cline 0675cf13ff fix: audit non-Claude Azure context limits vs Foundry docs
Align Azure OpenAI/partner model limits with Microsoft Foundry docs:
- gpt-5/5-mini/5-nano/5.1: context 400K + input 272K (was input-only 272K)
- gpt-5 codex/5.1-codex/5.2/5.3-codex: add missing input 272K
- Llama 4 Maverick: 1M context (was 128K)
- model-router: 200K context (was 128K)
- Cohere Command A: 131K/8K per Azure Direct table
- Cohere embed v4: 512 token text limit per Azure Direct table

ACS entries that symlink azure models pick these up automatically.
2026-07-17 11:23:33 -05:00
Aiden Cline 3b2096eb78 fix: raise Azure Claude Opus 4.6 context to 1M
Azure Foundry no longer applies the legacy 200K context cap for
claude-opus-4-6; both azure and azure-cognitive-services now match
the 1M window documented for Foundry Claude models.
2026-07-17 11:18:07 -05:00
Jack a049c7036b update DS-V4-Pro price in OpenCode Go 2026-07-17 23:21:46 +08:00
Aiden Cline 35709398f3 Merge pull request #3300 from zainhas/dev
[Together AI] add inkling
2026-07-17 09:57:52 -05:00
Aiden Cline 24abede254 Merge pull request #3308 from leszek3737/zenmux_kimi_k3
feat(zenmux): Add Kimi-k3 model configuration
2026-07-17 09:57:28 -05:00
Aiden Cline ac5223544c Merge pull request #3290 from anomalyco/automation/sync-models-empiriolabs
chore(sync): update EmpirioLabs AI model catalog
2026-07-17 09:56:39 -05:00
Aiden Cline 8ed112a0d7 Merge pull request #3292 from anomalyco/automation/sync-models-venice
chore(sync): update Venice model catalog
2026-07-17 09:56:19 -05:00
Aiden Cline b9a68fdb79 Merge pull request #3289 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-17 09:56:03 -05:00
Aiden Cline c5a634a922 Merge pull request #3305 from anomalyco/automation/sync-models-baseten
chore(sync): update Baseten model catalog
2026-07-17 09:55:45 -05:00
Aiden Cline a0a26e2aef Merge pull request #3309 from Kibouo/fix_azure_opus48
Fix azure opus48
2026-07-17 09:55:28 -05:00
github-actions[bot] 286bd0fc46 chore(sync): update OpenRouter model catalog 2026-07-17 14:51:34 +00:00
github-actions[bot] 5ce4218fdd chore(sync): update Venice model catalog 2026-07-17 14:51:33 +00:00
github-actions[bot] 6deb0f9b62 chore(sync): update Baseten model catalog 2026-07-17 14:51:32 +00:00
github-actions[bot] 79bcc62824 chore(sync): update EmpirioLabs AI model catalog 2026-07-17 14:51:31 +00:00
Frank fe316dd6c2 Merge branch 'dev' of github.com:anomalyco/models.dev into dev 2026-07-17 10:43:34 -04:00
Frank 574b85ba77 update go models 2026-07-17 10:43:12 -04:00
Jack 6dcf732d1f Merge pull request #3310 from wszqkzqk/feat/kimi-k3-effort-levels
feat(moonshotai): add Kimi K3 low/high effort options
2026-07-17 21:38:03 +08:00
Csonka Mihaly 417d4fc160 Fix possible effort levels 2026-07-17 15:02:37 +02:00
Csonka Mihaly 85aef3a05e Fix context window size 2026-07-17 15:00:15 +02:00
Jack 89183a9646 Merge pull request #3307 from 7Sageer/kimi-for-coding-drop-routed-models
fix(kimi-for-coding): drop legacy models auto-routed to k2.7-code
2026-07-17 20:29:17 +08:00
Leszek 0dcf5c4600 feat(zenmux): Add Kimi-k3 model configuration 2026-07-17 13:55:57 +02:00
Zhou Qiankang f6ac2f0457 feat(moonshotai): add Kimi K3 low/high effort options
K3 adaptive thinking now accepts output_config.effort = "low" | "high"
| "max" (previously max-only) on both the Moonshot AI platform and
Kimi For Coding, which mirrors the platform API surface.
2026-07-17 17:36:57 +08:00
7Sageer 1d1282ffb8 fix(kimi-for-coding): drop legacy models auto-routed to k2.7-code
The api.kimi.com/coding endpoint no longer serves k2p5, k2p6, and
kimi-k2-thinking as distinct models; requests for them are automatically
routed to K2.7 Code (k2p7). Remove them so the catalog only lists models
the endpoint actually exposes: k2p7, kimi-for-coding-highspeed, and k3.
2026-07-17 17:00:58 +08:00
Frank 9e26ded0d1 Revert "update go models"
This reverts commit ccd55d46e8.
2026-07-17 03:35:57 -04:00
Frank ccd55d46e8 update go models 2026-07-17 03:27:49 -04:00
Zain Hasan b25ad5c651 add audio input modality 2026-07-16 23:28:20 -07:00
Zain Hasan d0109ff70b remove redundancy 2026-07-16 22:23:44 -07:00
Aiden Cline 3d027d7d5f Merge pull request #3301 from rekram1-node/fix/inkling-reasoning-options
fix(thinkingmachines): document Inkling reasoning_effort options
2026-07-16 23:34:42 -05:00
Aiden Cline 295a483511 fix(thinkingmachines): document Inkling reasoning_effort options
Baseten and Vercel incorrectly used empty reasoning_options for Inkling.
Both expose top-level reasoning_effort with none/minimal/low/medium/high/xhigh.
2026-07-16 23:16:35 -05:00
Aiden Cline 4011599eb1 Merge pull request #3293 from anomalyco/automation/sync-models-llmgateway
chore(sync): update LLM Gateway model catalog
2026-07-16 23:15:12 -05:00
Aiden Cline c7bf39e4e9 Merge pull request #3296 from anomalyco/automation/sync-models-deepinfra
chore(sync): update Deep Infra model catalog
2026-07-16 23:15:00 -05:00
Aiden Cline a4665d1b88 Merge pull request #3288 from anomalyco/automation/sync-models-baseten
chore(sync): update Baseten model catalog
2026-07-16 23:14:44 -05:00
github-actions[bot] cf27076531 chore(sync): update Baseten model catalog 2026-07-17 03:24:07 +00:00
github-actions[bot] 008a6b56ba chore(sync): update Deep Infra model catalog 2026-07-17 03:24:05 +00:00
github-actions[bot] 9d1a6525c1 chore(sync): update LLM Gateway model catalog 2026-07-17 03:24:04 +00:00
Zain Hasan c094b61135 add reasoning efforts 2026-07-16 19:22:25 -07:00
Zain Hasan 3dc53bfb45 [Together AI] add inkling 2026-07-16 19:18:39 -07:00
Frank 7fbc892898 Merge branch 'dev' of github.com:anomalyco/models.dev into dev 2026-07-16 21:46:41 -04:00
Frank cb56524aa6 update go models 2026-07-16 21:46:14 -04:00
opencode-agent[bot] d15aa5a09d fix(moonshotai): add Kimi K3 pricing (#3298)
Co-authored-by: Dax Raad <d@ironbay.co>
2026-07-16 20:51:59 -04:00
Frank c67a5bba05 update Go models 2026-07-16 17:53:47 -04:00
Aiden Cline e5931b2156 Merge pull request #3287 from anomalyco/automation/sync-models-vercel
chore(sync): update Vercel AI Gateway model catalog
2026-07-16 11:45:11 -05:00
github-actions[bot] 818b0516bd chore(sync): update Vercel AI Gateway model catalog 2026-07-16 16:44:49 +00:00
Aiden Cline 52db94a899 Merge pull request #3286 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-16 11:25:41 -05:00
github-actions[bot] 7d7142b080 chore(sync): update OpenRouter model catalog 2026-07-16 15:47:35 +00:00
Aiden Cline a0c8c6b389 Merge pull request #3268 from anomalyco/automation/sync-models-vercel
chore(sync): update Vercel AI Gateway model catalog
2026-07-16 10:24:52 -05:00
Aiden Cline a0bb3cbda6 fix(vercel): use base_model for new catalog entries and add Thinking Machines
Wire Opus Fast, Realtime Whisper, and Inkling through model metadata, and
add a Thinking Machines provider for first-party Inkling access.
2026-07-16 10:22:17 -05:00
Aiden Cline a06cd852c9 Merge pull request #3280 from YOYO-do/feat/aihubmix-gpt56-grok45-claude5
feat(aihubmix): add GPT 5.6 and priority LLM models
2026-07-16 10:17:49 -05:00
Aiden Cline eb442c24da Merge pull request #3275 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-16 10:08:27 -05:00
Aiden Cline c2effa3c25 fix(aihubmix): align sonnet-5 structured_output and grok-build reasoning
Match AIHubMix models API structured_outputs for Claude Sonnet 5.
Use empty reasoning_options for Grok Build where no control is verified.
2026-07-16 10:07:49 -05:00
Aiden Cline 9cfe6ecfb7 Merge pull request #3276 from anomalyco/automation/sync-models-baseten
chore(sync): update Baseten model catalog
2026-07-16 10:07:34 -05:00
Aiden Cline e482704aa5 Merge pull request #3277 from anomalyco/automation/sync-models-venice
chore(sync): update Venice model catalog
2026-07-16 10:02:32 -05:00
Aiden Cline a582dcd4a5 Merge pull request #3281 from tsibog/evroc/add-glm-5.2
[evroc] add GLM 5.2
2026-07-16 10:02:20 -05:00
Aiden Cline df12b8724a Merge pull request #3279 from anomalyco/automation/sync-models-ambient
chore(sync): update Ambient model catalog
2026-07-16 10:01:58 -05:00
Aiden Cline b4ece56d70 Merge pull request #3285 from 7Sageer/feat/kimi-k3
feat(moonshotai): add Kimi K3
2026-07-16 10:01:21 -05:00
github-actions[bot] 5de41e0e5f chore(sync): update Ambient model catalog 2026-07-16 14:56:25 +00:00
github-actions[bot] d667b63b7f chore(sync): update OpenRouter model catalog 2026-07-16 14:56:23 +00:00
github-actions[bot] 976ca20ebf chore(sync): update Vercel AI Gateway model catalog 2026-07-16 14:56:21 +00:00
github-actions[bot] 8284b61189 chore(sync): update Baseten model catalog 2026-07-16 14:56:20 +00:00
github-actions[bot] 5d32b5385f chore(sync): update Venice model catalog 2026-07-16 14:56:20 +00:00
7Sageer 2aaff449a6 feat(moonshotai): add Kimi K3 model metadata
- Base metadata in models/moonshotai/kimi-k3.toml (1M context,
  multimodal input, open weights) with provider entries for
  moonshotai and moonshotai-cn (symlink): toggle + max-effort
  reasoning options, interleaved reasoning_content.
- kimi-for-coding adds a k3 entry under its short-alias convention
  (k2p5/k2p6/k2p7); the provider stays on @ai-sdk/anthropic, the
  officially documented Messages surface, with the verified
  dual-protocol behavior recorded in provider.toml.
- New kimi-k3 model family: enum value, inference rule, tests.
2026-07-16 21:52:29 +08:00
tsibog 4975b7fb48 [evroc] add GLM 5.2
evroc now serves zai-org/GLM-5.2 as a shared model. Price from the billing
API (EUR 1.25/5.00 per 1M), converted at the 1.15 rate used by the other
evroc models. Context bumped to the 1048576 evroc actually serves.

Reasoning surface checked against the live endpoint: GLM-5.2's chat template
only trains two effort levels (high/max, default max); other values collapse
to max. Thinking toggles off via enable_thinking=false or effort none.
2026-07-16 12:01:21 +03:00
YOYO-do 1dd66c87b2 feat(aihubmix): add priority LLM models 2026-07-16 16:46:33 +08:00
YOYO-do c79b45079c feat(aihubmix): add GPT 5.6, Grok 4.5, and Claude Sonnet 5 2026-07-16 13:57:34 +08:00
Aiden Cline d7fd1e1eb9 Merge pull request #3265 from anomalyco/automation/sync-models-venice
chore(sync): update Venice model catalog
2026-07-15 16:04:01 -05:00
github-actions[bot] 0e94e0644b chore(sync): update Venice model catalog 2026-07-15 20:37:19 +00:00
Aiden Cline 0d5594e06a Merge pull request #3269 from BiuBiu2015/feat/kimi-for-coding-highspeed
feat(kimi-for-coding): add HighSpeed model
2026-07-15 13:54:05 -05:00
Aiden Cline 9aec93e3e2 Merge pull request #3264 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-15 10:14:36 -05:00
Aiden Cline bfffcac592 Merge pull request #3260 from anomalyco/automation/sync-models-llmgateway
chore(sync): update LLM Gateway model catalog
2026-07-15 10:14:16 -05:00
Aiden Cline 2953fed88b Merge pull request #3266 from anomalyco/fix/latest-alias-reasoning-options
fix: align *-latest alias reasoning_options with current model targets
2026-07-15 10:13:59 -05:00
Aiden Cline dc26f9bc5f fix(openrouter): prefer API reasoning_options over authored ones
Stop sticky-preserving non-empty authored reasoning_options during OpenRouter
sync so aliases and rotated models pick up live effort/budget metadata.
Fall back to authored options only when the API omits a reasoning object.
2026-07-15 10:10:37 -05:00
Aiden Cline 507a68d0a1 Merge pull request #3263 from anomalyco/automation/sync-models-pioneer
chore(sync): update Pioneer model catalog
2026-07-15 10:08:12 -05:00
Aiden Cline f7a39e320e Merge pull request #3273 from anomalyco/issue-3271
fix: privatemode-ai model lineup is stale
2026-07-15 10:07:55 -05:00
Aiden Cline c3de500b5d Delete providers/privatemode-ai/models/gemma-3-27b.toml 2026-07-15 10:06:20 -05:00
Aiden Cline d479eebb47 Delete providers/privatemode-ai/models/qwen3-coder-30b-a3b.toml 2026-07-15 10:06:08 -05:00
Aiden Cline c8f0d25871 Merge pull request #3274 from stargazer617/ollama-cloud/retire-deprecated-models
chore(ollama-cloud): retire deprecated models
2026-07-15 10:05:36 -05:00
github-actions[bot] d0e10d7d44 chore(sync): update LLM Gateway model catalog 2026-07-15 14:55:01 +00:00
github-actions[bot] b91f684b9b chore(sync): update OpenRouter model catalog 2026-07-15 14:54:57 +00:00
github-actions[bot] cee485c1c4 chore(sync): update Pioneer model catalog 2026-07-15 14:54:56 +00:00
Stargazer 4225a7adda chore(ollama-cloud): retire deprecated models
Remove 25 models that Ollama Cloud retired on/before 2026-07-15.
The live catalog (https://ollama.com/v1/models) now serves only the 18
remaining models; all removed entries are gone from the API.

Retired 2026-07-15 (16):
  deepseek-v3.1:671b, deepseek-v3.2, devstral-2:123b, devstral-small-2:24b,
  ministral-3:14b, ministral-3:3b, ministral-3:8b, gemini-3-flash-preview,
  gemma3:12b, gemma3:27b, gemma3:4b, glm-4.7, glm-5, minimax-m2.1,
  qwen3-coder-next, qwen3-coder:480b

Retired 2026-06-30 / 2026-06-16 (9):
  rnj-1:8b, kimi-k2-thinking, kimi-k2:1t, minimax-m2, glm-4.6,
  qwen3-next:80b, qwen3-vl:235b, qwen3-vl:235b-instruct, cogito-2.1:671b

Source: https://docs.ollama.com/cloud#retirements
Verified via `bun validate` (exit 0) and cross-checked against the live
/v1/models endpoint — 18 ollama-cloud models remain, matching the API.
2026-07-15 14:36:45 +03:00
github-actions[bot] 725eea1b25 fix: privatemode-ai model lineup is stale 2026-07-15 10:29:50 +00:00
PixelDrifter a99e8b188f feat(kimi-for-coding): add HighSpeed model 2026-07-15 15:58:02 +08:00
Aiden Cline af5c74ff69 fix: align *-latest alias reasoning_options and metadata with current targets
Latest aliases were left on previous-generation controls/pricing after the
underlying models rotated (e.g. gemini-flash-latest still had Gemini 2.5
toggle+budget while mapping to 3.5 Flash effort). Sync RO, cost, and
related metadata to the models these aliases currently resolve to.
2026-07-14 22:15:49 -05:00
Aiden Cline 14b8cd5612 Merge pull request #3262 from rekram1-node/fix/nanogpt-reasoning
fix(nano-gpt): correct reasoning options
2026-07-14 16:01:16 -05:00
Aiden Cline 1d1ef59cd1 fix(nano-gpt): correct reasoning options 2026-07-14 15:58:56 -05:00
Aiden Cline 7d43c564b0 Merge pull request #3259 from anomalyco/automation/sync-models-vercel
chore(sync): update Vercel AI Gateway model catalog
2026-07-14 15:22:45 -05:00
Aiden Cline c0cfed9371 Merge pull request #3258 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-14 15:14:32 -05:00
github-actions[bot] bed4bc4f3d chore(sync): update Vercel AI Gateway model catalog 2026-07-14 19:45:58 +00:00
github-actions[bot] 97f64dffe9 chore(sync): update OpenRouter model catalog 2026-07-14 19:45:54 +00:00
Aiden Cline 7eef359d6b Merge pull request #3257 from rekram1-node/fix/cohere-model-metadata
refactor(cohere): centralize model metadata
2026-07-14 11:22:24 -05:00
Aiden Cline b463ea1300 refactor(cohere): centralize model metadata 2026-07-14 11:00:14 -05:00
Aiden Cline 6c9e0b6af0 Merge pull request #3256 from davidkna-sap/davidkna-sap/models-dev-update
chore(sap-ai-core): Add missing models & deprecate retired models
2026-07-14 10:51:03 -05:00
David Knaack 5e2483bb19 chore: address additional review feedback 2026-07-14 17:32:45 +02:00
Aiden Cline d2bb32ceb3 Merge pull request #3252 from Prashanth-InferX/patch-2
fix(inferx): update api endpoint to endpoints/v1
2026-07-14 10:05:04 -05:00
Aiden Cline 293903e820 Merge pull request #3241 from anomalyco/automation/sync-models-crossmodel
chore(sync): update CrossModel model catalog
2026-07-14 10:04:45 -05:00
Aiden Cline 1d79f0aef8 Merge pull request #3242 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-14 10:04:23 -05:00
Aiden Cline 1f0c79af71 Merge pull request #3247 from anomalyco/automation/sync-models-vercel
chore(sync): update Vercel AI Gateway model catalog
2026-07-14 10:04:03 -05:00
Aiden Cline f054b1f447 Merge pull request #3251 from anomalyco/automation/sync-models-baseten
chore(sync): update Baseten model catalog
2026-07-14 10:03:47 -05:00
Aiden Cline 0863d10ca0 Merge pull request #3255 from anomalyco/automation/sync-models-ambient
chore(sync): update Ambient model catalog
2026-07-14 10:03:35 -05:00
github-actions[bot] 4d9f510e34 chore(sync): update Baseten model catalog 2026-07-14 14:54:47 +00:00
github-actions[bot] fe8b0b687d chore(sync): update Ambient model catalog 2026-07-14 14:54:47 +00:00
github-actions[bot] 80e891a596 chore(sync): update CrossModel model catalog 2026-07-14 14:54:43 +00:00
github-actions[bot] d61dc47fe4 chore(sync): update Vercel AI Gateway model catalog 2026-07-14 14:54:42 +00:00
github-actions[bot] 7a084fd495 chore(sync): update OpenRouter model catalog 2026-07-14 14:54:41 +00:00
David Knaack 779118c76d chore: move comments to top 2026-07-14 16:49:06 +02:00
David Knaack 8f3b8f72f0 chore: remove deprecated model and address review comments 2026-07-14 16:49:05 +02:00
David Knaack dc1260c4b9 chore: remove deprecated mistralai--mistral-large-instruct 2026-07-14 16:30:44 +02:00
David Knaack ee422deff9 chore: address review feedback 2026-07-14 16:11:41 +02:00
David Knaack 3b11700e11 fix: improve model definitions 2026-07-14 15:38:55 +02:00
David Knaack fb7af6b667 chore(sap-ai-core): add missing models 2026-07-14 15:07:15 +02:00
David Knaack b059b702b8 chore(sap-ai-core): mark retired models as deprecated 2026-07-14 15:07:15 +02:00
celeste1900 d6ef5792fc feat(ofox): add Ofox provider with 13 top-tier models 2026-07-14 18:22:28 +08:00
Prashanth-InferX 0000659c57 fix(inferx): update api endpoint to endpoints/v1 2026-07-13 22:25:30 -07:00
Aiden Cline a2087ac20f Merge pull request #3248 from Adam8234/agent/add-bedrock-gpt-5-6-models
feat(amazon-bedrock): add GPT-5.6 models
2026-07-13 20:20:35 -05:00
Adam 0656114326 fix(amazon-bedrock): use GA GPT-5.6 pricing 2026-07-13 16:32:06 -05:00
Adam b49a4959dc feat(amazon-bedrock): add GPT-5.6 models 2026-07-13 14:52:41 -05:00
Aiden Cline a0bcde206a Merge pull request #3245 from adriandlam/cloudflare-glm-5-2
feat(cloudflare-ai-gateway): add GLM 5.2
2026-07-13 14:15:19 -05:00
Adrian Lam cc3096f9fe feat(cloudflare-ai-gateway): add GLM 5.2 2026-07-13 12:28:33 -05:00
Aiden Cline a82eee57f1 Merge pull request #3229 from oskarkocol/chore/update-cerebras-zai-glm-47-pricing
chore(cerebras): update prices 20260713
2026-07-13 12:15:21 -05:00
Aiden Cline f0981b8e0c Merge pull request #3243 from rekram1-node/add-gpt-5-6-mainstream-providers
feat(providers): add GPT-5.6 hosted models
2026-07-13 11:31:08 -05:00
Aiden Cline e205675103 feat(providers): add GPT-5.6 hosted models 2026-07-13 11:28:26 -05:00
Aiden Cline e7391fee74 Merge pull request #3237 from vglafirov/add-gpt-5-6-gitlab
feat: add gitlab duo-chat-gpt-5.6 models (sol, terra, luna)
2026-07-13 11:05:51 -05:00
Aiden Cline 6fa1c663a8 Merge pull request #3206 from anomalyco/automation/sync-models-ambient
chore(sync): update Ambient model catalog
2026-07-13 09:47:38 -05:00
Aiden Cline 288fc15ffb fix(ambient): narrow GLM reasoning efforts 2026-07-13 09:31:19 -05:00
Aiden Cline 184e62b2ff fix(ambient): preserve authored reasoning options 2026-07-13 09:22:58 -05:00
Aiden Cline b1554e7b25 fix(ambient): add GLM 5.2 reasoning controls 2026-07-13 09:19:57 -05:00
Aiden Cline ada66871e8 Merge pull request #3234 from hujuncheng/fix/crossmodel-xai-vendor-mapping
fix(crossmodel): map x-ai vendor to xai author prefix
2026-07-13 09:17:27 -05:00
Aiden Cline 01462cb929 Merge pull request #3222 from anomalyco/automation/sync-models-vercel
chore(sync): update Vercel AI Gateway model catalog
2026-07-13 09:16:14 -05:00
Aiden Cline 3e69a442ff Merge pull request #3221 from anomalyco/automation/sync-models-empiriolabs
chore(sync): update EmpirioLabs AI model catalog
2026-07-13 09:15:52 -05:00
Aiden Cline b11f2273e2 Merge pull request #3225 from anomalyco/automation/sync-models-llmgateway
chore(sync): update LLM Gateway model catalog
2026-07-13 09:15:33 -05:00
Aiden Cline d714ac65fb Merge pull request #3226 from anomalyco/automation/sync-models-venice
chore(sync): update Venice model catalog
2026-07-13 09:15:25 -05:00
Aiden Cline 62b2b3da43 Merge pull request #3236 from anomalyco/automation/sync-models-crossmodel
chore(sync): update CrossModel model catalog
2026-07-13 09:14:24 -05:00
Aiden Cline e6caca99c8 Merge pull request #3227 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-13 09:14:08 -05:00
github-actions[bot] ae431b6535 chore(sync): update LLM Gateway model catalog 2026-07-13 13:57:44 +00:00
github-actions[bot] 4ade647a05 chore(sync): update OpenRouter model catalog 2026-07-13 13:57:43 +00:00
github-actions[bot] 4cc0676f65 chore(sync): update Ambient model catalog 2026-07-13 13:57:41 +00:00
github-actions[bot] 623d98c04f chore(sync): update EmpirioLabs AI model catalog 2026-07-13 13:57:41 +00:00
github-actions[bot] cbb3cc97eb chore(sync): update CrossModel model catalog 2026-07-13 13:57:39 +00:00
github-actions[bot] 0e706c9afa chore(sync): update Vercel AI Gateway model catalog 2026-07-13 13:57:36 +00:00
github-actions[bot] 8b25c58cec chore(sync): update Venice model catalog 2026-07-13 13:57:36 +00:00
Vladimir Glafirov e5be40b88b fix: use empty reasoning_options for gitlab gpt-5.6 models
The gitlab-ai-provider npm integration does not expose a reasoning
passthrough (see providers/gitlab/provider.toml), so advertising
reasoning_options caused opencode to inject reasoning_effort into
/v1/chat/completions requests. GPT-5.6 rejects reasoning_effort (unless
'none') when function tools are present on chat completions, producing a
400. Match the other duo-chat-gpt-5-* entries with reasoning_options = [].
2026-07-13 13:56:53 +00:00
Vladimir Glafirov 13da13087e feat: add gitlab duo-chat-gpt-5-6 models (sol, terra, luna) 2026-07-13 12:40:22 +00:00
hujuncheng ccb24d36ce fix(crossmodel): map x-ai vendor to xai author prefix
CrossModel serves xAI Grok models with vendor_code "x-ai" (e.g.
x-ai/grok-4.5). AUTHOR_BY_VENDOR had no "x-ai" entry, so deriveBaseModel
returned undefined and buildCrossModel skipped every Grok model — no
TOML was ever created under providers/crossmodel/models/xai. The base
models (models/xai/grok-4.5.toml, grok-4.3.toml, grok-build-0.1.toml)
already exist, so mapping "x-ai" -> "xai" lets the sync factor them.

Dry-run after the fix: 3 created (grok-4.5, grok-4.3, grok-build-0.1).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 19:11:53 +08:00
bull-of-narev[bot] 01aa0cdfab chore: update hardcoded LLM prices 2026-07-13 16:09:37 +07:00
Aiden Cline e1f1d82f41 Merge pull request #3212 from vishalveerareddy123/add-lynkr
Add Lynkr (self-hosted complexity-routing gateway)
2026-07-13 00:56:11 -05:00
Aiden Cline 8b8cd78663 Merge pull request #3102 from ericzheng316/dev
feat(provider): add EBCloud provider
2026-07-13 00:55:43 -05:00
Aiden Cline 12c9f299cd Merge pull request #1903 from lit26/add-step-3.7-flash
Add Step 3.7 Flash and StepFun Step Plan providers
2026-07-13 00:52:59 -05:00
Aiden Cline bbaff1dbd9 Merge pull request #3228 from anomalyco/automation/sync-models-crossmodel
chore(sync): update CrossModel model catalog
2026-07-13 00:43:31 -05:00
github-actions[bot] a3c968e9a4 chore(sync): update CrossModel model catalog 2026-07-13 05:26:57 +00:00
Boyu Zheng f2fcd1c329 fix(ebcloud): use integer square viewBox for logo 2026-07-13 09:59:02 +08:00
Aiden Cline 750c85633e Merge pull request #3224 from leszek3737/zenmux-gbt-5.6_grok-4.5
feat(zenmux): Add  OpenAI GPT-5.6 (Luna, Sol, Terra) and xAI Grok-4.5 models
2026-07-12 17:26:09 -05:00
Leszek f79cd8b647 feat(zenmux): Add OpenAI GPT-5.6 (Luna, Sol, Terra) and xAI Grok-4.5 models 2026-07-12 23:09:11 +02:00
Aiden Cline 14ea63d06c Merge pull request #3223 from anomalyco/fix/gpt-5-6-families
fix(openai): split GPT-5.6 model families
2026-07-12 15:52:47 -05:00
Aiden Cline 8ade7d8d24 fix(openai): split GPT-5.6 model families 2026-07-12 15:41:26 -05:00
Aiden Cline 3c3c09cfe0 Merge pull request #3199 from seven7763/codex/add-daoxe-provider
feat(daoxe): add DaoXE provider
2026-07-12 15:28:48 -05:00
Aiden Cline 04990b4e7d fix(daoxe): add standard reasoning efforts 2026-07-12 15:10:43 -05:00
Aiden Cline 4027cf3610 Merge pull request #3198 from andrelandgraf/neon-gateway-clean-paths
fix(neon): use cleaned-up AI Gateway paths (/v1, /openai/v1)
2026-07-12 14:58:31 -05:00
Aiden Cline 5885a6e726 Merge pull request #3091 from eliteprox/feat/add-blueclaw-provider
feat(blueclaw): add Blue Claw provider
2026-07-12 14:56:37 -05:00
Aiden Cline 324e7f0de6 fix(neon): retain documented responses path 2026-07-12 13:31:04 -05:00
Aiden Cline aac99b72e1 fix(daoxe): align current gateway metadata 2026-07-12 13:30:48 -05:00
Aiden Cline 524524e488 fix(ebcloud): correct converted pricing 2026-07-12 13:30:17 -05:00
Aiden Cline fdddf34d92 fix(blueclaw): remove unverified reasoning toggles 2026-07-12 13:30:05 -05:00
Aiden Cline 867fd31dc0 Merge pull request #3209 from airouter-dev/add-ai-router-provider-source-backed
feat: add AI-ROUTER provider
2026-07-12 13:21:50 -05:00
Aiden Cline bf55e760ac Merge pull request #3220 from KTibow/chore/remove-wafer-qwen
chore: remove Qwen3.5-397B-A17B from wafer.ai provider
2026-07-12 11:49:47 -05:00
Aiden Cline a5e419dacf Merge pull request #3208 from Adam-Dalloul/add-mistral-canonical-mappings
Map mistral-small-4 and mistral-medium-3 to canonical base models
2026-07-12 11:49:25 -05:00
Aiden Cline c67e12e135 Merge pull request #3207 from anomalyco/automation/sync-models-empiriolabs
chore(sync): update EmpirioLabs AI model catalog
2026-07-12 11:49:11 -05:00
Aiden Cline 51a36c8398 Merge pull request #3140 from lioZ129/feature/add-hpc-ai-provider
add new model support
2026-07-12 11:48:49 -05:00
Aiden Cline 6a6acfb4b1 fix: correct HPC-AI model metadata 2026-07-12 11:45:23 -05:00
KTibow e793b58791 chore: remove Qwen3.5-397B-A17B from wafer.ai provider
The model exists at https://pass.wafer.ai/v1/models but has no wafer
metadata (no display_name, description, tier, capabilities, or pricing).
It is a raw pass-through without authoritative catalog data.

Generated by GLM-5.2 with human oversight.
2026-07-12 09:35:30 -07:00
github-actions[bot] 44cb2a2b2d chore(sync): update EmpirioLabs AI model catalog 2026-07-12 16:34:03 +00:00
Aiden Cline cecf31aa5b Merge pull request #3211 from anomalyco/automation/sync-models-venice
chore(sync): update Venice model catalog
2026-07-12 11:23:43 -05:00
Aiden Cline 83d23e7fbd Merge pull request #3214 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-12 11:23:30 -05:00
Aiden Cline 50bb0a0631 Merge pull request #3215 from anomalyco/automation/sync-models-vercel
chore(sync): update Vercel AI Gateway model catalog
2026-07-12 11:22:47 -05:00
Aiden Cline e61cfe4098 Merge pull request #3216 from fanweixiao/dev
feat(vivgrid): add gpt-5.6 family models
2026-07-12 11:22:22 -05:00
Aiden Cline e191ef168d Merge pull request #3217 from anomalyco/automation/sync-models-deepinfra
chore(sync): update Deep Infra model catalog
2026-07-12 11:22:06 -05:00
Aiden Cline 4a665d0b3a Merge pull request #2912 from NielsAI/feat/google-vertex-gemini-image-models
feat(google-vertex): add non-preview Gemini image models
2026-07-12 11:21:53 -05:00
github-actions[bot] 64cd156a32 chore(sync): update Venice model catalog 2026-07-12 15:37:15 +00:00
github-actions[bot] 275ae965fb chore(sync): update Deep Infra model catalog 2026-07-12 15:37:14 +00:00
github-actions[bot] d27836b6d5 chore(sync): update Vercel AI Gateway model catalog 2026-07-12 15:37:12 +00:00
github-actions[bot] cb68b9263b chore(sync): update OpenRouter model catalog 2026-07-12 15:37:11 +00:00
C.C. Fan 1652c012ac feat(vivgrid): add gpt-5.6 family models 2026-07-12 10:25:23 +08:00
Aiden Cline e6fae89eb8 fix(models): correct Nano Banana metadata 2026-07-11 17:59:47 -05:00
Aiden Cline fe9a8fcb4a Merge dev into feat/google-vertex-gemini-image-models 2026-07-11 17:50:35 -05:00
Aiden Cline 7bec16398e refactor: reuse stable Gemini image metadata 2026-07-11 17:49:33 -05:00
Aiden Cline 0b877eb3c0 feat(models): add stable Gemini image metadata 2026-07-11 17:44:09 -05:00
Vishal Veera Reddy 84bd139dc5 lynkr-auto: family=auto, top-of-file rationale with citations 2026-07-11 15:42:33 -07:00
Vishal Veera Reddy 9397edde73 Use currentColor in Lynkr logo 2026-07-11 15:42:32 -07:00
Aiden Cline f87e902b3b fix(google-vertex): add required model descriptions 2026-07-11 17:40:40 -05:00
Aiden Cline 668a1c4360 fix(google-vertex): correct Gemini image metadata 2026-07-11 17:39:37 -05:00
Vishal Veera Reddy b9d58009d8 Add Lynkr logo 2026-07-11 14:44:24 -07:00
Vishal Veera Reddy d8f677ad47 Add Lynkr auto-routing model 2026-07-11 14:44:23 -07:00
Vishal Veera Reddy 5bf1080088 Add Lynkr provider 2026-07-11 14:44:22 -07:00
User 5806a94836 feat: add AI-ROUTER provider 2026-07-12 04:16:32 +08:00
Aiden Cline 66dcd837fe Merge pull request #3203 from aegroto/chore/waferai_update
Updated wafer.ai models
2026-07-11 15:11:29 -05:00
Aiden Cline f08df784b5 fix: correct Wafer model metadata 2026-07-11 13:53:50 -05:00
Adam Dalloul b875d58989 feat(empiriolabs): map mistral-small-4 and mistral-medium-3 to canonical base models 2026-07-11 11:51:08 -07:00
Aiden Cline ec996a0c4a Merge pull request #2141 from Prashanth-InferX/patch-1
Add InferX provider (OpenAI-compatible endpoints)
2026-07-11 13:36:01 -05:00
Aiden Cline 4445552c8a fix(inferx): clean up model metadata 2026-07-11 13:30:44 -05:00
Aiden Cline cfce596e3c Merge pull request #3202 from ambient-gregory/ambient-catalog-sync
feat(ambient): sync model catalog from API
2026-07-11 13:21:09 -05:00
Aiden Cline 774468a7a7 Merge pull request #3197 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-11 13:16:32 -05:00
Aiden Cline b4b18ced31 Merge pull request #3205 from anomalyco/automation/sync-models-empiriolabs
chore(sync): update EmpirioLabs AI model catalog
2026-07-11 13:16:20 -05:00
Aiden Cline 18f001fba0 Merge pull request #3204 from anomalyco/automation/sync-models-llmgateway
chore(sync): update LLM Gateway model catalog
2026-07-11 13:13:01 -05:00
github-actions[bot] f1e7b994a0 chore(sync): update EmpirioLabs AI model catalog 2026-07-11 17:36:55 +00:00
github-actions[bot] c059edc1a4 chore(sync): update LLM Gateway model catalog 2026-07-11 17:36:55 +00:00
github-actions[bot] 6e87b3d24c chore(sync): update OpenRouter model catalog 2026-07-11 17:36:54 +00:00
aegroto 2e09cb410f chore: more revisions 2026-07-11 14:13:13 +02:00
aegroto fa41065a7d fix: fixed review issue 2026-07-11 14:04:02 +02:00
aegroto ec47f923cb chore: update wafer providers 2026-07-11 13:48:02 +02:00
Gregory ee07b91591 feat(ambient): sync model catalog from API
Add an Ambient sync provider that maps the OpenRouter-shaped catalog through the
shared builder. Skip catalog entries with is_ready=false so only served models
are generated, and set deleteMissing=false with skipped/missing notices so a
transient catalog omission retains local files instead of deleting them. Emit
reasoning_options = [] for reasoning models, since Ambient exposes no reasoning
control, rather than silently inheriting the base model's options.
2026-07-11 13:38:19 +02:00
seven7763 cd2f6ac132 feat(daoxe): add DaoXE provider 2026-07-11 14:10:11 +08:00
Andre Landgraf 8613f07b5f fix(neon): use cleaned-up AI Gateway paths (/v1, /openai/v1)
The Neon AI Gateway now exposes tidier routes: chat completions for all
models at `/v1/chat/completions` and the OpenAI Responses API at
`/openai/v1/responses`. Point the provider base URL and the GPT-5 responses
overrides at the new bases (`${NEON_AI_GATEWAY_BASE_URL}/v1` and
`${NEON_AI_GATEWAY_BASE_URL}/openai/v1`) instead of the old
`/ai-gateway/mlflow/v1` and `/ai-gateway/openai/v1` prefixes.
2026-07-10 22:35:40 -07:00
Tianning Li 0c3e1b3203 fix(stepfun-ai-step-plan): use platform.stepfun.ai/en doc links
Global step-plan model docs now point to the .ai/en guides instead of the
China .com/zh pages. Links verified live.
2026-07-11 13:26:00 +08:00
Tianning Li 6cbc76a67e Merge branch 'add-step-3.7-flash' of https://github.com/lit26/models.dev into add-step-3.7-flash 2026-07-11 13:12:56 +08:00
Tianning Li 79c868244e fix(stepfun-step-plan): align reasoning metadata with direct API
Add [interleaved] reasoning_content field to all step-plan model files
and normalize to multi-line TOML form matching the direct-API providers.
Step-plan comment omits the Responses endpoint clause (no plan Responses
endpoint per provider docs).
2026-07-11 13:11:45 +08:00
Tianning Li 6111f36aa7 Merge remote-tracking branch 'upstream/dev' into add-step-3.7-flash
# Conflicts:
#	models/stepfun/step-3.7-flash.toml
2026-07-11 12:59:51 +08:00
Aiden Cline 5e9e9ac0bb Merge pull request #3195 from anomalyco/automation/sync-models-vercel
chore(sync): update Vercel AI Gateway model catalog
2026-07-10 21:45:16 -05:00
Aiden Cline 41cf5aaf1e Merge pull request #3196 from lilly-luo/add-databricks-kimi-k2-7-code-glm-5-2
Add databricks-kimi-k2-7-code and databricks-glm-5-2 models
2026-07-10 21:44:54 -05:00
Lilly c15ccd0a77 Add databricks-kimi-k2-7-code and databricks-glm-5-2 models 2026-07-11 02:28:00 +00:00
github-actions[bot] 9d36c852d3 chore(sync): update Vercel AI Gateway model catalog 2026-07-11 01:56:41 +00:00
Aiden Cline 04ae13714e Merge pull request #3189 from anomalyco/automation/sync-models-llmgateway
chore(sync): update LLM Gateway model catalog
2026-07-10 19:01:27 -05:00
Aiden Cline 8bfa558700 fix(llmgateway): add Muse Spark reasoning efforts 2026-07-10 18:49:49 -05:00
Aiden Cline 66acdcc034 Merge pull request #3193 from anomalyco/automation/sync-models-vercel
chore(sync): update Vercel AI Gateway model catalog
2026-07-10 18:42:18 -05:00
Aiden Cline a909f61275 fix(vercel): add GPT-Realtime-2.1 reasoning efforts 2026-07-10 18:37:04 -05:00
github-actions[bot] f8b382bb01 chore(sync): update LLM Gateway model catalog 2026-07-10 23:35:29 +00:00
github-actions[bot] 98975461b7 chore(sync): update Vercel AI Gateway model catalog 2026-07-10 23:35:28 +00:00
Aiden Cline c322362a0f Merge pull request #2898 from samrathreddy/feat/add-pioneer-provider
feat: add Pioneer as inference provider
2026-07-10 15:30:46 -05:00
Samrath ca61e9ea27 Merge remote-tracking branch 'origin/dev' into feat/add-pioneer-provider
# Conflicts:
#	packages/core/src/sync/index.ts
2026-07-11 01:31:00 +05:30
Samrath ac05c4ea01 fix: add Pioneer reasoning metadata 2026-07-11 01:29:46 +05:30
Aiden Cline f74e16edcd Merge pull request #3188 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-10 14:32:27 -05:00
Aiden Cline 5a21c5d14e Merge pull request #3192 from rekram1-node/feat/openai-gpt-realtime-2-1
feat(openai): add GPT-Realtime-2.1
2026-07-10 14:32:05 -05:00
Samrath 71ce8da88e fix: generate Pioneer base model mappings 2026-07-11 00:55:05 +05:30
Aiden Cline 6af0231ae6 feat(openai): add GPT-Realtime-2.1 2026-07-10 14:20:39 -05:00
Aiden Cline 01e5ea975e Merge pull request #2707 from Adam-Dalloul/add-empiriolabs-provider-2
Add EmpirioLabs AI provider with hourly sync
2026-07-10 14:13:49 -05:00
Aiden Cline a08b39d342 fix(empiriolabs): harden model sync 2026-07-10 13:59:04 -05:00
Aiden Cline 929864004e Merge pull request #3161 from 0-don/feat/add-unorouter-provider
feat(unorouter): add UnoRouter provider
2026-07-10 13:56:00 -05:00
Aiden Cline 5dd5de679e Merge remote-tracking branch 'origin/dev' into fix/pr-2707
# Conflicts:
#	packages/core/src/sync/index.ts
2026-07-10 13:53:30 -05:00
github-actions[bot] c3a6f74ec1 chore(sync): update OpenRouter model catalog 2026-07-10 18:46:32 +00:00
Frank 83ffebbca7 update zen models 2026-07-10 13:48:32 -04:00
Adam 084f3e1684 add sourced benchmark results for frontier models 2026-07-10 12:08:10 -05:00
Aiden Cline 0c9b542198 Merge pull request #3185 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-10 11:51:33 -05:00
Aiden Cline 16860bca59 Merge pull request #2725 from sorenjuul/add-abacus-models
feat(abacus): add new provider model configurations
2026-07-10 11:50:46 -05:00
Aiden Cline 64fed1b223 fix(abacus): omit inherited GPT input limits 2026-07-10 11:49:53 -05:00
github-actions[bot] 50cbd2d6a8 chore(sync): update OpenRouter model catalog 2026-07-10 16:04:14 +00:00
Frank d647ededd7 update zen models 2026-07-10 11:37:15 -04:00
Aiden Cline c106790181 Merge pull request #3147 from anomalyco/fix/digitalocean-catalog-sync
fix(sync): use DigitalOcean model catalog
2026-07-10 10:35:04 -05:00
Aiden Cline 56223fd8fc Merge pull request #2997 from levdad/add-kilo-sync
feat(sync): add kilo provider
2026-07-10 10:34:41 -05:00
Aiden Cline 67c29c1b6d Merge branch 'dev' into add-kilo-sync 2026-07-10 10:33:47 -05:00
Aiden Cline d98f3e9c5b Merge pull request #3146 from rakshith1928/cleanup/nvidia-deprecated-kimi-k2.6-july-07
chore(nvidia): mark kimi-k2.6 and kimi-k2-instruct-0905 as deprecated
2026-07-10 10:29:50 -05:00
Aiden Cline cd33292c13 Merge pull request #3099 from cjcole8/add-model-oracle-ai
Add Model Oracle AI provider
2026-07-10 10:29:22 -05:00
Aiden Cline 29341789a2 Merge pull request #3175 from satvikxs/routing-run-gpt-5.6
routing.run: add gpt-5.6 sol/terra/luna
2026-07-10 10:27:25 -05:00
Aiden Cline 80980b03b2 Merge pull request #3182 from anomalyco/automation/sync-models-llmgateway
chore(sync): update LLM Gateway model catalog
2026-07-10 10:22:48 -05:00
Aiden Cline 4a689a763a Merge pull request #3184 from anomalyco/automation/sync-models-venice
chore(sync): update Venice model catalog
2026-07-10 10:22:16 -05:00
Aiden Cline 2f6da2e76d Merge pull request #3172 from anomalyco/automation/sync-models-openrouter
chore(sync): update OpenRouter model catalog
2026-07-10 10:22:05 -05:00
Aiden Cline 522c7cf328 Merge pull request #3180 from petrroll/fix/github-copilot-long-context
fix(github-copilot): correct long-context metadata
2026-07-10 10:21:38 -05:00
Aiden Cline f583ccd394 Merge pull request #3178 from petrroll/feat/github-copilot-gpt-5.6-models
feat(github-copilot): add GPT-5.6 models
2026-07-10 10:12:09 -05:00
github-actions[bot] c79e5e123a chore(sync): update OpenRouter model catalog 2026-07-10 15:10:44 +00:00
github-actions[bot] 115070da57 chore(sync): update LLM Gateway model catalog 2026-07-10 15:10:43 +00:00
github-actions[bot] a72d46bebb chore(sync): update Venice model catalog 2026-07-10 15:10:42 +00:00
Soren Juul 0004993aa6 fix(abacus): keep reasoning=true consistently for base-reasoning models without RouteLLM thinking control 2026-07-10 16:06:20 +02:00
Soren Juul c7bdba27d4 fix(abacus): keep reasoning=true from base model when RouteLLM lacks thinking control 2026-07-10 15:52:07 +02:00
Petr Houška d637169c29 feat(github-copilot): add GPT-5.6 models 2026-07-10 13:03:57 +00:00
Petr Houška da30cb58de fix(github-copilot): correct long-context metadata 2026-07-10 13:03:05 +00:00
0-don 25672f0ba7 Revert "unorouter: mirror base models' reasoning_options instead of empty arrays"
This reverts commit 4198dedd57.
2026-07-10 15:01:44 +02:00
Soren Juul b0dc8d57b1 fix(abacus): set reasoning=false for IDs where RouteLLM reports no thinking 2026-07-10 14:55:03 +02:00
Soren Juul 0aeb457b97 fix(abacus): cite RouteLLM cached_input_token_rate and verify reasoning flags 2026-07-10 14:47:33 +02:00
Soren Juul d0a1ad416d fix(abacus): set reasoning = false for IDs without RouteLLM thinking field 2026-07-10 14:30:57 +02:00
Soren Juul 53150a1e70 fix(abacus): apply thinking-field reasoning standard and cite remaining models
- Set reasoning = false for GLM-4.5, GLM-4.7, GLM-5, GLM-5.1,
  MiniMax-M3, gemma-4-31b-it, Qwen3.6-27B, and
  gemini-3.1-flash-image-preview because RouteLLM /v1/models does not
  report thinking: true for those IDs.
- Add leading RouteLLM API citation blocks to the ~19 new/updated model
  files that lacked them, mapping input/output modalities, limits,
  token rates, and the thinking field where present.
2026-07-10 14:24:45 +02:00
Soren Juul 60b092f08e fix(abacus): verify reasoning flags and map citations to RouteLLM fields
- Restore reasoning = false for GLM-4.6, GLM-5.2, and MiniMax-M2.7
  because the RouteLLM /v1/models descriptions for those IDs do not
  indicate reasoning emission.
- Replace bare source URLs with explicit claim mappings: each cited
  TOML now lists the RouteLLM API field values (context_length,
  max_completion_tokens, input_modalities, output_modalities, token
  rates, cached_input_token_rate, thinking) that justify the override.
2026-07-10 14:09:34 +02:00
Soren Juul dbb325e7ab docs(abacus): add RouteLLM API source citations to divergent overrides
Add a leading source comment to provider TOMLs whose cost, limit,
modalities, or reasoning flags diverge from the upstream base-model
metadata. All cited values are confirmed against the RouteLLM model
list at https://routellm.abacus.ai/v1/models.
2026-07-10 13:56:48 +02:00
mightbesatvik 7caae4cdd1 routing.run: add gpt-5.6 sol/terra/luna
routing.run now serves the three GPT-5.6 tiers on its OpenAI-compatible
endpoint. Each inherits the openai/gpt-5.6-<tier> base metadata (reasoning,
tool_call, vision, structured output) and overrides with routing.run's list
pricing from GET /v1/models plus a 1M context window. reasoning_options = []
with interleaved reasoning_content, matching the rest of the provider (no
request-side reasoning toggle on the compat surface).

Verified: bun validate passes; live 200 on bare ids via
api.routing.run/v1/chat/completions.
2026-07-10 17:05:58 +05:30
Soren Juul a62ceff48b fix(abacus): align gpt-oss-120b reasoning_options with provider audit
Revert reasoning_options to [] for openai/gpt-oss-120b. The Abacus
provider.toml audit explicitly states the RouteLLM API documents no
reasoning toggle, effort, or numeric budget request field.
2026-07-10 12:45:47 +02:00
Soren Juul f928b66bdd fix(abacus): remove Qwen case collision and restore gpt-oss reasoning effort
- Delete lowercase qwen3-coder-480b-a35b-instruct.toml so it no longer
  shadows the uppercase base_model variant (Bun resolves TOML imports
  case-insensitively).
- Restore reasoning_options effort control for openai/gpt-oss-120b;
  OpenAI documents low/medium/high reasoning effort for this model and
  RouteLLM's OpenAI-compatible API exposes it.
2026-07-10 12:24:56 +02:00
Soren Juul 7b46d372a1 fix(abacus): correct inherited reasoning flags and limit overrides
- Add base_model_omit = ["limit.input"] to gpt-5.4 so the inherited
  922K input cap does not exceed the 400K context window.
- Replace reasoning = false with reasoning_options = [] on base-model
  overrides that inherit reasoning = true from model metadata.
- Remove duplicate lowercase GLM TOMLs that shadowed the uppercase
  variants due to Bun's case-insensitive TOML import resolution.
2026-07-10 12:10:05 +02:00
Soren Juul a55627183d fix(abacus): Updated and added missing models from the RouteLLM abacus API 2026-07-10 11:31:49 +02:00
0-don 4198dedd57 unorouter: mirror base models' reasoning_options instead of empty arrays 2026-07-10 10:33:51 +02:00
0-don 174a76c3a0 fix(unorouter): drop fixed size from logo, square viewBox only 2026-07-10 10:32:57 +02:00
0-don 4c8a937d43 fix(unorouter): use currentColor in logo per guidelines 2026-07-10 10:32:57 +02:00
0-don 2995194f70 feat(unorouter): add UnoRouter provider 2026-07-10 10:32:57 +02:00
lioZ129 b9b230fbf4 update models' config 2026-07-10 11:25:18 +08:00
Boyu Zheng 7baf2c0970 uploaded a help document 2026-07-10 11:17:37 +08:00
Boyu Zheng f5fe2210c8 fix(ebcloud): drop unverified reasoning cost, add interleaved reasoning_content, cleanup
Addresses second review pass on PR #3102:
- Remove cost.reasoning (reasoning tokens bill as normal output tokens,
  no separate free/paid line item, matching repo convention)
- Add [interleaved] field = "reasoning_content" to all four models,
  since EBCloud's endpoint returns reasoning via that field
- Document the reasoning-control investigation in provider.toml
  (no verified effort/budget/toggle param found)
- Strip trailing whitespace, add trailing newline to provider.toml
- Normalize logo.svg viewBox to a 0 0 N N origin
2026-07-10 10:48:45 +08:00
Boyu Zheng 6e4a1e55d8 fix(ebcloud): use base_model inheritance and currentColor logo
Address review feedback on PR #3102: inherit provider-agnostic model
facts via base_model instead of duplicating them (fixes fabricated
dates, wrong temperature/limit overrides, and the DeepSeek-V4-Pro
copy-pasted description), switch logo fills to currentColor, and
correct GLM-5.1/Kimi-K2.6 pricing which had wrongly copied
DeepSeek-V4-Flash's rate.
2026-07-10 10:38:46 +08:00
Boyu Zheng 941d97c41d feat(ebcloud): add provider logo 2026-07-10 10:08:06 +08:00
Aiden Cline ba975a9e6f fix(sync): harden DigitalOcean catalog parsing 2026-07-09 12:42:30 -05:00
Aiden Cline 14431d5d10 fix(sync): use DigitalOcean model catalog 2026-07-09 11:50:02 -05:00
rakshith1928 56bf6e9760 mark nvidia's kimi-k2-instruct model as deprecated 2026-07-09 21:21:51 +05:30
rakshith1928 6fbd2950ea chore(nvidia): mark kimi-k2.6 as deprecated 2026-07-09 20:58:31 +05:30
Tianning Li 4c419b3a94 Merge branch 'anomalyco:dev' into add-step-3.7-flash 2026-07-09 17:52:19 +08:00
Tianning Li 85b0c61825 fix(stepfun): apply PR review non-blocking fixes
- Move video modality to base model step-3.7-flash; drop redundant
  per-provider [modalities] overrides (all 4 providers inherit video)
- Add # Reasoning HTTP format comment to both step-plan provider.toml
- Move reasoning-effort comments to top of model TOMLs for sync safety
- Logo cleanup: drop root fill=none, clipPath rect fill; add trailing newline
2026-07-09 17:48:07 +08:00
Tianning Li fa5d89ef86 fix(stepfun-step-plan): align step-3.5-flash effort and drop router reasoning
step-3.5-flash on both step-plan providers now declares effort low/high,
matching the stepfun/stepfun-ai variants and its own 2603 snapshot. Step
Router v1 is a dispatcher, not a reasoning model (per StepFun docs), so
reasoning=false.
2026-07-09 17:20:43 +08:00
Tianning Li d97ea65eb2 fix(stepfun): reconcile reasoning_options with documented effort support
Step 1/Step 2 are legacy chat models, not reasoning models, so drop the
placeholder reasoning=true/reasoning_options=[]. Give step-3.5-flash the
effort low/high options its 2603 snapshot already declares, matching the
provider reasoning-HTTP-format comment. Symlinked into stepfun-ai.
2026-07-09 17:10:01 +08:00
lioZ129 0b27b2f87d add new model support 2026-07-09 16:53:11 +08:00
eliteprox c777f40587 fix(blueclaw): mark models as beta
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 17:57:19 -04:00
eliteprox 02c592bd8c fix(blueclaw): replace embedded PNG logo with vector currentColor SVG
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 17:41:33 -04:00
Boyu Zheng b96653aa5c fix(ebcloud): correct copy-pasted model descriptions for GLM-5.1 and Kimi-K2.6 2026-07-08 17:22:08 +08:00
Boyu Zheng 128398d56b feat(provider): add EBCloud provider and Models: DeepSeek-v4-flash, pro, GLM and Kimi. 2026-07-08 16:49:17 +08:00
cjcole8 c1e0d97149 Add Model Oracle AI provider 2026-07-07 21:34:45 -06:00
Samrath b296e9819a Merge remote-tracking branch 'origin/dev' into feat/add-pioneer-provider
# Conflicts:
#	packages/core/src/sync/index.ts
2026-07-08 00:02:14 +05:30
eliteprox 4628979d6b fix(blueclaw): address review feedback
- add provider logo
- factor both Qwen models through canonical alibaba base_model
- declare explicit reasoning_options (toggle)
- drop limit.output copied from combined context; inherit base value

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 11:42:18 -04:00
Levi Hadad 4d8931d4af Merge branch 'dev' into add-kilo-sync 2026-07-07 15:12:42 +03:00
Tianning Li 2cd05cd265 Merge branch 'anomalyco:dev' into add-step-3.7-flash 2026-07-07 11:21:40 +08:00
Tianning Li c3ede089ed Merge remote-tracking branch 'upstream/dev' into add-step-3.7-flash
# Conflicts:
#	providers/stepfun-ai/models/step-3.7-flash.toml
#	providers/stepfun-ai/models/step-3.7-flash.toml~HEAD
2026-07-03 14:40:25 +08:00
KaiserBloo 69b443858a Add ClinePass reasoning options 2026-07-03 02:02:27 +01:00
Levi Hadad f9e613dcb3 docs(sync): document xai sync command 2026-07-02 17:40:56 +03:00
Levi Hadad eb02a4d5fb feat(sync): add kilo provider
Implement the Kilo Gateway sync provider to fetch and synchronize model
metadata.

- Add `kilo` provider implementation
- Add `kilo:sync` script to `package.json`
- Update CI workflow to include `KILO_API_KEY`
- Add `kilo` to the `aggregators` group
- Update `sync.md` documentation
2026-07-02 17:31:56 +03:00
Adam Dalloul c11840c407 Merge remote-tracking branch 'upstream/dev' into add-empiriolabs-provider-2
# Conflicts:
#	packages/core/src/sync/index.ts
2026-06-30 12:56:02 -07:00
KaiserBloo a820277894 Add ClinePass provider 2026-06-30 19:56:12 +01:00
Tianning Li 996ad32904 Merge remote-tracking branch 'upstream/dev' into add-step-3.7-flash
# Conflicts:
#	providers/stepfun/models/step-3.7-flash.toml
2026-07-01 00:32:58 +08:00
Samrath af4e0adee1 Merge remote-tracking branch 'origin/dev' into feat/add-pioneer-provider
# Conflicts:
#	packages/core/src/sync/index.ts
2026-06-30 16:45:37 +05:30
Samrath d099e824ac chore(sync): add Pioneer model sync 2026-06-30 16:40:39 +05:30
Niels van Beuningen e487ef96d3 Updated base models and added more propper metadata 2026-06-29 16:06:37 +02:00
Niels van Beuningen 70025d73bb Added non-preview vertex gemini image models 2026-06-29 12:19:51 +02:00
Tianning Li 57e8b1acfa fix(stepfun-ai): update reasoning HTTP format access date and clarify comments 2026-06-29 17:02:23 +08:00
Tianning Li c9a85bac60 fix(stepfun-ai): restore reasoning HTTP format comments
Merge resolution dropped the reasoning-format documentation comments
from stepfun-ai/provider.toml. Restore them (mirroring the China
stepfun/provider.toml block, adapted to the global .ai /v1 endpoints)
per reviewer request on PR #1903.
2026-06-29 16:57:48 +08:00
Samrath 65f7b05891 fix: add reasoning_options to gpt-5.4/5.5/5.4-nano pioneer models
These use base_model_omit alongside base_model, so the previous fix pass
missed them.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 11:35:01 +05:30
Samrath 6093568196 fix: add reasoning_options = [] to all pioneer base_model TOMLs with reasoning
Canonical models that have reasoning = true don't include reasoning_options,
so pioneer TOMLs using base_model need to explicitly set it to satisfy the
validator requirement.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 11:32:56 +05:30
Samrath cf2d9c134f fix: use base_model references for pioneer models with known canonical models
Converts 8 full-definition pioneer models to inherit correct output limits
and capabilities from their canonical base models instead of defaulting to
the incorrect output = 4_096.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 11:22:07 +05:30
Samrath c2fb688fe8 fix(pioneer): add reasoning_options to reasoning models
Adds reasoning_options = [] to full-definition models with reasoning = true
(pioneer/auto, mistral-medium-3.5, Qwen3-8B, gpt-oss-120b, gpt-oss-20b).
Pioneer abstracts reasoning controls so no effort/toggle options are exposed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 04:51:00 +05:30
Samrath b868e9c479 feat(pioneer): expand model catalog and fix pricing
- Add 28 new models from Pioneer API (Qwen3, Gemini, GPT-5, Mistral, Nvidia, etc.)
- Add pioneer/auto routing model
- Update pricing and context windows on 47 existing models from /base-models API

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 04:21:42 +05:30
Tianning Li 8eeea3e02a fix(stepfun): restore China step-3.7-flash cost and add video modality 2026-06-28 23:50:05 +08:00
Tianning Li 5f00eb57d1 Merge branch 'dev' of https://github.com/anomalyco/models.dev into add-step-3.7-flash
# Conflicts:
#	providers/stepfun-ai/provider.toml
#	providers/stepfun/models/step-3.7-flash.toml
2026-06-28 23:47:43 +08:00
Adam Dalloul 628d9e3170 Improve EmpirioLabs canonical sync coverage 2026-06-26 11:33:19 -07:00
Adam Dalloul f15087d8ed Fix EmpirioLabs model sync metadata 2026-06-26 10:07:32 -07:00
John | Elite Encoder c252d86a33 feat(blueclaw): add Blue Claw provider 2026-06-24 19:38:14 -04:00
Tianning Li 7463396925 Merge branch 'anomalyco:dev' into add-step-3.7-flash 2026-06-22 12:51:44 +08:00
Adam Dalloul a84c8d86e6 Add EmpirioLabs AI provider with hourly sync 2026-06-21 05:47:46 +00:00
Tianning Li ca216d4aa0 Merge branch 'anomalyco:dev' into add-step-3.7-flash 2026-06-18 21:32:38 +08:00
Tianning Li c74a7d5540 Merge branch 'anomalyco:dev' into add-step-3.7-flash 2026-06-17 00:06:34 +08:00
Tianning Li b5bec57ebd Merge branch 'anomalyco:dev' into add-step-3.7-flash 2026-06-15 23:33:23 +08:00
Tianning Li f55836ab46 refactor(stepfun): use base_model inheritance for step provider models
- Collapse stepfun/stepfun-ai/*-step-plan model files to base_model refs
- Add reasoning_options (effort levels) per model
- Add benchmarks and update knowledge date on base step-3.7-flash
- Normalize logo.svg viewBox
2026-06-15 01:59:10 +08:00
Tianning Li 8831574def Merge branch 'dev' into add-step-3.7-flash 2026-06-15 00:08:13 +08:00
Prashanth-InferX e03f2e3d38 Update qwen3.6-35b-a3b-fp8.toml 2026-06-14 06:46:27 -07:00
Prashanth-InferX 49bcef0721 Update qwen3.6-27b-fp8.toml 2026-06-14 06:46:02 -07:00
Prashanth-InferX 1b89542222 Update qwen3.5-122b-a10b-nvfp4.toml 2026-06-14 06:45:35 -07:00
Prashanth-InferX b64eb07ba9 Update qwen3-coder-next-fp8.toml 2026-06-14 06:39:20 -07:00
Prashanth-InferX 3c7a10cd70 Update qwen3-coder-next-fp8-1m.toml 2026-06-14 06:39:00 -07:00
Prashanth-InferX cb70234277 Update qwen3-coder-next-fp8-1m.toml 2026-06-14 06:35:37 -07:00
Prashanth-InferX ae015bbecb Update qwen3-coder-next-fp8.toml 2026-06-14 06:35:15 -07:00
Prashanth-InferX 7422d6fa48 Update qwen3-coder-next-fp8.toml 2026-06-14 06:32:33 -07:00
Prashanth-InferX 21585db20a Update qwen3-coder-next-fp8-1m.toml 2026-06-14 06:32:14 -07:00
Prashanth-InferX d6e0eabbf8 Update qwen3-coder-next-fp8-1m.toml 2026-06-14 06:28:21 -07:00
Prashanth-InferX 175bd75389 Update qwen3-coder-next-fp8.toml 2026-06-14 06:27:59 -07:00
Prashanth-InferX fb8f07534e Update qwen3-coder-next-fp8.toml 2026-06-14 06:24:09 -07:00
Prashanth-InferX 4b50b0d338 Update qwen3-coder-next-fp8-1m.toml 2026-06-14 06:23:06 -07:00
Prashanth-InferX 0b04d0f2af Update logo.svg 2026-06-14 06:14:02 -07:00
Prashanth-InferX 3b3933f8f8 Update logo.svg 2026-06-14 06:03:47 -07:00
Prashanth-InferX c51394cdd7 Update qwen3.6-35b-a3b-fp8.toml 2026-06-14 05:45:11 -07:00
Prashanth-InferX aecda0251e Update qwen3.6-27b-fp8.toml 2026-06-14 05:44:33 -07:00
Prashanth-InferX 748df5f980 Update qwen3.5-122b-a10b-nvfp4.toml 2026-06-14 05:43:47 -07:00
Tianning Li 3763be6988 Merge branch 'anomalyco:dev' into add-step-3.7-flash 2026-06-14 00:06:31 +08:00
Prashanth-InferX 543f159a1c Update gemma-4-31b-it-fp8.toml 2026-06-12 03:30:19 -07:00
Tianning Li 054da7d81c Merge branch 'anomalyco:dev' into add-step-3.7-flash 2026-06-12 14:57:34 +08:00
Prashanth-InferX ce1b441a48 Update gemma-4-31b-it-fp8.toml 2026-06-11 18:22:03 -07:00
Prashanth-InferX cbb3c1e732 Update logo.svg 2026-06-11 18:03:54 -07:00
Prashanth-InferX d5303fb7ee Update qwen3.5-122b-a10b-nvfp4.toml 2026-06-11 17:46:25 -07:00
Prashanth-InferX af3941c5c1 Update qwen3.6-27b-fp8.toml 2026-06-11 17:46:07 -07:00
Prashanth-InferX 25d8516199 Update qwen3.6-35b-a3b-fp8.toml 2026-06-11 17:45:26 -07:00
Prashanth-InferX d5d3180917 Update qwen3.6-27b-fp8.toml 2026-06-11 17:43:19 -07:00
Prashanth-InferX 02b5429e9b Update qwen3.5-122b-a10b-nvfp4.toml 2026-06-11 17:42:22 -07:00
Prashanth-InferX 48b820c9fa Update qwen3-coder-next-fp8.toml 2026-06-11 17:41:26 -07:00
Prashanth-InferX 4a46d08015 Update qwen3-coder-next-fp8-1m.toml 2026-06-11 17:40:31 -07:00
Prashanth-InferX 45b286a85f Update gemma-4-31b-it-fp8.toml 2026-06-11 17:34:26 -07:00
Prashanth-InferX 73c58b11fb Update logo.svg 2026-06-11 17:28:48 -07:00
Prashanth-InferX d316d6ba16 Update gemma-4-31b-it-fp8.toml 2026-06-11 17:17:45 -07:00
Tianning Li 2c779fc8c8 Merge branch 'dev' into add-step-3.7-flash 2026-06-11 01:14:54 +08:00
Samrath 0dd27c0da9 feat: add Pioneer provider 2026-06-08 11:04:41 +05:30
Tianning Li c98b11d3ee Merge branch 'dev' into add-step-3.7-flash 2026-06-06 16:40:02 +08:00
Tianning Li 467363a4ae Fix StepFun China step-3.7-flash pricing and clarify provider names
- Convert step-3.7-flash China cost from copied global USD to RMB-converted
  USD (0.185/1.11/0.037 from ¥1.35/8.1/0.27), matching step-3.5-flash convention
- Rename providers to disambiguate China vs Global variants
2026-05-30 13:11:33 +08:00
Tianning Li d3c3aea1d4 Add StepFun Step Plan providers and fix stepfun-ai endpoint
Add stepfun-step-plan (api.stepfun.com/step_plan/v1) and
stepfun-ai-step-plan (api.stepfun.ai/step_plan/v1) providers for the
StepFun step-plan reasoning API. Models: step-3.7-flash, step-3.5-flash,
step-3.5-flash-2603 in both; step-router-v1 in the .com provider only.
All step-plan models omit cost (plan-based billing).

Fix stepfun-ai provider to point at the standard api.stepfun.ai/v1
endpoint and overview doc, separating it cleanly from the step-plan API.
2026-05-30 02:12:31 +08:00
Tianning Li a19b2008ea Add Step 3.7 Flash model to stepfun and stepfun-ai providers
Add step-3.7-flash.toml for both providers (released 2026-05-29,
multimodal text/image/video input, 256K context, open weights) plus
provider logos.
2026-05-30 01:37:08 +08:00
Prashanth-InferX 8f449a6dc8 Update provider.toml 2026-05-25 08:11:44 -07:00
Prashanth-InferX b2322529ae Update logo.svg 2026-05-24 22:05:00 -07:00
Prashanth-InferX e239a17ef1 Update provider.toml 2026-05-24 21:51:53 -07:00
Prashanth-InferX 0057a210b0 Add InferX logo 2026-05-24 21:46:58 -07:00
Prashanth-InferX 7d52d15549 Update qwen3-coder-next-fp8.toml 2026-05-23 17:39:00 -07:00
Prashanth-InferX 39163abcd4 Update qwen3-coder-next-fp8-1m.toml 2026-05-23 17:38:06 -07:00
Prashanth-InferX 8f9ad03e1c Update qwen3-coder-next-fp8.toml 2026-05-23 17:10:57 -07:00
Prashanth-InferX ba9e5f5403 Update qwen3-coder-next-fp8-1m.toml 2026-05-23 17:08:35 -07:00
Prashanth-InferX 6d143784e4 Update gemma-4-31b-it-fp8.toml 2026-05-23 17:08:16 -07:00
Prashanth-InferX 3163eaee22 Delete providers/inferx/models/qwen/gemma-4-31b-it-fp8.toml 2026-05-22 17:40:45 -07:00
Prashanth-InferX 16b7bffb0f Create gemma-4-31b-it-fp8.toml 2026-05-22 17:37:25 -07:00
Prashanth-InferX cdfee03695 Create gemma-4-31b-it-fp8.toml 2026-05-22 17:34:51 -07:00
Prashanth-InferX f5b2ae2071 Create qwen3.6-35b-a3b-fp8.toml 2026-05-22 17:33:58 -07:00
Prashanth-InferX bd985e6d97 Create qwen3.6-27b-fp8.toml 2026-05-22 17:33:24 -07:00
Prashanth-InferX 353af73289 Create qwen3.5-122b-a10b-nvfp4.toml 2026-05-22 17:32:45 -07:00
Prashanth-InferX 2ee373fdf9 Update qwen3-coder-next-fp8-1m.toml 2026-05-22 17:31:36 -07:00
Prashanth-InferX de3f51e2cd Create qwen3-coder-next-fp8-1m.toml 2026-05-22 17:28:41 -07:00
Prashanth-InferX 50eeac2f73 Create qwen3-coder-next-fp8.toml 2026-05-22 17:26:54 -07:00
Prashanth-InferX fcb99992a9 Create provider.toml 2026-05-22 17:08:09 -07:00
1431 changed files with 19256 additions and 4976 deletions
+1 -1
View File
@@ -140,7 +140,7 @@ jobs:
Failed log excerpt:
EOF
cat "$LOG_FILE"
} | opencode run --agent ci-fixer -m opencode/glm-5.2 | tee "$RESPONSE_FILE"
} | opencode run --agent ci-fixer -m opencode/grok-4.5 | tee "$RESPONSE_FILE"
- name: Check changed paths
if: steps.budget.outputs.run == 'true' && steps.budget-cache.outputs.cache-hit != 'true'
+29 -19
View File
@@ -3,23 +3,28 @@ name: Issue Fixer
on:
issues:
types: [opened]
repository_dispatch:
types: [missing-model]
permissions:
contents: write
issues: write
pull-requests: write
concurrency: issue-fixer-${{ github.event.issue.number }}
concurrency: issue-fixer-${{ github.event.issue.number || github.event.client_payload.issue_number }}
jobs:
fix:
if: github.repository == 'anomalyco/models.dev'
if: >-
github.repository == 'anomalyco/models.dev'
&& !contains(github.event.issue.labels.*.name, 'provider:openai')
&& !contains(github.event.issue.labels.*.name, 'provider:pioneer')
&& github.event.client_payload.provider != 'openai'
&& github.event.client_payload.provider != 'pioneer'
runs-on: ubuntu-latest
env:
GH_TOKEN: ${{ github.token }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
ISSUE_TITLE: ${{ github.event.issue.title }}
ISSUE_BODY: ${{ github.event.issue.body }}
ISSUE_NUMBER: ${{ github.event.issue.number || github.event.client_payload.issue_number }}
steps:
- name: Checkout code
@@ -27,6 +32,13 @@ jobs:
with:
ref: dev
- name: Load issue
run: |
set -euo pipefail
ISSUE_FILE="$RUNNER_TEMP/issue.json"
gh issue view "$ISSUE_NUMBER" --json number,title,body,labels > "$ISSUE_FILE"
echo "ISSUE_FILE=$ISSUE_FILE" >> "$GITHUB_ENV"
- name: Install opencode
run: curl -fsSL https://opencode.ai/install | bash
@@ -38,22 +50,19 @@ jobs:
set -euo pipefail
EVENTS_FILE="$RUNNER_TEMP/issue-fixer-events.jsonl"
RESPONSE_FILE="$RUNNER_TEMP/issue-fixer-response.md"
PROMPT_FILE="$RUNNER_TEMP/issue-fixer-prompt.md"
echo "RESPONSE_FILE=$RESPONSE_FILE" >> "$GITHUB_ENV"
opencode run --agent issue-fixer -m opencode/glm-5.2 --format json <<EOF | tee "$EVENTS_FILE"
A new GitHub issue was opened in anomalyco/models.dev.
jq -r '
"A new GitHub issue was opened in anomalyco/models.dev.\n\n"
+ "Issue #\(.number): \(.title)\n\n"
+ "Body:\n" + (.body // "") + "\n\n"
+ "Decide whether this is an actionable model catalog data fix.\n\n"
+ "If it asks for a model to be added or for factual model/provider metadata to be corrected, make the minimal TOML changes in the repository. Do not use Bash. Do not create branches, commits, comments, or pull requests yourself.\n\n"
+ "If it is a feature request, a request to track a new kind of information, a question, or any miscellaneous non-catalog-data request, do not edit files. Respond briefly that it needs maintainer review and no automated fix was opened."
' "$ISSUE_FILE" > "$PROMPT_FILE"
Issue #$ISSUE_NUMBER: $ISSUE_TITLE
Body:
$ISSUE_BODY
Decide whether this is an actionable model catalog data fix.
If it asks for a model to be added or for factual model/provider metadata to be corrected, make the minimal TOML changes in the repository. Do not use Bash. Do not create branches, commits, comments, or pull requests yourself.
If it is a feature request, a request to track a new kind of information, a question, or any miscellaneous non-catalog-data request, do not edit files. Respond briefly that it needs maintainer review and no automated fix was opened.
EOF
opencode run --agent issue-fixer -m opencode/grok-4.5 --format json < "$PROMPT_FILE" | tee "$EVENTS_FILE"
if ! jq -ers 'map(select(.type == "text") | .part.text) | last | select(length > 0)' "$EVENTS_FILE" > "$RESPONSE_FILE"; then
echo "Issue fixer did not produce a final response." >&2
@@ -74,9 +83,10 @@ jobs:
- name: Create pull request
if: success()
env:
BRANCH: issue-${{ github.event.issue.number }}
BRANCH: issue-${{ github.event.issue.number || github.event.client_payload.issue_number }}
run: |
set -euo pipefail
ISSUE_TITLE="$(jq -r .title "$ISSUE_FILE")"
if [ -z "$(git status --porcelain)" ]; then
if [ -s "$RESPONSE_FILE" ]; then
+1 -1
View File
@@ -27,4 +27,4 @@ jobs:
env:
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
with:
model: opencode/gpt-5.5
model: opencode/grok-4.5
+1 -1
View File
@@ -60,7 +60,7 @@ jobs:
RESPONSE_FILE="$RUNNER_TEMP/pr-reviewer-response.md"
echo "RESPONSE_FILE=$RESPONSE_FILE" >> "$GITHUB_ENV"
opencode run --agent pr-reviewer -m opencode/glm-5.2 --format json <<'EOF' | tee "$EVENTS_FILE"
opencode run --agent pr-reviewer -m opencode/grok-4.5 --format json <<'EOF' | tee "$EVENTS_FILE"
Review this pull request using the trusted reviewer instructions. Start with `.pr-review/pull-request.json`, `.pr-review/diff.patch`, `AGENTS.md`, and the contributing guidance in `README.md`. Read `sync.md`, the reasoning-options audit guide, schema code, and nearby base-revision files when relevant to the changed files. Use only the read, glob, and grep tools. Return only the final review comment in the agent's required output format. Never include progress narration or passed-check summaries.
EOF
+3
View File
@@ -63,6 +63,7 @@ jobs:
- name: Sync model catalogs
run: bun models:sync ${{ matrix.provider }}
env:
GH_TOKEN: ${{ github.token }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
BASETEN_API_KEY: ${{ secrets.BASETEN_API_KEY }}
DEEPINFRA_API_KEY: ${{ secrets.DEEPINFRA_API_KEY }}
@@ -73,6 +74,8 @@ jobs:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
VENICE_API_KEY: ${{ secrets.VENICE_API_KEY }}
LLMGATEWAY_API_KEY: ${{ secrets.LLMGATEWAY_API_KEY }}
MERGE_GATEWAY_API_KEY: ${{ secrets.MERGE_GATEWAY_API_KEY }}
KILO_API_KEY: ${{ secrets.KILO_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
GOOGLE_GENERATIVE_AI_API_KEY: ${{ secrets.GOOGLE_GENERATIVE_AI_API_KEY }}
+2
View File
@@ -38,6 +38,8 @@ For model catalog changes, enforce these review rules:
- Treat a missing compliant logo for a new provider as a merge blocker. The SVG must use `currentColor`, have no fixed size or hardcoded color, and preferably use a square `viewBox`.
- Treat duplicated provider-agnostic metadata as a merge blocker when a matching `models/<provider>/<model>.toml` exists; the provider entry must use `base_model` and retain only provider-specific fields and overrides.
- Treat missing `reasoning_options` on `reasoning = true` provider models as a merge blocker. Options describe controls exposed by that inference provider, not merely by the upstream model. An empty array is correct when reasoning exists but no caller control is verified.
- Before reporting a `reasoning_options` problem, compare the proposed model with existing entries for the same underlying model that use a comparable request surface. Determine that surface from the effective `npm`, provider API shape, and any model-level provider override—not from the model family alone. Prefer native-provider examples when the target uses the native SDK (for example, an Anthropic model through `@ai-sdk/anthropic` should be compared with the Anthropic provider). Prefer established OpenAI-compatible gateway examples when the target uses an OpenAI-compatible chat-completions surface (for example, Cloudflare AI Gateway may be usefully compared with OpenRouter). Do not compare a native Anthropic route with an OpenAI-compatible gateway as though their controls were interchangeable.
- Use those peer entries as required review context, not as values to copy mechanically or as standalone proof. Consistent same-model, same-surface examples make a proposed option more plausible and help identify likely omissions or contradictions; target-provider documentation, endpoint metadata, adapter behavior, or reproduced requests still override peer precedent. A lack of bespoke provider documentation is not by itself an action item when the target surface and strong peer examples support the proposal and the diff contains no concrete contradictory evidence. Conversely, do not accept or reject `reasoning_options = []` mechanically: explain the specific mismatch with the target API shape or comparable providers before requesting a change.
- Do not treat absence of a sync module as a blocker. Recommend one only when a context-rich provider API can authoritatively populate model data or delete models no longer served.
- Data-changing PRs should cite direct provider pricing, model documentation, or API references in the PR body. Missing citations are not by themselves a merge blocker, but should be reported as a low-severity request for evidence when material factual changes otherwise cannot be reviewed. Prefer first-party sources and require each citation to state what it supports.
- You cannot fetch citation URLs. Assess whether citations are present, direct, and mapped to claims, but never claim you opened a URL or verified its contents. A URL or PR assertion alone does not prove a disputed value.
+3
View File
@@ -119,6 +119,9 @@ items are **hard blockers**; the last two are **strongly recommended** but not b
- Latest/undated models: `@default` (`claude-opus-4-6@default.toml`)
### Cost Schema
- **All `cost` values are USD per million tokens.** Never publish EUR, CNY, or other currencies.
If a provider API or pricing page quotes another currency, convert to USD before writing the
TOML and note the source rate/date in a top-of-file comment.
- `cost.context_over_200k` is a nested `Cost` object for >200K token pricing
- Cache pricing ratios: standard models use 10%/125% (read/write), regional variants may use 30%/375%
+1
View File
@@ -0,0 +1 @@
description = "Poolside builds open-weight foundation models and the systems that refine and improve them."
+3
View File
@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" fill="currentColor">
<path d="m35.959 121.526c-11.8772-5.794-21.5249-14.947-27.90834-26.4686-6.23593-11.2582-8.930092-23.9574-7.798832-36.7265.256124-2.8615 2.777032-4.9741 5.639732-4.7214 2.85734.2545 4.97334 2.7778 4.72074 5.641-.94779 10.6955 1.3128 21.3362 6.538 30.7705 4.4985 8.1229 10.9417 14.84 18.8061 19.656l24.4606-50.1633c-9.5744-3.1888-17.5492-1.8007-18.2669-1.6613-.1053.0243-.2071.0414-.3106.0621-2.3841.3992-4.6901-.9038-5.6184-3.0702-1.2811-2.3919-5.1275-8.2384-9.7828-10.5094-4.6552-2.2711-11.8298-1.5385-14.1394-1.0363-1.9474.4252-3.97402-.3009-5.20405-1.8667-1.23003-1.5659-1.4658-3.7015-.5927-5.492 15.45775-31.71872 53.84575-44.93849 85.55925-29.46724 31.7136 15.47124 44.9196 53.82984 29.4886 85.53934-.016.0323-.032.0647-.049.1006-15.485 31.6834-53.8429 44.8774-85.542 29.4134zm33.8009-57.4544-24.4588 50.1594c24.6863 9.222 52.7773-1.024 65.6229-24.3097-1.806-2.7947-4.974-6.8014-8.641-8.5902-4.7375-2.3114-11.6793-1.5543-14.0641-1.0532-.3926.0933-.7839.1383-1.1773.1422-.7048.0034-1.4199-.1363-2.1061-.4355-.7114-.3114-1.3547-.781-1.874-1.386-.2968-.3495-.5421-.7317-.7393-1.1395-.1533-.3062-3.9466-7.6667-12.5659-13.3893zm-38.7651-29.0902c3.9831 1.9431 7.2244 5.0332 9.6483 7.947 7.496-11.4666 17.6688-20.1275 25.527-25.7116 2.9201-2.0736 5.9436-4.0123 8.8552-5.6852-20.4537-4.29467-41.8903 3.8115-54.3197 20.8782 3.2899.2252 6.9209.9284 10.2892 2.5716zm67.5712-11.9611c.4747 3.3248.8105 6.8979.9729 10.4798.4384 9.6049-.1169 22.9086-4.5038 35.8475 3.6589.0981 7.9139.7451 11.8069 2.6443 3.476 1.6959 6.39 4.2614 8.684 6.8223 5.855-20.3405-.95-42.2864-16.9617-55.7903zm-28.7702 29.1142c7.1932 3.5091 12.3927 8.1776 15.9169 12.2023 5.733-18.6289 3.2338-39.4757 1.1469-47.1965-7.3675 3.1085-25.3335 13.9715-36.4767 29.961 5.3459.2981 12.2232 1.5257 19.4129 5.0332z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

+1 -1
View File
@@ -3,7 +3,7 @@ description = "Earlier Qwen multimodal workhorse for million-token agent and doc
family = "qwen"
release_date = "2026-04-02"
last_updated = "2026-04-02"
attachment = false
attachment = true
reasoning = true
temperature = true
tool_call = true
+64
View File
@@ -16,3 +16,67 @@ output = 65_536
[modalities]
input = ["text"]
output = ["text"]
[[benchmarks]]
name = "SWE-Bench Verified"
score = 80.4
metric = "resolved"
source = "https://qwen.ai/blog?id=qwen3.7"
date = "2026-05-19"
[[benchmarks]]
name = "SWE-Bench Pro"
score = 60.6
metric = "resolve rate"
source = "https://qwen.ai/blog?id=qwen3.7"
date = "2026-05-19"
[[benchmarks]]
name = "SWE-Bench Multilingual"
score = 78.3
metric = "resolve rate"
source = "https://qwen.ai/blog?id=qwen3.7"
date = "2026-05-19"
[[benchmarks]]
name = "Terminal-Bench"
score = 69.7
metric = "success rate"
harness = "Terminus-2"
version = "2.0"
source = "https://qwen.ai/blog?id=qwen3.7"
date = "2026-05-19"
[[benchmarks]]
name = "GPQA Diamond"
score = 92.4
metric = "accuracy"
source = "https://qwen.ai/blog?id=qwen3.7"
date = "2026-05-19"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 41.4
metric = "accuracy"
source = "https://qwen.ai/blog?id=qwen3.7"
date = "2026-05-19"
[[benchmarks]]
name = "SciCode"
score = 53.5
source = "https://qwen.ai/blog?id=qwen3.7"
date = "2026-05-19"
[[benchmarks]]
name = "MCP Atlas"
score = 76.4
metric = "success rate"
source = "https://qwen.ai/blog?id=qwen3.7"
date = "2026-05-19"
[[benchmarks]]
name = "NL2Repo"
score = 47.2
harness = "Claude Code"
source = "https://qwen.ai/blog?id=qwen3.7"
date = "2026-05-19"
+2 -2
View File
@@ -3,7 +3,7 @@ description = "Multimodal Qwen workhorse for long-context agents, visual inputs,
family = "qwen"
release_date = "2026-06-02"
last_updated = "2026-06-02"
attachment = false
attachment = true
reasoning = true
temperature = true
tool_call = true
@@ -15,5 +15,5 @@ context = 1_000_000
output = 64_000
[modalities]
input = ["text", "image"]
input = ["text", "image", "video"]
output = ["text"]
+30
View File
@@ -0,0 +1,30 @@
# Sources (accessed 2026-07-20):
# https://docs.qwencloud.com/token-plan/personal/token-plan-personal-overview
# https://platform.qianwenai.com/docs/token-plan/personal/token-plan-personal-overview
# https://docs.qwencloud.com/developer-guides/getting-started/text-generation-models
# https://platform.qianwenai.com/docs/developer-guides/getting-started/text-generation-models
# https://docs.qwencloud.com/developer-guides/clients-and-developer-tools/opencode
# https://platform.qianwenai.com/docs/developer-guides/clients-and-developer-tools/opencode
# https://docs.qwencloud.com/developer-guides/clients-and-developer-tools/kilo-cli
# https://platform.qianwenai.com/docs/developer-guides/clients-and-developer-tools/kilo-cli
# https://github.com/QwenLM/qwen-code/issues/7198
# https://github.com/QwenLM/qwen-code/pull/7199
name = "Qwen3.8 Max Preview"
description = "Preview Qwen flagship for million-token multimodal reasoning and long-horizon agentic workflows"
family = "qwen"
release_date = "2026-07-19"
last_updated = "2026-07-19"
attachment = true
reasoning = true
temperature = true
tool_call = true
open_weights = false
[limit]
context = 1_000_000
output = 131_072
[modalities]
input = ["text", "image", "video"]
output = ["text"]
+67
View File
@@ -17,3 +17,70 @@ output = 128_000
[modalities]
input = ["text", "image", "pdf"]
output = ["text"]
[[benchmarks]]
name = "SWE-Bench Pro"
score = 80.3
metric = "resolve rate"
source = "https://www.anthropic.com/news/claude-fable-5-mythos-5"
date = "2026-06-09"
[[benchmarks]]
name = "SWE-Bench Verified"
score = 95
metric = "resolved"
source = "https://benchlm.ai/benchmarks/sweVerified"
[[benchmarks]]
name = "Terminal-Bench"
score = 88.0
metric = "success rate"
version = "2.1"
source = "https://www.anthropic.com/news/claude-fable-5-mythos-5"
date = "2026-06-09"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 59
metric = "accuracy"
variant = "no tools"
source = "https://www.anthropic.com/news/claude-fable-5-mythos-5"
date = "2026-06-09"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 64.5
metric = "accuracy"
variant = "with tools"
source = "https://www.anthropic.com/news/claude-fable-5-mythos-5"
date = "2026-06-09"
[[benchmarks]]
name = "OSWorld-Verified"
score = 85
metric = "success rate"
source = "https://www.anthropic.com/news/claude-fable-5-mythos-5"
date = "2026-06-09"
[[benchmarks]]
name = "FrontierCode"
score = 29.3
metric = "pass rate"
variant = "high effort"
dataset = "Diamond"
source = "https://www.anthropic.com/news/claude-fable-5-mythos-5"
date = "2026-06-09"
[[benchmarks]]
name = "GDPval-AA"
score = 1932
metric = "Elo"
source = "https://www.anthropic.com/news/claude-fable-5-mythos-5"
date = "2026-06-09"
[[benchmarks]]
name = "AutomationBench"
score = 17.4
metric = "success rate"
source = "https://www.anthropic.com/news/claude-fable-5-mythos-5"
date = "2026-06-09"
+30
View File
@@ -142,3 +142,33 @@ harness = "Claude Code"
variant = "medium"
version = "2.1"
source = "https://artificialanalysis.ai/agents/coding-agents"
[[benchmarks]]
name = "GPQA Diamond"
score = 94.2
metric = "accuracy"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 46.9
metric = "accuracy"
variant = "no tools"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 54.7
metric = "accuracy"
variant = "with tools"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "OSWorld-Verified"
score = 78.0
metric = "success rate"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
+38
View File
@@ -33,3 +33,41 @@ harness = "Terminus-2"
version = "2.1"
source = "https://www.anthropic.com/news/claude-opus-4-8"
date = "2026-05-28"
[[benchmarks]]
name = "SWE-Bench Verified"
score = 88.6
metric = "resolved"
source = "https://benchlm.ai/benchmarks/sweVerified"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 49.8
metric = "accuracy"
variant = "no tools"
source = "https://www.anthropic.com/news/claude-fable-5-mythos-5"
date = "2026-06-09"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 57.9
metric = "accuracy"
variant = "with tools"
source = "https://www.anthropic.com/news/claude-fable-5-mythos-5"
date = "2026-06-09"
[[benchmarks]]
name = "OSWorld-Verified"
score = 83.4
metric = "success rate"
source = "https://www.anthropic.com/news/claude-fable-5-mythos-5"
date = "2026-06-09"
[[benchmarks]]
name = "FrontierCode"
score = 13.4
metric = "pass rate"
variant = "high effort"
dataset = "Diamond"
source = "https://www.anthropic.com/news/claude-fable-5-mythos-5"
date = "2026-06-09"
+19
View File
@@ -0,0 +1,19 @@
name = "Claude Opus 5"
description = "Strongest Claude Opus model for coding, agents, and professional work"
family = "claude-opus"
release_date = "2026-07-24"
last_updated = "2026-07-24"
attachment = true
reasoning = true
temperature = false
tool_call = true
open_weights = false
knowledge = "2026-05"
[limit]
context = 1_000_000
output = 128_000
[modalities]
input = ["text", "image", "pdf"]
output = ["text"]
+32
View File
@@ -72,3 +72,35 @@ harness = "Claude Code"
variant = "medium"
version = "2.1"
source = "https://artificialanalysis.ai/agents/coding-agents"
[[benchmarks]]
name = "Terminal-Bench"
score = 67.0
metric = "success rate"
harness = "Terminus-2"
version = "2.1"
source = "https://www.anthropic.com/news/claude-sonnet-5"
date = "2026-06-30"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 34.6
metric = "accuracy"
variant = "no tools"
source = "https://www.anthropic.com/news/claude-sonnet-5"
date = "2026-06-30"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 46.8
metric = "accuracy"
variant = "with tools"
source = "https://www.anthropic.com/news/claude-sonnet-5"
date = "2026-06-30"
[[benchmarks]]
name = "OSWorld-Verified"
score = 78.5
metric = "success rate"
source = "https://www.anthropic.com/news/claude-sonnet-5"
date = "2026-06-30"
+53
View File
@@ -17,3 +17,56 @@ output = 128_000
[modalities]
input = ["text", "image", "pdf"]
output = ["text"]
[[benchmarks]]
name = "SWE-Bench Verified"
score = 85.2
metric = "resolved"
source = "https://www.anthropic.com/news/claude-sonnet-5"
date = "2026-06-30"
[[benchmarks]]
name = "SWE-Bench Pro"
score = 63.2
metric = "resolve rate"
source = "https://www.anthropic.com/news/claude-sonnet-5"
date = "2026-06-30"
[[benchmarks]]
name = "SWE-Bench Multilingual"
score = 78.3
metric = "resolve rate"
source = "https://www.anthropic.com/news/claude-sonnet-5"
date = "2026-06-30"
[[benchmarks]]
name = "Terminal-Bench"
score = 80.4
metric = "success rate"
harness = "Terminus-2"
version = "2.1"
source = "https://www.anthropic.com/news/claude-sonnet-5"
date = "2026-06-30"
[[benchmarks]]
name = "OSWorld-Verified"
score = 81.2
metric = "success rate"
source = "https://www.anthropic.com/news/claude-sonnet-5"
date = "2026-06-30"
[[benchmarks]]
name = "BrowseComp"
score = 84.7
metric = "accuracy"
variant = "single agent"
source = "https://www.anthropic.com/news/claude-sonnet-5"
date = "2026-06-30"
[[benchmarks]]
name = "FrontierCode"
score = 38.8
metric = "pass rate"
version = "v1"
source = "https://www.anthropic.com/news/claude-sonnet-5"
date = "2026-06-30"
+23
View File
@@ -0,0 +1,23 @@
# https://huggingface.co/CohereLabs/aya-expanse-32b
name = "Aya Expanse 32B"
description = "Open multilingual model optimized for generation across 23 languages"
release_date = "2024-10-24"
last_updated = "2024-10-24"
attachment = false
reasoning = false
temperature = true
tool_call = false
open_weights = true
license = "CC-BY-NC-4.0"
[limit]
context = 128_000
output = 4_000
[modalities]
input = ["text"]
output = ["text"]
[[weights]]
label = "Hugging Face"
url = "https://huggingface.co/CohereLabs/aya-expanse-32b"
+23
View File
@@ -0,0 +1,23 @@
# https://huggingface.co/CohereLabs/aya-expanse-8b
name = "Aya Expanse 8B"
description = "Compact open multilingual model optimized for generation across 23 languages"
release_date = "2024-10-24"
last_updated = "2024-10-24"
attachment = false
reasoning = false
temperature = true
tool_call = false
open_weights = true
license = "CC-BY-NC-4.0"
[limit]
context = 8_000
output = 4_000
[modalities]
input = ["text"]
output = ["text"]
[[weights]]
label = "Hugging Face"
url = "https://huggingface.co/CohereLabs/aya-expanse-8b"
+23
View File
@@ -0,0 +1,23 @@
# https://huggingface.co/CohereLabs/aya-vision-32b
name = "Aya Vision 32B"
description = "Open multilingual vision model for OCR, visual reasoning, and image question answering"
release_date = "2025-03-04"
last_updated = "2025-05-14"
attachment = true
reasoning = false
temperature = true
tool_call = false
open_weights = true
license = "CC-BY-NC-4.0"
[limit]
context = 16_000
output = 4_000
[modalities]
input = ["text", "image"]
output = ["text"]
[[weights]]
label = "Hugging Face"
url = "https://huggingface.co/CohereLabs/aya-vision-32b"
+23
View File
@@ -0,0 +1,23 @@
# https://huggingface.co/CohereLabs/aya-vision-8b
name = "Aya Vision 8B"
description = "Compact open multilingual vision model for OCR and visual question answering"
release_date = "2025-03-04"
last_updated = "2025-05-14"
attachment = true
reasoning = false
temperature = true
tool_call = false
open_weights = true
license = "CC-BY-NC-4.0"
[limit]
context = 16_000
output = 4_000
[modalities]
input = ["text", "image"]
output = ["text"]
[[weights]]
label = "Hugging Face"
url = "https://huggingface.co/CohereLabs/aya-vision-8b"
@@ -0,0 +1,25 @@
# https://docs.cohere.com/docs/command-a-reasoning
# https://huggingface.co/CohereLabs/c4ai-command-a-reasoning-08-2025
name = "Command A Reasoning"
description = "Cohere reasoning model for multilingual enterprise agents, tools, and complex workflows"
family = "command-a"
release_date = "2025-08-21"
last_updated = "2025-08-21"
attachment = false
reasoning = true
temperature = true
knowledge = "2024-06-01"
tool_call = true
open_weights = true
[limit]
context = 256_000
output = 32_000
[modalities]
input = ["text"]
output = ["text"]
[[weights]]
label = "Hugging Face"
url = "https://huggingface.co/CohereLabs/c4ai-command-a-reasoning-08-2025"
@@ -0,0 +1,25 @@
# https://docs.cohere.com/docs/models
# https://huggingface.co/CohereLabs/c4ai-command-a-translate-08-2025
name = "Command A Translate"
description = "Translation model for multilingual conversion, localization, and cross-language workflows"
family = "command-a"
release_date = "2025-08-28"
last_updated = "2025-08-28"
attachment = false
reasoning = false
temperature = true
knowledge = "2024-06-01"
tool_call = true
open_weights = true
[limit]
context = 8_000
output = 8_000
[modalities]
input = ["text"]
output = ["text"]
[[weights]]
label = "Hugging Face"
url = "https://huggingface.co/CohereLabs/c4ai-command-a-translate-08-2025"
@@ -0,0 +1,25 @@
# https://docs.cohere.com/docs/command-a-vision
# https://huggingface.co/CohereLabs/c4ai-command-a-vision-07-2025
name = "Command A Vision"
description = "Cohere vision model for multilingual document analysis, OCR, and image understanding"
family = "command-a"
release_date = "2025-07-31"
last_updated = "2025-07-31"
attachment = true
reasoning = false
temperature = true
knowledge = "2024-06-01"
tool_call = false
open_weights = true
[limit]
context = 128_000
output = 8_000
[modalities]
input = ["text", "image"]
output = ["text"]
[[weights]]
label = "Hugging Face"
url = "https://huggingface.co/CohereLabs/c4ai-command-a-vision-07-2025"
@@ -0,0 +1,25 @@
# https://huggingface.co/CohereLabs/c4ai-command-r7b-arabic-02-2025
# https://docs.cohere.com/changelog/command-r7b-arabic
name = "Command R7B Arabic"
description = "Open Command R model optimized for Arabic enterprise chat, RAG, and cultural knowledge"
family = "command-r"
release_date = "2025-02-27"
last_updated = "2025-02-27"
attachment = false
reasoning = false
temperature = true
knowledge = "2024-06-01"
tool_call = true
open_weights = true
[limit]
context = 128_000
output = 4_000
[modalities]
input = ["text"]
output = ["text"]
[[weights]]
label = "Hugging Face"
url = "https://huggingface.co/CohereLabs/c4ai-command-r7b-arabic-02-2025"
+44
View File
@@ -18,3 +18,47 @@ output = 64_000
[modalities]
input = ["text"]
output = ["text"]
[[benchmarks]]
name = "SWE-Bench Verified"
score = 67.6
metric = "resolved"
harness = "SWE-agent"
source = "https://huggingface.co/CohereLabs/North-Mini-Code-1.0"
date = "2026-06-09"
[[benchmarks]]
name = "SWE-Bench Pro"
score = 40.2
metric = "resolve rate"
harness = "SWE-agent"
source = "https://huggingface.co/CohereLabs/North-Mini-Code-1.0"
date = "2026-06-09"
[[benchmarks]]
name = "Artificial Analysis Intelligence Index"
score = 27.6
metric = "index score"
source = "https://artificialanalysis.ai/articles/north-mini-code-cohere-s-small-coding-focused-moe-model"
date = "2026-06-09"
[[benchmarks]]
name = "Artificial Analysis Coding Index"
score = 33.4
metric = "index score"
source = "https://artificialanalysis.ai/articles/north-mini-code-cohere-s-small-coding-focused-moe-model"
date = "2026-06-09"
[[benchmarks]]
name = "GDPval-AA"
score = 14
metric = "win rate"
source = "https://artificialanalysis.ai/articles/north-mini-code-cohere-s-small-coding-focused-moe-model"
date = "2026-06-09"
[[benchmarks]]
name = "τ²-Bench Telecom"
score = 37
metric = "success rate"
source = "https://artificialanalysis.ai/articles/north-mini-code-cohere-s-small-coding-focused-moe-model"
date = "2026-06-09"
@@ -0,0 +1,24 @@
# Sources:
# - https://ai.google.dev/gemini-api/docs/models/deep-research-max-preview-04-2026
# - https://ai.google.dev/gemini-api/docs/deep-research
# - https://blog.google/innovation-and-ai/models-and-research/gemini-models/next-generation-gemini-deep-research/
name = "Deep Research Max Preview"
description = "Maximum-comprehensiveness agentic researcher for multi-step investigation, synthesis, and cited reports"
family = "gemini-pro"
release_date = "2026-04-21"
last_updated = "2026-04-21"
attachment = true
reasoning = true
temperature = false
tool_call = true
knowledge = "2025-01"
open_weights = false
[limit]
context = 1_048_576
output = 65_536
[modalities]
input = ["text", "image", "video", "audio", "pdf"]
output = ["text", "image"]
@@ -0,0 +1,24 @@
# Sources:
# - https://ai.google.dev/gemini-api/docs/models/deep-research-preview-04-2026
# - https://ai.google.dev/gemini-api/docs/deep-research
# - https://blog.google/innovation-and-ai/models-and-research/gemini-models/next-generation-gemini-deep-research/
name = "Gemini Deep Research Preview"
description = "Agentic model for autonomous multi-step research, synthesis, and cited reports"
family = "gemini-pro"
release_date = "2026-04-21"
last_updated = "2026-04-21"
attachment = true
reasoning = true
temperature = false
tool_call = true
knowledge = "2025-01"
open_weights = false
[limit]
context = 1_048_576
output = 65_536
[modalities]
input = ["text", "image", "video", "audio", "pdf"]
output = ["text", "image"]
@@ -0,0 +1,27 @@
# Sources:
# - https://ai.google.dev/gemini-api/docs/models/gemini-2.5-computer-use-preview-10-2025
# (model id, modalities text+image in / text out, input 128000, output 64000, latest update Oct 2025)
# - https://ai.google.dev/gemini-api/docs/computer-use
# (legacy computer-use model; tool/function actions; still listed as available)
# - https://blog.google/innovation-and-ai/models-and-research/google-deepmind/gemini-computer-use-model/
# (public preview 2025-10-07; built on Gemini 2.5 Pro visual + reasoning)
name = "Gemini 2.5 Computer Use Preview"
description = "Specialized Gemini 2.5 model for browser-control agents that automate UI tasks"
family = "gemini-pro"
release_date = "2025-10-07"
last_updated = "2025-10-07"
attachment = true
reasoning = true
temperature = true
tool_call = true
knowledge = "2025-01"
open_weights = false
[limit]
context = 128_000
output = 64_000
[modalities]
input = ["text", "image"]
output = ["text"]
+1 -1
View File
@@ -7,7 +7,7 @@ attachment = true
reasoning = true
temperature = true
tool_call = false
knowledge = "2025-06"
knowledge = "2024-06"
open_weights = false
[limit]
+19
View File
@@ -0,0 +1,19 @@
name = "Nano Banana Pro"
description = "Nano Banana Pro for higher-fidelity image generation and design-heavy edits"
family = "gemini-pro"
release_date = "2026-05-28"
last_updated = "2026-05-28"
attachment = true
reasoning = true
temperature = true
tool_call = false
knowledge = "2025-01"
open_weights = false
[limit]
context = 65_536
output = 32_768
[modalities]
input = ["text", "image"]
output = ["text", "image"]
+19
View File
@@ -0,0 +1,19 @@
name = "Nano Banana 2"
description = "Image model for prompt-driven generation, editing, and visual design workflows"
family = "gemini-flash"
release_date = "2026-05-28"
last_updated = "2026-05-28"
attachment = true
reasoning = true
temperature = true
tool_call = false
knowledge = "2025-01"
open_weights = false
[limit]
context = 131_072
output = 32_768
[modalities]
input = ["text", "image", "video", "pdf"]
output = ["text", "image"]
@@ -0,0 +1,25 @@
# Sources:
# - https://ai.google.dev/gemini-api/docs/models/gemini-3.1-flash-lite-image
# - https://ai.google.dev/gemini-api/docs/image-generation
# - https://deepmind.google/models/model-cards/gemini-3-1-flash-lite-image/
# - https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/gemini/3-1-flash-lite-image
name = "Nano Banana 2 Lite"
description = "Fastest, most cost-efficient Gemini image model for high-volume 1K generation and editing"
family = "gemini-flash-lite"
release_date = "2026-06-30"
last_updated = "2026-06-30"
attachment = true
reasoning = true
temperature = true
tool_call = true
structured_output = false
knowledge = "2025-01"
open_weights = false
[limit]
context = 65_536
output = 4_096
[modalities]
input = ["text", "image"]
output = ["text", "image"]
@@ -0,0 +1,24 @@
# Sources:
# - https://ai.google.dev/gemini-api/docs/models/gemini-3.1-flash-live-preview
# - https://blog.google/innovation-and-ai/technology/developers-tools/build-with-gemini-3-1-flash-live/
# - https://deepmind.google/models/model-cards/gemini-3-1-flash-audio/
name = "Gemini 3.1 Flash Live Preview"
description = "High-quality, low-latency Live API model for real-time dialogue and voice-first AI applications"
family = "gemini-flash"
release_date = "2026-03-26"
last_updated = "2026-03-26"
attachment = true
reasoning = true
temperature = true
tool_call = true
structured_output = false
knowledge = "2025-01"
open_weights = false
[limit]
context = 131_072
output = 65_536
[modalities]
input = ["text", "image", "video", "audio"]
output = ["text", "audio"]
@@ -0,0 +1,23 @@
# Sources:
# - https://ai.google.dev/gemini-api/docs/models/gemini-3.1-flash-tts-preview
# - https://blog.google/innovation-and-ai/models-and-research/gemini-models/gemini-3-1-flash-tts/
name = "Gemini 3.1 Flash TTS Preview"
description = "Low-latency speech generation with steerable prompts and expressive audio tags"
family = "gemini-flash"
release_date = "2026-04-15"
last_updated = "2026-04-15"
attachment = false
reasoning = false
temperature = true
tool_call = false
knowledge = "2025-01"
open_weights = false
[limit]
context = 8_192
output = 16_384
[modalities]
input = ["text"]
output = ["audio"]
+59
View File
@@ -96,3 +96,62 @@ harness = "Gemini CLI"
variant = "high"
version = "2.1"
source = "https://artificialanalysis.ai/agents/coding-agents"
[[benchmarks]]
name = "GPQA Diamond"
score = 94.3
metric = "accuracy"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 44.4
metric = "accuracy"
dataset = "full set, text + MM"
source = "https://deepmind.google/models/gemini/flash/"
date = "2026-05-19"
[[benchmarks]]
name = "ARC-AGI-2"
score = 77.1
metric = "accuracy"
source = "https://deepmind.google/models/gemini/flash/"
date = "2026-05-19"
[[benchmarks]]
name = "MMMU Pro"
score = 80.5
metric = "accuracy"
variant = "no tools"
source = "https://deepmind.google/models/gemini/flash/"
date = "2026-05-19"
[[benchmarks]]
name = "MCP Atlas"
score = 78.2
metric = "success rate"
source = "https://deepmind.google/models/gemini/flash/"
date = "2026-05-19"
[[benchmarks]]
name = "OSWorld-Verified"
score = 76.2
metric = "success rate"
source = "https://deepmind.google/models/gemini/flash/"
date = "2026-05-19"
[[benchmarks]]
name = "CharXiv Reasoning"
score = 83.3
metric = "accuracy"
variant = "no tools"
source = "https://deepmind.google/models/gemini/flash/"
date = "2026-05-19"
[[benchmarks]]
name = "GDPval-AA"
score = 1314
metric = "Elo"
source = "https://deepmind.google/models/gemini/flash/"
date = "2026-05-19"
+20
View File
@@ -0,0 +1,20 @@
name = "Gemini 3.5 Flash Lite"
description = "Fast Gemini model balancing multimodal reasoning, tool use, and cost"
family = "gemini-flash-lite"
release_date = "2026-07-21"
last_updated = "2026-07-21"
attachment = true
reasoning = true
temperature = true
tool_call = true
structured_output = true
knowledge = "2026-03"
open_weights = false
[limit]
context = 1_048_576
output = 65_536
[modalities]
input = ["text", "image", "video", "audio", "pdf"]
output = ["text"]
+77
View File
@@ -18,3 +18,80 @@ output = 65_536
[modalities]
input = ["text", "image", "video", "audio", "pdf"]
output = ["text"]
[[benchmarks]]
name = "Terminal-Bench"
score = 76.2
metric = "success rate"
harness = "Terminus-2"
version = "2.1"
source = "https://deepmind.google/models/gemini/flash/"
date = "2026-05-19"
[[benchmarks]]
name = "SWE-Bench Pro"
score = 55.1
metric = "resolve rate"
variant = "single attempt"
dataset = "public"
source = "https://deepmind.google/models/gemini/flash/"
date = "2026-05-19"
[[benchmarks]]
name = "MCP Atlas"
score = 83.6
metric = "success rate"
source = "https://deepmind.google/models/gemini/flash/"
date = "2026-05-19"
[[benchmarks]]
name = "Toolathlon"
score = 56.5
metric = "success rate"
source = "https://deepmind.google/models/gemini/flash/"
date = "2026-05-19"
[[benchmarks]]
name = "OSWorld-Verified"
score = 78.4
metric = "success rate"
source = "https://deepmind.google/models/gemini/flash/"
date = "2026-05-19"
[[benchmarks]]
name = "MMMU Pro"
score = 83.6
metric = "accuracy"
variant = "no tools"
source = "https://deepmind.google/models/gemini/flash/"
date = "2026-05-19"
[[benchmarks]]
name = "CharXiv Reasoning"
score = 84.2
metric = "accuracy"
variant = "no tools"
source = "https://deepmind.google/models/gemini/flash/"
date = "2026-05-19"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 40.2
metric = "accuracy"
dataset = "full set, text + MM"
source = "https://deepmind.google/models/gemini/flash/"
date = "2026-05-19"
[[benchmarks]]
name = "ARC-AGI-2"
score = 72.1
metric = "accuracy"
source = "https://deepmind.google/models/gemini/flash/"
date = "2026-05-19"
[[benchmarks]]
name = "GDPval-AA"
score = 1656
metric = "Elo"
source = "https://deepmind.google/models/gemini/flash/"
date = "2026-05-19"
@@ -0,0 +1,24 @@
# Sources:
# - https://ai.google.dev/gemini-api/docs/models/gemini-3.5-live-translate-preview
# - https://ai.google.dev/gemini-api/docs/live-api/live-translate
# - https://deepmind.google/models/model-cards/gemini-3-5-audio/
# - https://blog.google/innovation-and-ai/models-and-research/gemini-models/gemini-live-3-5-translate/
name = "Gemini 3.5 Live Translate Preview"
description = "Low-latency audio-to-audio model for real-time speech translation across 70+ languages"
family = "gemini-pro"
release_date = "2026-06-09"
last_updated = "2026-06-09"
attachment = false
reasoning = false
temperature = false
tool_call = false
knowledge = "2025-01"
open_weights = false
[limit]
context = 131_072
output = 65_536
[modalities]
input = ["audio"]
output = ["audio", "text"]
+20
View File
@@ -0,0 +1,20 @@
name = "Gemini 3.6 Flash"
description = "Fast Gemini model balancing multimodal reasoning, tool use, and cost"
family = "gemini-flash"
release_date = "2026-07-21"
last_updated = "2026-07-21"
attachment = true
reasoning = true
temperature = true
tool_call = true
structured_output = true
knowledge = "2026-03"
open_weights = false
[limit]
context = 1_048_576
output = 65_536
[modalities]
input = ["text", "image", "video", "audio", "pdf"]
output = ["text"]
+19
View File
@@ -0,0 +1,19 @@
name = "Gemini Embedding 2"
description = "Multimodal embedding model mapping text, images, video, audio, and PDFs into a unified embedding space"
family = "gemini"
release_date = "2026-04-22"
last_updated = "2026-04-22"
attachment = true
reasoning = false
temperature = false
tool_call = false
knowledge = "2025-11"
open_weights = false
[limit]
context = 8_192
output = 3_072
[modalities]
input = ["text", "image", "audio", "video", "pdf"]
output = ["text"]
+4 -3
View File
@@ -1,8 +1,9 @@
# Tracks the current Gemini Flash release (gemini-3.5-flash).
name = "Gemini Flash Latest"
description = "Fast Gemini model balancing multimodal reasoning, tool use, and cost"
family = "gemini-flash"
release_date = "2025-09-25"
last_updated = "2025-09-25"
release_date = "2026-05-19"
last_updated = "2026-05-19"
attachment = true
reasoning = true
temperature = true
@@ -16,5 +17,5 @@ context = 1_048_576
output = 65_536
[modalities]
input = ["text", "image", "audio", "video", "pdf"]
input = ["text", "image", "video", "audio", "pdf"]
output = ["text"]
+4 -3
View File
@@ -1,8 +1,9 @@
# Tracks the current Gemini Flash-Lite release (gemini-3.1-flash-lite).
name = "Gemini Flash-Lite Latest"
description = "Low-latency Gemini model for high-volume multimodal and agent workloads"
family = "gemini-flash-lite"
release_date = "2025-09-25"
last_updated = "2025-09-25"
release_date = "2026-05-07"
last_updated = "2026-05-07"
attachment = true
reasoning = true
temperature = true
@@ -16,5 +17,5 @@ context = 1_048_576
output = 65_536
[modalities]
input = ["text", "image", "audio", "video", "pdf"]
input = ["text", "image", "video", "audio", "pdf"]
output = ["text"]
@@ -15,3 +15,10 @@ output = 57_920
[modalities]
input = ["text", "image", "video"]
output = ["video"]
[[benchmarks]]
name = "LMArena Text-to-Video Arena"
score = 1527
metric = "Elo"
source = "https://venturebeat.com/technology/googles-gemini-omni-flash-hits-the-api-turning-enterprise-video-production-into-a-conversation"
date = "2026-06-30"
@@ -0,0 +1,26 @@
# Sources:
# - https://ai.google.dev/gemini-api/docs/models/gemini-robotics-er-1.6-preview
# - https://ai.google.dev/gemini-api/docs/robotics-overview
# - https://blog.google/innovation-and-ai/models-and-research/google-deepmind/gemini-robotics-er-1-6
# - https://storage.googleapis.com/deepmind-media/Model-Cards/Gemini-Robotics-ER-1-6-Model-Card.pdf
name = "Gemini Robotics-ER 1.6 Preview"
description = "Vision-language model for embodied reasoning: spatial understanding, task planning, and physical-world agentic robotics"
family = "gemini"
release_date = "2026-04-14"
last_updated = "2026-04-14"
attachment = true
reasoning = true
temperature = true
tool_call = true
structured_output = true
knowledge = "2025-01"
open_weights = false
[limit]
context = 131_072
output = 65_536
[modalities]
input = ["text", "image", "video", "audio"]
output = ["text"]
+25
View File
@@ -0,0 +1,25 @@
# https://ai.google.dev/gemini-api/docs/models/lyria-3-clip-preview
# https://ai.google.dev/gemini-api/docs/music-generation
# https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/lyria/lyria-3
# https://ai.google.dev/gemini-api/docs/pricing
# https://cloud.google.com/gemini-enterprise-agent-platform/generative-ai/pricing
name = "Lyria 3 Clip Preview"
description = "Music generation model for short 30-second clips, loops, and previews from text or image prompts"
family = "lyria"
release_date = "2026-03-25"
last_updated = "2026-03-25"
attachment = true
reasoning = false
temperature = true
tool_call = false
structured_output = false
open_weights = false
[limit]
context = 131_072
output = 65_536
[modalities]
input = ["text", "image"]
output = ["text", "audio"]
+26
View File
@@ -0,0 +1,26 @@
# Sources:
# - https://ai.google.dev/gemini-api/docs/models/lyria-3-pro-preview — model card: text+image in; audio+lyrics text out; input token limit 131,072; no tools/thinking/structured output/caching
# - https://ai.google.dev/gemini-api/docs/music-generation — full-length song generation; MP3 (WAV optional); lyrics/structure text in responses
# - https://docs.cloud.google.com/vertex-ai/generative-ai/docs/models/lyria/lyria-3 — release_date 2026-03-25; preview; text+image input; audio output; max ~184s
# - https://blog.google/innovation-and-ai/technology/developers-tools/lyria-3-developers/ — public preview announcement (2026-03-25)
# Output token limit not published on the first-party model card; 8_192 retained from LiteLLM cost map pending Models API sync overwrite.
name = "Lyria 3 Pro Preview"
description = "Music generation model for full-length songs from text or images with vocals and structure"
family = "lyria"
release_date = "2026-03-25"
last_updated = "2026-03-25"
attachment = true
reasoning = false
temperature = true
tool_call = false
structured_output = false
open_weights = false
[limit]
context = 131_072
output = 8_192
[modalities]
input = ["text", "image"]
output = ["text", "audio"]
@@ -0,0 +1,18 @@
name = "Veo 3.1 Fast Preview"
description = "Video model for prompt-guided generation, editing, and motion workflows"
family = "veo"
release_date = "2025-10-15"
last_updated = "2026-01-01"
attachment = true
reasoning = false
temperature = false
tool_call = false
open_weights = false
[limit]
context = 1_024
output = 0
[modalities]
input = ["text", "image", "video"]
output = ["video"]
@@ -0,0 +1,23 @@
# Sources:
# - https://ai.google.dev/gemini-api/docs/models/veo-3.1-generate-preview
# - https://ai.google.dev/gemini-api/docs/veo
# - https://developers.googleblog.com/introducing-veo-3-1-and-new-creative-capabilities-in-the-gemini-api
name = "Veo 3.1 Preview"
description = "Video model for prompt-guided generation, editing, and motion workflows"
family = "veo"
release_date = "2025-10-15"
last_updated = "2026-01"
attachment = true
reasoning = false
temperature = false
tool_call = false
open_weights = false
[limit]
context = 1_024
output = 1
[modalities]
input = ["text", "image"]
output = ["video"]
@@ -0,0 +1,26 @@
# Sources:
# - https://ai.google.dev/gemini-api/docs/models/veo-3.1-lite-generate-preview
# (model code, text+image input, video+audio output, 1,024 text input tokens, March 2026 update)
# - https://blog.google/innovation-and-ai/technology/ai/veo-3-1-lite/
# (release 2026-03-31; text-to-video and image-to-video; 720p/1080p; 4s/6s/8s)
# - https://ai.google.dev/gemini-api/docs/pricing
# (Veo 3.1 Lite paid-tier per-second video pricing; not token-based — cost omitted)
name = "Veo 3.1 Lite Preview"
description = "Video model for prompt-guided generation, editing, and motion workflows"
family = "veo"
release_date = "2026-03-31"
last_updated = "2026-03-31"
attachment = true
reasoning = false
temperature = false
tool_call = false
open_weights = false
[limit]
context = 1_024
output = 0
[modalities]
input = ["text", "image"]
output = ["video"]
+50
View File
@@ -16,3 +16,53 @@ output = 131_072
[modalities]
input = ["text"]
output = ["text"]
[[benchmarks]]
name = "SWE-Bench Pro"
score = 59.5
metric = "resolve rate"
source = "https://github.com/meituan-longcat/longcat-2.0"
date = "2026-06-30"
[[benchmarks]]
name = "SWE-Bench Multilingual"
score = 77.3
metric = "resolve rate"
source = "https://github.com/meituan-longcat/longcat-2.0"
date = "2026-06-30"
[[benchmarks]]
name = "Terminal-Bench"
score = 70.8
metric = "success rate"
version = "2.1"
source = "https://github.com/meituan-longcat/longcat-2.0"
date = "2026-06-30"
[[benchmarks]]
name = "GPQA Diamond"
score = 88.9
metric = "accuracy"
source = "https://github.com/meituan-longcat/longcat-2.0"
date = "2026-06-30"
[[benchmarks]]
name = "BrowseComp"
score = 79.9
metric = "accuracy"
source = "https://github.com/meituan-longcat/longcat-2.0"
date = "2026-06-30"
[[benchmarks]]
name = "IFEval"
score = 90.0
metric = "accuracy"
source = "https://github.com/meituan-longcat/longcat-2.0"
date = "2026-06-30"
[[benchmarks]]
name = "FORTE"
score = 73.2
metric = "success rate"
source = "https://github.com/meituan-longcat/longcat-2.0"
date = "2026-06-30"
+81
View File
@@ -17,3 +17,84 @@ output = 32_000
[modalities]
input = ["text", "image", "pdf", "video"]
output = ["text"]
[[benchmarks]]
name = "SWE-Bench Pro"
score = 61.5
metric = "resolve rate"
source = "https://ai.meta.com/blog/introducing-muse-spark-meta-model-api/"
date = "2026-07-09"
[[benchmarks]]
name = "Terminal-Bench"
score = 80.0
metric = "success rate"
version = "2.1"
source = "https://ai.meta.com/blog/introducing-muse-spark-meta-model-api/"
date = "2026-07-09"
[[benchmarks]]
name = "DeepSWE"
score = 53.3
metric = "resolve rate"
version = "1.1"
source = "https://ai.meta.com/blog/introducing-muse-spark-meta-model-api/"
date = "2026-07-09"
[[benchmarks]]
name = "MCP Atlas"
score = 88.1
metric = "success rate"
source = "https://ai.meta.com/blog/introducing-muse-spark-meta-model-api/"
date = "2026-07-09"
[[benchmarks]]
name = "JobBench"
score = 54.7
metric = "success rate"
source = "https://ai.meta.com/blog/introducing-muse-spark-meta-model-api/"
date = "2026-07-09"
[[benchmarks]]
name = "Toolathlon-Verified"
score = 75.6
metric = "success rate"
source = "https://ai.meta.com/blog/introducing-muse-spark-meta-model-api/"
date = "2026-07-09"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 62.1
metric = "accuracy"
variant = "with tools"
source = "https://ai.meta.com/blog/introducing-muse-spark-meta-model-api/"
date = "2026-07-09"
[[benchmarks]]
name = "OSWorld-Verified"
score = 80.8
metric = "success rate"
source = "https://ai.meta.com/blog/introducing-muse-spark-meta-model-api/"
date = "2026-07-09"
[[benchmarks]]
name = "Finance Agent"
score = 57.2
metric = "accuracy"
version = "v2"
source = "https://ai.meta.com/blog/introducing-muse-spark-meta-model-api/"
date = "2026-07-09"
[[benchmarks]]
name = "CharXiv Reasoning"
score = 88.4
metric = "accuracy"
source = "https://ai.meta.com/blog/introducing-muse-spark-meta-model-api/"
date = "2026-07-09"
[[benchmarks]]
name = "BabyVision"
score = 76.3
metric = "accuracy"
source = "https://ai.meta.com/blog/introducing-muse-spark-meta-model-api/"
date = "2026-07-09"
+27
View File
@@ -28,3 +28,30 @@ type = "model_card"
label = "Announcement"
url = "https://microsoft.ai/news/introducingmai-code-1-flash/"
type = "announcement"
[[benchmarks]]
name = "SWE-Bench Pro"
score = 51.2
metric = "resolve rate"
harness = "GitHub Copilot"
source = "https://microsoft.ai/news/introducingmai-code-1-flash/"
date = "2026-06-02"
[[benchmarks]]
name = "SWE-Bench Verified"
score = 71.6
metric = "resolved"
source = "https://llm-stats.com/benchmarks/swe-bench-verified"
[[benchmarks]]
name = "Terminal-Bench"
score = 54.8
metric = "success rate"
version = "2.0"
source = "https://llm-stats.com/benchmarks/terminal-bench-2"
[[benchmarks]]
name = "GPQA Diamond"
score = 84.6
metric = "accuracy"
source = "https://llm-stats.com/benchmarks/gpqa"
+24
View File
@@ -20,3 +20,27 @@ output = ["text"]
[[weights]]
label = "Hugging Face"
url = "https://huggingface.co/MiniMaxAI/MiniMax-M2.7"
[[benchmarks]]
name = "SWE-Bench Verified"
score = 79.9
metric = "resolved"
harness = "Claude Code"
source = "https://www.minimax.io/blog/minimax-m3"
date = "2026-06-01"
[[benchmarks]]
name = "SWE-Bench Pro"
score = 56.2
metric = "resolve rate"
harness = "Claude Code"
source = "https://www.minimax.io/blog/minimax-m3"
date = "2026-06-01"
[[benchmarks]]
name = "Terminal-Bench"
score = 51.1
metric = "success rate"
version = "2.1"
source = "https://www.minimax.io/blog/minimax-m3"
date = "2026-06-01"
+45
View File
@@ -20,3 +20,48 @@ output = ["text"]
[[weights]]
label = "Hugging Face"
url = "https://huggingface.co/MiniMaxAI/MiniMax-M3"
[[benchmarks]]
name = "SWE-Bench Verified"
score = 80.5
metric = "resolved"
harness = "Claude Code"
source = "https://www.minimax.io/blog/minimax-m3"
date = "2026-06-01"
[[benchmarks]]
name = "SWE-Bench Pro"
score = 59.0
metric = "resolve rate"
harness = "Claude Code"
source = "https://www.minimax.io/blog/minimax-m3"
date = "2026-06-01"
[[benchmarks]]
name = "Terminal-Bench"
score = 66.0
metric = "success rate"
version = "2.1"
source = "https://www.minimax.io/blog/minimax-m3"
date = "2026-06-01"
[[benchmarks]]
name = "BrowseComp"
score = 83.52
metric = "accuracy"
source = "https://www.minimax.io/blog/minimax-m3"
date = "2026-06-01"
[[benchmarks]]
name = "MCP Atlas"
score = 74.2
metric = "success rate"
source = "https://www.minimax.io/blog/minimax-m3"
date = "2026-06-01"
[[benchmarks]]
name = "OSWorld-Verified"
score = 70.06
metric = "success rate"
source = "https://www.minimax.io/blog/minimax-m3"
date = "2026-06-01"
+1 -1
View File
@@ -3,7 +3,7 @@ description = "Earlier Kimi frontier model for long-context agents, coding, and
family = "kimi-k2"
release_date = "2026-01"
last_updated = "2026-01"
attachment = false
attachment = true
reasoning = true
temperature = false
tool_call = true
+45
View File
@@ -22,3 +22,48 @@ output = ["text"]
[[weights]]
label = "Hugging Face"
url = "https://huggingface.co/moonshotai/Kimi-K2.7-Code"
[[benchmarks]]
name = "Kimi Code Bench"
score = 62.0
harness = "Kimi Code CLI"
version = "v2"
source = "https://huggingface.co/moonshotai/Kimi-K2.7-Code"
date = "2026-06-12"
[[benchmarks]]
name = "Program Bench"
score = 53.6
harness = "Kimi Code CLI"
source = "https://huggingface.co/moonshotai/Kimi-K2.7-Code"
date = "2026-06-12"
[[benchmarks]]
name = "MLS Bench Lite"
score = 35.1
harness = "Kimi Code CLI"
source = "https://huggingface.co/moonshotai/Kimi-K2.7-Code"
date = "2026-06-12"
[[benchmarks]]
name = "MCP Atlas"
score = 76.0
metric = "success rate"
harness = "Kimi Code CLI"
source = "https://huggingface.co/moonshotai/Kimi-K2.7-Code"
date = "2026-06-12"
[[benchmarks]]
name = "MCP Mark Verified"
score = 81.1
metric = "success rate"
harness = "Kimi Code CLI"
source = "https://huggingface.co/moonshotai/Kimi-K2.7-Code"
date = "2026-06-12"
[[benchmarks]]
name = "Kimi Claw 24/7 Bench"
score = 46.9
harness = "Kimi Code CLI"
source = "https://huggingface.co/moonshotai/Kimi-K2.7-Code"
date = "2026-06-12"
+19
View File
@@ -0,0 +1,19 @@
name = "Kimi K3"
description = "Multimodal Kimi model with 1M context and toggleable max-effort thinking for long-horizon agent work"
family = "kimi-k3"
release_date = "2026-07-16"
last_updated = "2026-07-16"
attachment = true
reasoning = true
temperature = false
tool_call = true
structured_output = true
open_weights = true
[limit]
context = 1_048_576
output = 131_072
[modalities]
input = ["text", "image", "video"]
output = ["text"]
@@ -16,3 +16,86 @@ output = 128_000
[modalities]
input = ["text"]
output = ["text"]
[[benchmarks]]
name = "SWE-Bench Verified"
score = 70.7
metric = "resolved"
source = "https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-BF16"
date = "2026-06-04"
[[benchmarks]]
name = "SWE-Bench Multilingual"
score = 67.7
metric = "resolve rate"
source = "https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-BF16"
date = "2026-06-04"
[[benchmarks]]
name = "Terminal-Bench"
score = 56.4
metric = "success rate"
version = "2.1"
source = "https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-BF16"
date = "2026-06-04"
[[benchmarks]]
name = "GPQA"
score = 87.0
metric = "accuracy"
variant = "no tools"
source = "https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-BF16"
date = "2026-06-04"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 26.7
metric = "accuracy"
variant = "no tools"
source = "https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-BF16"
date = "2026-06-04"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 37.4
metric = "accuracy"
variant = "with tools"
source = "https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-BF16"
date = "2026-06-04"
[[benchmarks]]
name = "LiveCodeBench"
score = 89.0
metric = "pass@1"
version = "v6"
source = "https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-BF16"
date = "2026-06-04"
[[benchmarks]]
name = "MMLU-Pro"
score = 86.8
metric = "accuracy"
source = "https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-BF16"
date = "2026-06-04"
[[benchmarks]]
name = "BrowseComp"
score = 44.4
metric = "accuracy"
source = "https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-BF16"
date = "2026-06-04"
[[benchmarks]]
name = "IFBench"
score = 81.7
metric = "accuracy"
variant = "prompt loose"
source = "https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-BF16"
date = "2026-06-04"
[[benchmarks]]
name = "GDPval"
score = 46.7
metric = "wins or ties"
source = "https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-BF16"
date = "2026-06-04"
+84
View File
@@ -19,3 +19,87 @@ output = 128_000
[modalities]
input = ["text", "image"]
output = ["text"]
[[benchmarks]]
name = "GPQA Diamond"
score = 94.4
metric = "accuracy"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 42.7
metric = "accuracy"
variant = "no tools"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 58.7
metric = "accuracy"
variant = "with tools"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "BrowseComp"
score = 89.3
metric = "accuracy"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "GDPval"
score = 82.0
metric = "wins or ties"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "FrontierMath"
score = 50.0
metric = "accuracy"
dataset = "Tier 1-3"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "FrontierMath"
score = 38.0
metric = "accuracy"
dataset = "Tier 4"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "ARC-AGI-1"
score = 94.5
metric = "accuracy"
variant = "Verified"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "ARC-AGI-2"
score = 83.3
metric = "accuracy"
variant = "Verified"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "FinanceAgent"
score = 61.5
metric = "accuracy"
version = "1.1"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "GeneBench"
score = 25.6
metric = "accuracy"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
+84
View File
@@ -129,3 +129,87 @@ harness = "Cursor CLI"
variant = "medium"
version = "2.1"
source = "https://artificialanalysis.ai/agents/coding-agents"
[[benchmarks]]
name = "Terminal-Bench"
score = 75.1
metric = "success rate"
version = "2.0"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "GPQA Diamond"
score = 92.8
metric = "accuracy"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 39.8
metric = "accuracy"
variant = "no tools"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 52.1
metric = "accuracy"
variant = "with tools"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "OSWorld-Verified"
score = 75.0
metric = "success rate"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "BrowseComp"
score = 82.7
metric = "accuracy"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "GDPval"
score = 83.0
metric = "wins or ties"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "ARC-AGI-2"
score = 73.3
metric = "accuracy"
variant = "Verified"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "FrontierMath"
score = 47.6
metric = "accuracy"
dataset = "Tier 1-3"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "FrontierMath"
score = 27.1
metric = "accuracy"
dataset = "Tier 4"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "MMMU Pro"
score = 81.2
metric = "accuracy"
variant = "no tools"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
+53
View File
@@ -19,3 +19,56 @@ output = 128_000
[modalities]
input = ["text", "image", "pdf"]
output = ["text"]
[[benchmarks]]
name = "BrowseComp"
score = 90.1
metric = "accuracy"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 43.1
metric = "accuracy"
variant = "no tools"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 57.2
metric = "accuracy"
variant = "with tools"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "FrontierMath"
score = 52.4
metric = "accuracy"
dataset = "Tier 1-3"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "FrontierMath"
score = 39.6
metric = "accuracy"
dataset = "Tier 4"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "GDPval"
score = 82.3
metric = "wins or ties"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "GeneBench"
score = 33.2
metric = "accuracy"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
+106
View File
@@ -158,3 +158,109 @@ harness = "Cursor CLI"
variant = "medium"
version = "2.1"
source = "https://artificialanalysis.ai/agents/coding-agents"
[[benchmarks]]
name = "Terminal-Bench"
score = 82.7
metric = "success rate"
version = "2.0"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "GPQA Diamond"
score = 93.6
metric = "accuracy"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 41.4
metric = "accuracy"
variant = "no tools"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 52.2
metric = "accuracy"
variant = "with tools"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "OSWorld-Verified"
score = 78.7
metric = "success rate"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "BrowseComp"
score = 84.4
metric = "accuracy"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "MMMU Pro"
score = 81.2
metric = "accuracy"
variant = "no tools"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "ARC-AGI-2"
score = 85.0
metric = "accuracy"
variant = "Verified"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "FrontierMath"
score = 51.7
metric = "accuracy"
dataset = "Tier 1-3"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "FrontierMath"
score = 35.4
metric = "accuracy"
dataset = "Tier 4"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "GDPval"
score = 84.9
metric = "wins or ties"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "MCP Atlas"
score = 75.3
metric = "success rate"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "Toolathlon"
score = 55.6
metric = "success rate"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
[[benchmarks]]
name = "τ²-Bench Telecom"
score = 98.0
metric = "success rate"
variant = "original prompts"
source = "https://openai.com/index/introducing-gpt-5-5/"
date = "2026-04-23"
+95 -1
View File
@@ -1,6 +1,6 @@
name = "GPT-5.6 Luna"
description = "Cost-efficient GPT-5.6 model for fast, high-volume workloads"
family = "gpt-nano"
family = "gpt-luna"
release_date = "2026-07-09"
last_updated = "2026-07-09"
attachment = true
@@ -19,3 +19,97 @@ output = 128_000
[modalities]
input = ["text", "image", "pdf"]
output = ["text"]
[[benchmarks]]
name = "SWE-Bench Pro"
score = 62.7
metric = "resolve rate"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "Terminal-Bench"
score = 84.7
metric = "success rate"
version = "2.1"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "DeepSWE"
score = 67.2
metric = "resolve rate"
version = "1.1"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "GPQA Diamond"
score = 92.3
metric = "accuracy"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "FrontierMath"
score = 78.6
metric = "accuracy"
dataset = "Tier 1-3"
version = "v2"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "BrowseComp"
score = 83.3
metric = "accuracy"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "OSWorld"
score = 45.6
metric = "success rate"
version = "2.0"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "MMMU Pro"
score = 78.4
metric = "accuracy"
variant = "no tools"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "Agents' Last Exam"
score = 50.3
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "Toolathlon"
score = 53.4
metric = "success rate"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "Artificial Analysis Intelligence Index"
score = 51.2
metric = "index score"
variant = "max"
version = "4.1"
source = "https://artificialanalysis.ai/articles/gpt-5-6-has-landed"
date = "2026-07-09"
[[benchmarks]]
name = "Artificial Analysis Coding Agent Index"
score = 74.6
metric = "index score"
harness = "Codex"
variant = "max"
version = "1.1"
source = "https://artificialanalysis.ai/articles/gpt-5-6-has-landed"
date = "2026-07-09"
+95 -1
View File
@@ -1,6 +1,6 @@
name = "GPT-5.6 Sol"
description = "Frontier GPT-5.6 model for complex professional work, coding, and agentic workflows"
family = "gpt"
family = "gpt-sol"
release_date = "2026-07-09"
last_updated = "2026-07-09"
attachment = true
@@ -19,3 +19,97 @@ output = 128_000
[modalities]
input = ["text", "image", "pdf"]
output = ["text"]
[[benchmarks]]
name = "SWE-Bench Pro"
score = 64.6
metric = "resolve rate"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "Terminal-Bench"
score = 88.8
metric = "success rate"
version = "2.1"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "DeepSWE"
score = 72.7
metric = "resolve rate"
version = "1.1"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "GPQA Diamond"
score = 94.6
metric = "accuracy"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "FrontierMath"
score = 89
metric = "accuracy"
dataset = "Tier 1-3"
version = "v2"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "BrowseComp"
score = 90.4
metric = "accuracy"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "OSWorld"
score = 62.6
metric = "success rate"
version = "2.0"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "MMMU Pro"
score = 83
metric = "accuracy"
variant = "no tools"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "Agents' Last Exam"
score = 52.7
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "Toolathlon"
score = 58
metric = "success rate"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "Artificial Analysis Intelligence Index"
score = 58.9
metric = "index score"
variant = "max"
version = "4.1"
source = "https://artificialanalysis.ai/articles/gpt-5-6-has-landed"
date = "2026-07-09"
[[benchmarks]]
name = "Artificial Analysis Coding Agent Index"
score = 80
metric = "index score"
harness = "Codex"
variant = "max"
version = "1.1"
source = "https://artificialanalysis.ai/articles/gpt-5-6-has-landed"
date = "2026-07-09"
+95 -1
View File
@@ -1,6 +1,6 @@
name = "GPT-5.6 Terra"
description = "Balanced GPT-5.6 model for capable, cost-efficient everyday work"
family = "gpt-mini"
family = "gpt-terra"
release_date = "2026-07-09"
last_updated = "2026-07-09"
attachment = true
@@ -19,3 +19,97 @@ output = 128_000
[modalities]
input = ["text", "image", "pdf"]
output = ["text"]
[[benchmarks]]
name = "SWE-Bench Pro"
score = 63.4
metric = "resolve rate"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "Terminal-Bench"
score = 87.4
metric = "success rate"
version = "2.1"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "DeepSWE"
score = 69.6
metric = "resolve rate"
version = "1.1"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "GPQA Diamond"
score = 92.9
metric = "accuracy"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "FrontierMath"
score = 84.9
metric = "accuracy"
dataset = "Tier 1-3"
version = "v2"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "BrowseComp"
score = 87.5
metric = "accuracy"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "OSWorld"
score = 50.2
metric = "success rate"
version = "2.0"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "MMMU Pro"
score = 80.7
metric = "accuracy"
variant = "no tools"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "Agents' Last Exam"
score = 50.4
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "Toolathlon"
score = 53.1
metric = "success rate"
source = "https://openai.com/index/gpt-5-6/"
date = "2026-07-09"
[[benchmarks]]
name = "Artificial Analysis Intelligence Index"
score = 55
metric = "index score"
variant = "max"
version = "4.1"
source = "https://artificialanalysis.ai/articles/gpt-5-6-has-landed"
date = "2026-07-09"
[[benchmarks]]
name = "Artificial Analysis Coding Agent Index"
score = 77.4
metric = "index score"
harness = "Codex"
variant = "max"
version = "1.1"
source = "https://artificialanalysis.ai/articles/gpt-5-6-has-landed"
date = "2026-07-09"
+21
View File
@@ -0,0 +1,21 @@
name = "GPT-Realtime-2.1"
description = "Realtime speech-to-speech model with configurable reasoning, tool use, and robust voice-agent behavior"
family = "gpt"
release_date = "2026-07-06"
last_updated = "2026-07-06"
attachment = true
reasoning = true
temperature = false
tool_call = true
structured_output = false
knowledge = "2024-09-30"
open_weights = false
[limit]
context = 128_000
input = 96_000
output = 32_000
[modalities]
input = ["text", "audio", "image"]
output = ["text", "audio"]
+18
View File
@@ -0,0 +1,18 @@
name = "GPT Realtime Whisper"
description = "Streaming speech-to-text model for low-latency transcript deltas from live audio"
family = "whisper"
release_date = "2026-05-07"
last_updated = "2026-05-07"
attachment = false
reasoning = false
temperature = true
tool_call = false
open_weights = false
[limit]
context = 0
output = 0
[modalities]
input = ["audio"]
output = ["text"]
+1 -1
View File
@@ -1,5 +1,5 @@
name = "Laguna M.1"
description = "Poolside's flagship agentic coding model for long-horizon work"
description = "Poolside's open-weight model for agentic coding and long-horizon work"
family = "laguna"
release_date = "2026-04-28"
last_updated = "2026-06-13"
+19
View File
@@ -0,0 +1,19 @@
name = "Laguna S 2.1"
description = "Agentic coding model from Poolside in the XS size class for local deployment"
family = "laguna"
release_date = "2026-07-21"
last_updated = "2026-07-21"
attachment = false
reasoning = true
temperature = true
tool_call = true
structured_output = false
open_weights = true
[limit]
context = 1_048_576
output = 32_768
[modalities]
input = ["text"]
output = ["text"]
+33
View File
@@ -17,3 +17,36 @@ output = 32_768
[modalities]
input = ["text"]
output = ["text"]
[[benchmarks]]
name = "SWE-Bench Verified"
score = 70.9
metric = "resolved"
harness = "Harbor"
source = "https://poolside.ai/blog/introducing-laguna-xs-2-1"
date = "2026-07-02"
[[benchmarks]]
name = "SWE-Bench Multilingual"
score = 63.1
metric = "resolve rate"
harness = "Harbor"
source = "https://poolside.ai/blog/introducing-laguna-xs-2-1"
date = "2026-07-02"
[[benchmarks]]
name = "SWE-Bench Pro"
score = 47.6
metric = "resolve rate"
harness = "Harbor"
source = "https://poolside.ai/blog/introducing-laguna-xs-2-1"
date = "2026-07-02"
[[benchmarks]]
name = "Terminal-Bench"
score = 37.5
metric = "success rate"
harness = "Harbor"
version = "2.0"
source = "https://poolside.ai/blog/introducing-laguna-xs-2-1"
date = "2026-07-02"
+82 -2
View File
@@ -6,7 +6,7 @@ attachment = true
reasoning = true
temperature = true
tool_call = true
knowledge = "2026-01-01"
knowledge = "2026-03-01"
open_weights = true
[limit]
@@ -15,9 +15,89 @@ input = 256_000
output = 256_000
[modalities]
input = ["text", "image"]
input = ["text", "image", "video"]
output = ["text"]
[[weights]]
label = "Hugging Face"
url = "https://huggingface.co/stepfun-ai/Step-3.7-Flash"
[[benchmarks]]
name = "SWE-Bench Pro"
score = 56.3
metric = "resolve rate"
source = "https://static.stepfun.com/blog/step-3.7-flash/"
date = "2026-05-29"
[[benchmarks]]
name = "SWE-Bench Verified"
score = 76.5
metric = "resolved"
source = "https://static.stepfun.com/blog/step-3.7-flash/"
date = "2026-05-29"
[[benchmarks]]
name = "Terminal-Bench"
score = 59.6
metric = "success rate"
version = "2.1"
source = "https://static.stepfun.com/blog/step-3.7-flash/"
date = "2026-05-29"
[[benchmarks]]
name = "Humanity's Last Exam"
score = 47.2
metric = "accuracy"
variant = "with tools"
source = "https://static.stepfun.com/blog/step-3.7-flash/"
date = "2026-05-29"
[[benchmarks]]
name = "BrowseComp"
score = 75.8
metric = "accuracy"
source = "https://static.stepfun.com/blog/step-3.7-flash/"
date = "2026-05-29"
[[benchmarks]]
name = "Toolathlon"
score = 49.5
metric = "success rate"
source = "https://static.stepfun.com/blog/step-3.7-flash/"
date = "2026-05-29"
[[benchmarks]]
name = "GDPval"
score = 45.8
metric = "wins or ties"
source = "https://static.stepfun.com/blog/step-3.7-flash/"
date = "2026-05-29"
[[benchmarks]]
name = "ClawEval"
score = 67.1
metric = "pass^3"
version = "1.1"
source = "https://static.stepfun.com/blog/step-3.7-flash/"
date = "2026-05-29"
[[benchmarks]]
name = "Artificial Analysis Coding Index"
score = 37.1
metric = "index"
source = "https://openrouter.ai/stepfun/step-3.7-flash/benchmarks"
date = "2026-06-15"
[[benchmarks]]
name = "SciCode"
score = 40.0
metric = "percent correct"
source = "https://openrouter.ai/stepfun/step-3.7-flash/benchmarks"
date = "2026-06-15"
[[benchmarks]]
name = "Terminal-Bench Hard"
score = 35.6
metric = "success rate"
source = "https://openrouter.ai/stepfun/step-3.7-flash/benchmarks"
date = "2026-06-15"
@@ -1,27 +1,28 @@
name = "Hy3 (free)"
name = "Hy3"
description = "Tencent Hy reasoning model for coding, instruction following, and agent tasks"
family = "hy3"
family = "Hy"
release_date = "2026-07-06"
last_updated = "2026-07-06"
attachment = false
reasoning = true
temperature = true
tool_call = true
structured_output = true
open_weights = true
[[reasoning_options]]
type = "effort"
values = ["none", "low", "high"]
[cost]
input = 0
output = 0
[limit]
context = 262_144
output = 262_144
context = 256_000
output = 64_000
[modalities]
input = ["text"]
output = ["text"]
[[weights]]
label = "Hugging Face"
url = "https://huggingface.co/tencent/Hy3"
[[benchmarks]]
name = "SWE-Bench Verified"
score = 78
metric = "resolved"
source = "https://huggingface.co/tencent/Hy3"
+27
View File
@@ -0,0 +1,27 @@
# Sources (accessed 2026-07-22):
# - https://thinkingmachines.ai/news/introducing-inkling/
# - https://thinkingmachines.ai/model-card/inkling/
# - https://huggingface.co/thinkingmachines/Inkling
name = "Inkling"
description = "Multimodal MoE reasoning model (975B total, 41B active) for text, image, and audio"
family = "ling"
release_date = "2026-07-15"
last_updated = "2026-07-15"
attachment = true
reasoning = true
temperature = true
tool_call = true
open_weights = true
license = "Apache-2.0"
[limit]
context = 1_048_576
[modalities]
input = ["text", "image", "audio"]
output = ["text"]
[[weights]]
label = "Hugging Face"
url = "https://huggingface.co/thinkingmachines/Inkling"
+29
View File
@@ -17,3 +17,32 @@ output = 30_000
[modalities]
input = ["text", "image", "pdf"]
output = ["text"]
[[benchmarks]]
name = "Artificial Analysis Intelligence Index"
score = 53
metric = "index score"
version = "4.0"
source = "https://artificialanalysis.ai/articles/xai-launches-grok-4-3-with-improved-agentic-performance-and-lower-pricing"
date = "2026-04-30"
[[benchmarks]]
name = "GDPval-AA"
score = 1500
metric = "Elo"
source = "https://artificialanalysis.ai/articles/xai-launches-grok-4-3-with-improved-agentic-performance-and-lower-pricing"
date = "2026-04-30"
[[benchmarks]]
name = "τ²-Bench Telecom"
score = 98
metric = "success rate"
source = "https://artificialanalysis.ai/articles/xai-launches-grok-4-3-with-improved-agentic-performance-and-lower-pricing"
date = "2026-04-30"
[[benchmarks]]
name = "IFBench"
score = 81
metric = "accuracy"
source = "https://artificialanalysis.ai/articles/xai-launches-grok-4-3-with-improved-agentic-performance-and-lower-pricing"
date = "2026-04-30"
+39
View File
@@ -17,3 +17,42 @@ output = 500_000
[modalities]
input = ["text", "image"]
output = ["text"]
[[benchmarks]]
name = "SWE-Bench Pro"
score = 64.7
metric = "resolve rate"
source = "https://x.ai/news/grok-4-5"
date = "2026-07-08"
[[benchmarks]]
name = "SWE-Bench Multilingual"
score = 78
metric = "resolve rate"
source = "https://x.ai/news/grok-4-5"
date = "2026-07-08"
[[benchmarks]]
name = "Terminal-Bench"
score = 83.3
metric = "success rate"
version = "2.1"
source = "https://x.ai/news/grok-4-5"
date = "2026-07-08"
[[benchmarks]]
name = "DeepSWE"
score = 62.0
metric = "resolve rate"
version = "1.0"
source = "https://x.ai/news/grok-4-5"
date = "2026-07-08"
[[benchmarks]]
name = "DeepSWE"
score = 53
metric = "resolve rate"
harness = "mini-swe-agent"
version = "1.1"
source = "https://x.ai/news/grok-4-5"
date = "2026-07-08"
+23
View File
@@ -0,0 +1,23 @@
# Sources:
# - https://docs.x.ai/docs/models
# - https://docs.x.ai/developers/models/grok-imagine-video-1.5
# - https://docs.x.ai/docs/guides/video-generation
name = "Grok Imagine Video 1.5"
description = "Video model for image-to-video generation, editing, and extension workflows"
family = "grok"
release_date = "2026-05-30"
last_updated = "2026-05-30"
attachment = true
reasoning = false
temperature = false
tool_call = false
open_weights = false
[limit]
context = 1_024
output = 0
[modalities]
input = ["text", "image", "video"]
output = ["video"]
+14
View File
@@ -27,3 +27,17 @@ name = "SWE-Bench Verified"
score = 78.9
metric = "resolved"
source = "https://huggingface.co/XiaomiMiMo/MiMo-V2.5-Pro"
[[benchmarks]]
name = "SWE-Bench Pro"
score = 57.2
metric = "resolve rate"
source = "https://mimo.xiaomi.com/mimo-v2-5-pro/"
date = "2026-04-22"
[[benchmarks]]
name = "GPQA Diamond"
score = 86.6
metric = "accuracy"
source = "https://mimo.xiaomi.com/mimo-v2-5-pro/"
date = "2026-04-22"
+23
View File
@@ -21,3 +21,26 @@ output = ["text"]
[[weights]]
label = "Hugging Face"
url = "https://huggingface.co/zai-org/GLM-5.2"
[[benchmarks]]
name = "SWE-Bench Pro"
score = 62.1
metric = "resolve rate"
source = "https://z.ai/blog/glm-5.2"
date = "2026-06-16"
[[benchmarks]]
name = "Terminal-Bench"
score = 82.7
metric = "success rate"
harness = "Claude Code"
version = "2.1"
source = "https://z.ai/blog/glm-5.2"
date = "2026-06-16"
[[benchmarks]]
name = "FrontierSWE"
score = 74.4
metric = "dominance"
source = "https://z.ai/blog/glm-5.2"
date = "2026-06-16"
+4 -1
View File
@@ -26,12 +26,15 @@
"databricks:generate": "bun ./packages/core/script/generate-databricks.ts",
"helicone:generate": "bun ./packages/core/script/generate-helicone.ts",
"huggingface:sync": "bun ./packages/core/script/sync-models.ts huggingface",
"kilo:sync": "bun ./packages/core/script/sync-models.ts kilo",
"llmgateway:sync": "bun ./packages/core/script/sync-models.ts llmgateway",
"merge-gateway:sync": "bun ./packages/core/script/sync-models.ts merge-gateway",
"nano-gpt:sync": "bun ./packages/core/script/sync-models.ts nano-gpt",
"venice:sync": "bun ./packages/core/script/sync-models.ts venice",
"vercel:generate": "bun ./packages/core/script/sync-models.ts vercel",
"wandb:generate": "bun ./packages/core/script/sync-models.ts wandb",
"digitalocean:sync": "bun ./packages/core/script/sync-models.ts digitalocean",
"ambient:generate": "bun ./packages/core/script/generate-ambient.ts",
"ambient:sync": "bun ./packages/core/script/sync-models.ts ambient",
"models:sync": "bun ./packages/core/script/sync-models.ts",
"sync:models": "bun ./packages/core/script/sync-models.ts"
},
-169
View File
@@ -1,169 +0,0 @@
#!/usr/bin/env bun
/**
* Generates Ambient model TOML files from https://api.ambient.xyz/v1/models.
*
* Emits `base_model` TOMLs that inherit upstream metadata
* (family, release_date, knowledge, capabilities) from the canonical
* provider model, and override only the fields Ambient's API reports:
* cost, limit, modalities.
*
* Flags:
* --dry-run Preview generated TOMLs without writing files.
*/
import { z } from "zod";
import path from "node:path";
import { mkdir } from "node:fs/promises";
const API_ENDPOINT = "https://api.ambient.xyz/v1/models";
// Allowlist for the initial rollout.
const ALLOWLIST = new Set<string>([
"zai-org/GLM-5.1-FP8",
"moonshotai/kimi-k2.6",
]);
// Maps Ambient model IDs to canonical model metadata IDs in this repo.
const BASE_MODEL_MAP: Record<string, string> = {
"zai-org/GLM-5.1-FP8": "zhipuai/glm-5.1",
"moonshotai/kimi-k2.6": "moonshotai/kimi-k2.6",
};
const Pricing = z
.object({
prompt: z.string(),
completion: z.string(),
input_cache_read: z.string().optional(),
input_cache_write: z.string().optional(),
})
.passthrough();
const AmbientModel = z
.object({
id: z.string(),
name: z.string(),
context_length: z.number(),
max_output_length: z.number(),
input_modalities: z.array(z.string()),
output_modalities: z.array(z.string()),
pricing: Pricing,
})
.passthrough();
const AmbientResponse = z
.object({
object: z.literal("list"),
data: z.array(AmbientModel),
})
.passthrough();
const ALLOWED_MODALITIES = new Set(["text", "audio", "image", "video", "pdf"]);
function modalities(values: string[]): string[] {
return values
.map((v) => v.toLowerCase())
.filter((v) => ALLOWED_MODALITIES.has(v));
}
function perMTok(price: string): number {
const n = parseFloat(price);
if (!Number.isFinite(n)) {
throw new Error(`Invalid price: ${price}`);
}
// Round to 6 decimals to absorb float noise from per-token strings.
return Math.round(n * 1_000_000 * 1_000_000) / 1_000_000;
}
function formatToml(
model: z.infer<typeof AmbientModel>,
baseModel: string,
): string {
const lines: string[] = [];
lines.push(`base_model = "${baseModel}"`);
lines.push("");
lines.push("[cost]");
lines.push(`input = ${perMTok(model.pricing.prompt)}`);
lines.push(`output = ${perMTok(model.pricing.completion)}`);
if (model.pricing.input_cache_read !== undefined) {
lines.push(`cache_read = ${perMTok(model.pricing.input_cache_read)}`);
}
if (model.pricing.input_cache_write !== undefined) {
lines.push(`cache_write = ${perMTok(model.pricing.input_cache_write)}`);
}
lines.push("");
lines.push("[limit]");
lines.push(`context = ${model.context_length}`);
lines.push(`output = ${model.max_output_length}`);
lines.push("");
const input = modalities(model.input_modalities);
const output = modalities(model.output_modalities);
lines.push("[modalities]");
lines.push(`input = [${input.map((m) => `"${m}"`).join(", ")}]`);
lines.push(`output = [${output.map((m) => `"${m}"`).join(", ")}]`);
return lines.join("\n") + "\n";
}
async function main() {
const dryRun = process.argv.includes("--dry-run");
const outDir = path.join(
import.meta.dirname,
"..",
"..",
"..",
"providers",
"ambient",
"models",
);
const res = await fetch(API_ENDPOINT);
if (!res.ok) {
console.error(`Fetch failed: ${res.status} ${res.statusText}`);
process.exit(1);
}
const parsed = AmbientResponse.safeParse(await res.json());
if (!parsed.success) {
console.error("Invalid Ambient response:", parsed.error.issues);
process.exit(1);
}
const selected = parsed.data.data.filter((m) => ALLOWLIST.has(m.id));
const missing = [...ALLOWLIST].filter(
(id) => !selected.some((m) => m.id === id),
);
if (missing.length > 0) {
console.error(`Allowlisted models missing from API: ${missing.join(", ")}`);
process.exit(1);
}
let count = 0;
for (const model of selected) {
const baseModel = BASE_MODEL_MAP[model.id];
if (!baseModel) {
console.error(`No BASE_MODEL_MAP entry for ${model.id}; skipping`);
continue;
}
const filePath = path.join(outDir, `${model.id}.toml`);
const toml = formatToml(model, baseModel);
if (dryRun) {
console.log(`--- ${path.relative(process.cwd(), filePath)} ---`);
console.log(toml);
} else {
await mkdir(path.dirname(filePath), { recursive: true });
await Bun.write(filePath, toml);
}
count++;
}
console.log(
`${dryRun ? "Previewed" : "Wrote"} ${count} model file(s) under providers/ambient/models/`,
);
}
await main();
+6
View File
@@ -13,6 +13,9 @@ export const ModelFamilyValues = [
"gpt-pro",
"gpt-mini",
"gpt-nano",
"gpt-sol",
"gpt-terra",
"gpt-luna",
"gpt-oss",
"gpt-image",
@@ -73,11 +76,13 @@ export const ModelFamilyValues = [
// Moonshot Kimi
"kimi",
"kimi-k2",
"kimi-k3",
"kimi-free",
"kimi-thinking",
// Poolside Laguna
"laguna",
"laguna-s",
// Mistral family
"mistral",
@@ -442,5 +447,6 @@ export function inferKimiFamily(...values: string[]): ModelFamily | undefined {
const target = values.join(" ").toLowerCase();
if (/kimi[^a-z0-9]*k2(?:[^a-z0-9]*\d+)?[^a-z0-9]*thinking/.test(target)) return "kimi-thinking";
if (/kimi[\s_-]*k2/.test(target)) return "kimi-k2";
if (/kimi[\s_-]*k3/.test(target)) return "kimi-k3";
return undefined;
}
+92 -15
View File
@@ -4,6 +4,8 @@ import { mergeDeep } from "remeda";
import { z } from "zod";
import { AuthoredModel, AuthoredModelShape, ModelMetadata } from "../schema.js";
import { openMissingModelIssues } from "./missing-issues.js";
import { ambient } from "./providers/ambient.js";
import { anthropic } from "./providers/anthropic.js";
import { baseten } from "./providers/baseten.js";
import { chutes } from "./providers/chutes.js";
@@ -11,12 +13,18 @@ import { cloudflareWorkersAi } from "./providers/cloudflare-workers-ai.js";
import { crossmodel } from "./providers/crossmodel.js";
import { deepinfra } from "./providers/deepinfra.js";
import { digitalocean } from "./providers/digitalocean.js";
import { empiriolabs } from "./providers/empiriolabs.js";
import { google } from "./providers/google.js";
import { hyper } from "./providers/hyper.js";
import { huggingface } from "./providers/huggingface.js";
import { kilo } from "./providers/kilo.js";
import { llmgateway } from "./providers/llmgateway.js";
import { mergeGateway } from "./providers/merge-gateway.js";
import { nanoGpt } from "./providers/nano-gpt.js";
import { openai } from "./providers/openai.js";
import { openrouter } from "./providers/openrouter.js";
import { ovhcloud } from "./providers/ovhcloud.js";
import { pioneer } from "./providers/pioneer.js";
import { vercel } from "./providers/vercel.js";
import { venice } from "./providers/venice.js";
import { wandb } from "./providers/wandb.js";
@@ -57,13 +65,24 @@ export interface SyncProvider<SourceModel> {
name: string;
modelsDir: string;
metadataNamespace?: string;
/**
* Do not create new local TOMLs for remote-only models. Instead open one
* deduped GitHub issue per missing model ID.
*/
skipCreates?: boolean;
/** Report remote-only models skipped by skipCreates as GitHub issues. */
trackMissingModels?: boolean;
deleteMissing?: boolean;
preserveSymlinks?: boolean;
preserveBaseModels?: boolean;
preserveDescriptions?: boolean;
sameModel?(current: ExistingModel, desired: SyncedModel): boolean;
missingNotice?(paths: string[]): string[];
sourceID?(model: SourceModel): string;
/**
* Remote ID to report when translateModel skips a source model. Return
* undefined to skip silently (no notice, no missing-model issue).
*/
sourceID?(model: SourceModel): string | undefined;
skippedNotice?(ids: string[]): string[];
fetchModels(): Promise<unknown>;
parseModels(raw: unknown): SourceModel[];
@@ -89,6 +108,7 @@ export interface SyncResult {
}
export const providers: {
ambient: SyncProvider<any>;
anthropic: SyncProvider<any>;
baseten: SyncProvider<any>;
chutes: SyncProvider<any>;
@@ -96,17 +116,24 @@ export const providers: {
crossmodel: SyncProvider<any>;
deepinfra: SyncProvider<any>;
digitalocean: SyncProvider<any>;
empiriolabs: SyncProvider<any>;
google: SyncProvider<any>;
hyper: SyncProvider<any>;
huggingface: SyncProvider<any>;
kilo: SyncProvider<any>;
llmgateway: SyncProvider<any>;
"merge-gateway": SyncProvider<any>;
"nano-gpt": SyncProvider<any>;
openai: SyncProvider<any>;
openrouter: SyncProvider<any>;
ovhcloud: SyncProvider<any>;
pioneer: SyncProvider<any>;
vercel: SyncProvider<any>;
venice: SyncProvider<any>;
wandb: SyncProvider<any>;
xai: SyncProvider<any>;
} = {
ambient,
anthropic,
baseten,
chutes,
@@ -114,12 +141,18 @@ export const providers: {
crossmodel,
deepinfra,
digitalocean,
empiriolabs,
google,
hyper,
huggingface,
kilo,
llmgateway,
"merge-gateway": mergeGateway,
"nano-gpt": nanoGpt,
openai,
openrouter,
ovhcloud,
pioneer,
vercel,
venice,
wandb,
@@ -127,15 +160,26 @@ export const providers: {
};
export const groups = {
aggregators: ["crossmodel", "huggingface", "llmgateway", "openrouter", "vercel"],
aggregators: [
"crossmodel",
"empiriolabs",
"huggingface",
"kilo",
"llmgateway",
"merge-gateway",
"nano-gpt",
"openrouter",
"vercel",
],
cloudflare: ["cloudflare-workers-ai"],
direct: ["anthropic", "baseten", "chutes", "deepinfra", "digitalocean", "google", "openai", "ovhcloud", "venice", "wandb", "xai"],
direct: ["ambient", "anthropic", "baseten", "chutes", "deepinfra", "digitalocean", "google", "hyper", "openai", "ovhcloud", "pioneer", "venice", "wandb", "xai"],
} as const;
type ProviderID = keyof typeof providers;
interface SyncOptions {
dryRun?: boolean;
openIssues?: boolean;
newOnly?: boolean;
}
@@ -167,12 +211,13 @@ export async function syncProvider<SourceModel>(
},
});
if (translated === undefined) {
if (provider.sourceID !== undefined) skippedRemote.push(provider.sourceID(sourceModel));
const skippedID = provider.sourceID?.(sourceModel);
if (skippedID !== undefined) skippedRemote.push(skippedID);
continue;
}
const relativePath = `${translated.id}.toml`;
if (provider.skipCreates && !existing.has(relativePath)) {
if (provider.skipCreates === true && !existing.has(relativePath)) {
skippedRemote.push(translated.id);
continue;
}
@@ -214,16 +259,17 @@ export async function syncProvider<SourceModel>(
} else {
resolvedReasoning = existing.get(relativePath)?.toml.reasoning;
}
const withReasoningOptions = preserveReasoningOptions(
translatedModel,
existing.get(relativePath)?.authored,
resolvedReasoning,
);
const withDescription = provider.preserveDescriptions === false
? withReasoningOptions
: preserveDescription(withReasoningOptions, existing.get(relativePath)?.authored);
const parsed = SyncedAuthoredModel.safeParse(stripUndefined({
id: translated.id,
...preserveDescription(
preserveReasoningOptions(
translatedModel,
existing.get(relativePath)?.authored,
resolvedReasoning,
),
existing.get(relativePath)?.authored,
),
...withDescription,
}));
if (!parsed.success) {
parsed.error.cause = { provider: provider.id, path: relativePath };
@@ -345,10 +391,38 @@ export async function syncProvider<SourceModel>(
}
}
const result = summarize(provider, files, unchanged, [
const notices = [
...provider.skippedNotice?.(skippedRemote) ?? [],
...provider.missingNotice?.(missingLocal) ?? [],
]);
];
if (
provider.skipCreates === true
&& provider.trackMissingModels !== false
&& skippedRemote.length > 0
&& options.openIssues === true
) {
try {
notices.push(
...await openMissingModelIssues(
{ id: provider.id, name: provider.name, modelsDir: provider.modelsDir },
skippedRemote,
{ dryRun: options.dryRun },
),
);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
const notice = `Failed to open missing-model GitHub issues: ${message}`;
notices.push(notice);
console.error(notice);
// Surface as a workflow annotation: on no-change hours the notice never
// reaches a PR body, so a broken token or full dedupe window would
// otherwise disable issue opens silently while runs stay green.
if (process.env.GITHUB_ACTIONS === "true") console.log(`::error::${provider.id}: ${notice}`);
}
}
const result = summarize(provider, files, unchanged, notices);
console.log(
`${options.dryRun ? "Dry run: " : ""}${result.created} created, ${result.updated} updated, ${result.deleted} removed, ${result.unchanged} unchanged`,
);
@@ -922,6 +996,9 @@ export async function main(args = process.argv.slice(2)) {
const results = await syncTargets(target, {
dryRun: args.includes("--dry-run"),
newOnly: args.includes("--new-only"),
// Only GitHub Actions opens issues by default; local needs --open-issues.
openIssues: args.includes("--open-issues")
|| (process.env.GITHUB_ACTIONS === "true" && !args.includes("--no-issues")),
});
await writeReport(target, results);
+184
View File
@@ -0,0 +1,184 @@
export interface MissingModelIssueTarget {
id: string;
name: string;
modelsDir: string;
}
export interface OpenMissingModelIssuesOptions {
dryRun?: boolean;
}
function issueTitle(providerId: string, modelId: string) {
return `[missing-model] ${providerId}: ${modelId}`;
}
function issueBody(provider: MissingModelIssueTarget, modelId: string) {
return [
`The **${provider.name}** catalog sync found remote model \`${modelId}\` that is not in the local catalog.`,
"",
`| Field | Value |`,
`| --- | --- |`,
`| Provider | \`${provider.id}\` |`,
`| Model ID | \`${modelId}\` |`,
`| Expected path | \`${provider.modelsDir}/${modelId}.toml\` |`,
"",
"This provider uses `skipCreates` because the remote source is not enough to auto-author a full TOML.",
"Add the model manually (prefer `base_model` when matching `models/` metadata exists).",
"",
].join("\n");
}
/** Open one deduped GitHub issue per missing model ID (title-stable). */
export async function openMissingModelIssues(
provider: MissingModelIssueTarget,
modelIds: string[],
options: OpenMissingModelIssuesOptions = {},
): Promise<string[]> {
const ids = [...new Set(modelIds)].filter((id) => id.length > 0).sort();
if (ids.length === 0) return [];
const notices: string[] = [];
const labels = ["automation", "model-sync", "missing-model", `provider:${provider.id}`];
if (options.dryRun) {
for (const modelId of ids) {
const notice = `Would open GitHub issue for missing model \`${modelId}\` (\`${issueTitle(provider.id, modelId)}\`)`;
notices.push(notice);
console.log(notice);
}
return notices;
}
// Fail closed before listing/creating: a label failure here would otherwise
// surface as one opaque `gh issue create` error per model.
for (const label of labels) {
const result = await runGh([
"label",
"create",
label,
"--color",
"0E8A16",
"--description",
"Automated model catalog sync",
"--force",
]);
if (result.code !== 0) {
throw new Error(`gh label create ${label} failed: ${result.stderr || result.stdout || `exit ${result.code}`}`);
}
}
const existingByTitle = await listTrackedTitles(provider.id);
for (const modelId of ids) {
const title = issueTitle(provider.id, modelId);
const existing = existingByTitle.get(title);
if (existing !== undefined) {
const notice = `Missing model \`${modelId}\` already tracked by #${existing}`;
notices.push(notice);
console.log(notice);
continue;
}
try {
const number = await createIssue(title, issueBody(provider, modelId), labels);
existingByTitle.set(title, number);
await dispatchIssueFixer(provider.id, number);
const notice = `Opened GitHub issue #${number} and dispatched the issue fixer for missing model \`${modelId}\``;
notices.push(notice);
console.log(notice);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
const notice = `Failed to open GitHub issue for missing model \`${modelId}\`: ${message}`;
notices.push(notice);
console.error(notice);
}
}
return notices;
}
const LIST_LIMIT = 1000;
async function listTrackedTitles(providerId: string) {
// Include closed so a wontfix/closed issue does not reopen hourly.
const result = await runGh([
"issue",
"list",
"--state",
"all",
"--label",
"missing-model",
"--label",
`provider:${providerId}`,
"--limit",
String(LIST_LIMIT),
"--json",
"number,title",
]);
if (result.code !== 0) {
throw new Error(`gh issue list failed: ${result.stderr || result.stdout || `exit ${result.code}`}`);
}
const issues = JSON.parse(result.stdout || "[]") as Array<{ number: number; title: string }>;
// Fail closed when the window is full: older titles may have been truncated,
// and creating against an incomplete list could reopen duplicates.
if (issues.length >= LIST_LIMIT) {
throw new Error(
`gh issue list returned ${issues.length} issues (window limit ${LIST_LIMIT}); refusing to create against a possibly truncated dedupe list`,
);
}
return new Map(issues.map((issue) => [issue.title, issue.number]));
}
async function createIssue(title: string, body: string, labels: string[]) {
const args = ["issue", "create", "--title", title, "--body", body];
for (const label of labels) args.push("--label", label);
const result = await runGh(args);
if (result.code !== 0) {
throw new Error(`gh issue create failed: ${result.stderr || result.stdout || `exit ${result.code}`}`);
}
const url = result.stdout.trim();
const number = url.match(/\/issues\/(\d+)\s*$/)?.[1] ?? url.match(/#(\d+)\s*$/)?.[1];
if (number === undefined) {
throw new Error(`gh issue create returned no issue number: ${url}`);
}
return Number(number);
}
async function dispatchIssueFixer(providerId: string, issueNumber: number) {
const repository = process.env.GITHUB_REPOSITORY;
if (repository === undefined) {
throw new Error("GITHUB_REPOSITORY is required to dispatch the issue fixer");
}
const result = await runGh([
"api",
`repos/${repository}/dispatches`,
"--method",
"POST",
"--field",
"event_type=missing-model",
"--field",
`client_payload[provider]=${providerId}`,
"--field",
`client_payload[issue_number]=${issueNumber}`,
]);
if (result.code !== 0) {
throw new Error(`issue fixer dispatch failed: ${result.stderr || result.stdout || `exit ${result.code}`}`);
}
}
async function runGh(args: string[]) {
const proc = Bun.spawn(["gh", ...args], {
stdout: "pipe",
stderr: "pipe",
env: process.env,
});
const [stdout, stderr, code] = await Promise.all([
new Response(proc.stdout).text(),
new Response(proc.stderr).text(),
proc.exited,
]);
return { code, stdout, stderr };
}
+117
View File
@@ -0,0 +1,117 @@
import { z } from "zod";
import type { SyncProvider } from "../index.js";
import { buildOpenRouterModel, type OpenRouterModel } from "./openrouter.js";
const API_ENDPOINT = "https://api.ambient.xyz/v1/models";
export const AmbientModel = z.object({
id: z.string().min(1),
name: z.string().min(1),
created: z.number(),
hugging_face_id: z.string().nullable().optional(),
context_length: z.number(),
max_output_length: z.number(),
input_modalities: z.array(z.string()),
output_modalities: z.array(z.string()),
pricing: z.object({
prompt: z.string(),
completion: z.string(),
input_cache_read: z.string().optional(),
input_cache_write: z.string().optional(),
}).passthrough(),
supported_features: z.array(z.string()).default([]),
supported_sampling_parameters: z.array(z.string()).default([]),
openrouter: z.object({ slug: z.string() }).nullable().optional(),
is_ready: z.boolean().default(false),
}).passthrough();
export const AmbientResponse = z.object({
object: z.literal("list"),
data: z.array(AmbientModel),
}).passthrough();
export type AmbientModel = z.infer<typeof AmbientModel>;
function toOpenRouterShape(model: AmbientModel): OpenRouterModel {
return {
id: model.openrouter?.slug ?? model.id,
name: model.name,
created: model.created,
hugging_face_id: model.hugging_face_id ?? null,
knowledge_cutoff: null,
context_length: model.context_length,
architecture: {
input_modalities: model.input_modalities,
output_modalities: model.output_modalities,
},
pricing: {
prompt: model.pricing.prompt,
completion: model.pricing.completion,
input_cache_read: model.pricing.input_cache_read,
input_cache_write: model.pricing.input_cache_write,
},
top_provider: {
context_length: model.context_length,
max_completion_tokens: model.max_output_length,
},
supported_parameters: [...model.supported_features, ...model.supported_sampling_parameters],
};
}
export const ambient = {
id: "ambient",
name: "Ambient",
modelsDir: "providers/ambient/models",
deleteMissing: false,
sourceID(model) {
return model.id;
},
skippedNotice(ids) {
if (ids.length === 0) return [];
return [
`${ids.length} Ambient models were skipped because the catalog reports them as not ready (is_ready=false).`,
`Skipped remote IDs: ${ids.map((id) => `\`${id}\``).join(", ")}`,
];
},
missingNotice(paths) {
if (paths.length === 0) return [];
return [
`${paths.length} local Ambient models were absent from the catalog and were retained for manual lifecycle review.`,
`Retained local paths: ${paths.map((item) => `\`${item}\``).join(", ")}`,
];
},
async fetchModels() {
const response = await fetch(API_ENDPOINT);
if (!response.ok) {
throw new Error(`Ambient request failed: ${response.status} ${response.statusText}`);
}
return response.json();
},
parseModels(raw) {
return AmbientResponse.parse(raw).data;
},
translateModel(model, context) {
if (!model.is_ready) return undefined;
const existing = context.existing(model.id);
const built = buildOpenRouterModel(toOpenRouterShape(model), existing);
const reasoning = model.supported_features.includes("reasoning");
const withOptions = reasoning
? { ...built, reasoning_options: existing?.reasoning_options ?? [] }
: built;
const aliasName = ambientAliasName(model.id);
return {
id: model.id,
model: aliasName === undefined ? withOptions : { ...withOptions, name: aliasName },
};
},
} satisfies SyncProvider<AmbientModel>;
function ambientAliasName(id: string): string | undefined {
if (!id.startsWith("ambient/")) return undefined;
const label = id.slice("ambient/".length)
.split(/[/-]/)
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
return `Ambient ${label}`;
}
+35 -12
View File
@@ -2,7 +2,8 @@ import path from "node:path";
import { existsSync } from "node:fs";
import { z } from "zod";
import type { ExistingModel, SyncProvider, SyncedModel } from "../index.js";
import type { ExistingModel, SyncProvider, SyncedFullModel, SyncedModel } from "../index.js";
import { factorBaseModel } from "./openrouter.js";
const API_ENDPOINT = "https://api.anthropic.com/v1/models";
const PRICING_ENDPOINT = "https://platform.claude.com/docs/en/about-claude/pricing";
@@ -310,20 +311,42 @@ export function buildAnthropicModel(
const output = model.max_tokens > 0 ? model.max_tokens : existing?.limit?.output;
const cost = syncedCost(model, existing);
const options = reasoningOptions(model, existing);
// Models API has no fast-mode surface; preserve authored experimental/provider config.
const experimental = existing?.experimental;
const provider = existing?.provider;
const status = model.pricing?.deprecated ? "deprecated" as const : existing?.status;
const structured_output = model.capabilities.structured_outputs?.supported
?? existing?.structured_output;
const limit = context !== undefined || output !== undefined || existing?.limit !== undefined
? {
context: context ?? existing?.limit?.context ?? 0,
input: existing?.limit?.input,
output: output ?? existing?.limit?.output ?? 0,
}
: undefined;
const modalities = { input, output: ["text" as const] };
if (baseModel !== undefined) {
return {
base_model: baseModel,
const overrides: Partial<SyncedFullModel> = {
name: model.canonical_id === undefined ? undefined : name,
attachment: input.length > 1,
reasoning,
reasoning_options: options,
structured_output: model.capabilities.structured_outputs?.supported,
status: model.pricing?.deprecated ? "deprecated" : undefined,
structured_output,
status,
interleaved: existing?.interleaved,
experimental,
provider,
cost,
limit: context !== undefined && output !== undefined ? { context, output } : undefined,
modalities: { input, output: ["text"] },
limit,
modalities,
};
return factorBaseModel(
baseModel,
overrides,
limit ?? { context: 0, output: 0 },
existing?.base_model_omit,
);
}
if (
@@ -349,15 +372,15 @@ export function buildAnthropicModel(
reasoning_options: options,
temperature: existing.temperature,
tool_call: existing.tool_call,
structured_output: model.capabilities.structured_outputs?.supported ?? existing.structured_output,
structured_output,
knowledge: existing.knowledge,
open_weights: existing.open_weights,
status: model.pricing?.deprecated ? "deprecated" : existing.status,
status,
interleaved: existing.interleaved,
experimental: existing.experimental,
provider: existing.provider,
experimental,
provider,
cost,
limit: { context, input: existing.limit?.input, output },
modalities: { input, output: ["text"] },
modalities,
};
}
@@ -81,6 +81,7 @@ const AUTHOR_BY_VENDOR: Record<string, string> = {
xiaomi: "xiaomi",
minimax: "minimax",
"z-ai": "zhipuai",
"x-ai": "xai",
tencent: "tencent",
};
+233 -121
View File
@@ -6,7 +6,7 @@ import type { ExistingModel, SyncProvider, SyncedFullModel, SyncedModel } from "
import { factorBaseModel, resolveCanonicalBaseModel } from "./openrouter.js";
const MODELS_API = "https://api.digitalocean.com/v2/gen-ai/models?per_page=200";
const PRICING_API = "https://www.digitalocean.com/api/static-content/v1/products";
const CATALOG_API = "https://api.digitalocean.com/v2/gen-ai/models/catalog?limit=200";
export const DigitalOceanModel = z.object({
id: z.string().min(1),
@@ -14,6 +14,7 @@ export const DigitalOceanModel = z.object({
lifecycle_status: z.string(),
type: z.string().optional(),
thinking: z.boolean().optional(),
reasoning_efforts: z.array(z.string()).optional(),
context_window: z.union([z.number(), z.string()]).optional(),
modalities: z.object({
input: z.array(z.string()).optional(),
@@ -36,75 +37,91 @@ const DigitalOceanModelsResponse = z.object({
}).passthrough().optional(),
}).passthrough();
const PricingEntry = z.object({
name: z.string(),
slug: z.string(),
model: z.string(),
prompt_tokens: z.string().optional(),
price: z.object({ rate: z.number() }),
const DigitalOceanCatalogPricing = z.object({
input_price_per_million: z.number().optional(),
output_price_per_million: z.number().optional(),
cache_read_input_price_per_million: z.number().optional(),
cache_write_5m_input_price_per_million: z.number().optional(),
}).passthrough();
const DigitalOceanPricingResponse = z.object({
gradient: z.object({ models: z.array(PricingEntry) }),
const DigitalOceanCatalogModel = z.object({
id: z.string().min(1).optional(),
model_id: z.string().min(1),
name: z.string().min(1),
context_window: z.union([z.number(), z.string()]).nullish(),
max_output_tokens: z.union([z.number(), z.string()]).nullish(),
availability: z.array(z.string()).optional(),
modalities: z.object({
input: z.array(z.string()).optional(),
output: z.array(z.string()).optional(),
}).nullish(),
pricing: DigitalOceanCatalogPricing.nullish(),
pricing_detail: z.object({
variants: z.array(z.object({
tier: z.string().optional(),
mode: z.string().optional(),
prices: DigitalOceanCatalogPricing.nullish(),
}).passthrough()),
}).nullish(),
}).passthrough();
const DigitalOceanCatalogResponse = z.object({
data: z.array(DigitalOceanCatalogModel),
links: z.object({
pages: z.object({
next: z.string().nullable().optional(),
}).passthrough().optional(),
}).passthrough().optional(),
meta: z.object({
page: z.number().int().positive(),
pages: z.number().int().nonnegative(),
total: z.number().int().nonnegative(),
}).passthrough().optional(),
}).passthrough();
const DigitalOceanCatalogDetailResponse = z.object({
data: DigitalOceanCatalogModel,
}).passthrough();
const DigitalOceanResponse = z.object({
models: z.array(DigitalOceanModel),
pricing: z.array(PricingEntry),
catalog: z.array(DigitalOceanCatalogModel),
});
export type DigitalOceanModel = z.infer<typeof DigitalOceanModel>;
type PricingEntry = z.infer<typeof PricingEntry>;
type DigitalOceanCatalogModel = z.infer<typeof DigitalOceanCatalogModel>;
interface ModelPricing {
input?: number;
output?: number;
inputOver200k?: number;
outputOver200k?: number;
cacheRead?: number;
cacheWrite?: number;
extended?: {
context: number;
input?: number;
output?: number;
cacheRead?: number;
cacheWrite?: number;
};
}
type ReasoningEffort =
| null
| "none"
| "minimal"
| "low"
| "medium"
| "high"
| "xhigh"
| "max"
| "default";
export interface DigitalOceanSourceModel extends DigitalOceanModel {
max_output_tokens?: string | number | null;
availability?: string[];
pricing?: ModelPricing;
}
const PRICING_NAME_OVERRIDES: Record<string, string> = {
"claude sonnet 4.6": "anthropic-claude-4.6-sonnet",
"claude sonnet 4.5": "anthropic-claude-4.5-sonnet",
"claude sonnet 4": "anthropic-claude-sonnet-4",
"claude haiku 4.5": "anthropic-claude-haiku-4.5",
"claude opus 4.6": "anthropic-claude-opus-4.6",
"claude opus 4.5": "anthropic-claude-opus-4.5",
"claude opus 4.1": "anthropic-claude-4.1-opus",
"claude opus 4": "anthropic-claude-opus-4",
"gpt-5.4": "openai-gpt-5.4",
"gpt-5.4 mini": "openai-gpt-5.4-mini",
"gpt-5.4 nano": "openai-gpt-5.4-nano",
"gpt-5.4 pro": "openai-gpt-5.4-pro",
"gpt-5.3-codex": "openai-gpt-5.3-codex",
"gpt-5.2": "openai-gpt-5.2",
"gpt-5.2 pro": "openai-gpt-5.2-pro",
"gpt-5.1-codex-max": "openai-gpt-5.1-codex-max",
"gpt-5": "openai-gpt-5",
"gpt-5 mini": "openai-gpt-5-mini",
"gpt-5 nano": "openai-gpt-5-nano",
"gpt-4.1": "openai-gpt-4.1",
"gpt image 1": "openai-gpt-image-1",
"gpt image 1.5": "openai-gpt-image-1.5",
"gpt-oss-120b": "openai-gpt-oss-120b",
"gpt-oss-20b": "openai-gpt-oss-20b",
"gpt-4o": "openai-gpt-4o",
"gpt-4o mini": "openai-gpt-4o-mini",
o1: "openai-o1",
"o3-mini": "openai-o3-mini",
"deepseek r1 distill llama 70b": "deepseek-r1-distill-llama-70b",
"llama 3.3 70b": "llama3.3-70b-instruct",
"qwen3-32b": "alibaba-qwen3-32b",
"minimax m2.5": "minimax-m2.5",
"kimi k2.5": "kimi-k2.5",
"nvidia nemotron 3 super 120b": "nvidia-nemotron-3-super-120b",
"glm 5": "glm-5",
};
export const digitalocean = {
id: "digitalocean",
name: "DigitalOcean",
@@ -140,7 +157,7 @@ export const digitalocean = {
translateModel(model, context) {
const existing = context.existing(model.id);
const contextWindow = number(model.context_window);
const outputLimit = model.settings?.find((setting) => setting.name === "max_tokens")?.max;
const outputLimit = number(model.max_output_tokens ?? undefined);
if (model.pricing?.input === undefined || model.pricing.output === undefined) return undefined;
if (
existing === undefined
@@ -162,19 +179,11 @@ export const digitalocean = {
} satisfies SyncProvider<DigitalOceanSourceModel>;
export async function fetchDigitalOceanModels(key: string, fetcher: typeof fetch = fetch) {
const [models, pricingResponse] = await Promise.all([
const [models, catalog] = await Promise.all([
fetchAllDigitalOceanModels(key, fetcher),
fetcher(PRICING_API, {
headers: { "User-Agent": "models.dev/digitalocean-sync" },
}),
fetchAllDigitalOceanCatalog(fetcher),
]);
if (!pricingResponse.ok) {
throw new Error(`DigitalOcean pricing request failed: ${pricingResponse.status} ${pricingResponse.statusText}`);
}
const pricing = DigitalOceanPricingResponse.parse(await pricingResponse.json()).gradient.models;
return { models, pricing };
return { models, catalog };
}
async function fetchAllDigitalOceanModels(key: string, fetcher: typeof fetch) {
@@ -201,56 +210,124 @@ async function fetchAllDigitalOceanModels(key: string, fetcher: typeof fetch) {
return models;
}
async function fetchAllDigitalOceanCatalog(fetcher: typeof fetch) {
const catalog: DigitalOceanCatalogModel[] = [];
const visited = new Set<string>();
let url: string | undefined = CATALOG_API;
while (url !== undefined) {
if (visited.has(url)) throw new Error(`DigitalOcean catalog pagination repeated URL: ${url}`);
visited.add(url);
const response = await fetcher(url, {
headers: { "Content-Type": "application/json", "User-Agent": "models.dev/digitalocean-sync" },
});
if (!response.ok) {
throw new Error(`DigitalOcean catalog request failed: ${response.status} ${response.statusText}`);
}
const page = DigitalOceanCatalogResponse.parse(await response.json());
catalog.push(...page.data);
const next = page.links?.pages?.next;
if (next) {
url = new URL(next, url).toString();
} else if (page.meta !== undefined && page.meta.page < page.meta.pages) {
const nextPage = new URL(url);
nextPage.searchParams.set("page", String(page.meta.page + 1));
url = nextPage.toString();
} else {
url = undefined;
}
}
return Promise.all(catalog.map(async (model) => {
if (model.id === undefined || model.availability?.includes("serverless") !== true) return model;
const response = await fetcher(`https://api.digitalocean.com/v2/gen-ai/models/catalog/${model.id}`, {
headers: { "Content-Type": "application/json", "User-Agent": "models.dev/digitalocean-sync" },
});
if (!response.ok) {
throw new Error(`DigitalOcean catalog detail request failed: ${response.status} ${response.statusText}`);
}
const detail = DigitalOceanCatalogDetailResponse.parse(await response.json()).data;
return {
...model,
modalities: detail.modalities ?? model.modalities,
pricing_detail: detail.pricing_detail ?? model.pricing_detail,
};
}));
}
export function parseDigitalOceanModels(raw: unknown): DigitalOceanSourceModel[] {
const response = DigitalOceanResponse.parse(raw);
const pricing = buildPricingMap(response.pricing, response.models);
const catalog = new Map(response.catalog.map((model) => [model.model_id, model]));
return response.models
.filter(isManagedTextModel)
.map((model) => ({ ...model, pricing: pricing.get(model.id) }));
.map((model) => mergeCatalogModel(model, catalog.get(model.id)))
.filter(isManagedTextModel);
}
function isManagedTextModel(model: DigitalOceanModel) {
function mergeCatalogModel(
model: DigitalOceanModel,
catalog: DigitalOceanCatalogModel | undefined,
): DigitalOceanSourceModel {
return {
...model,
name: catalog?.name ?? model.name,
context_window: catalog?.context_window ?? model.context_window,
max_output_tokens: catalog?.max_output_tokens,
modalities: catalog?.modalities ?? model.modalities,
availability: catalog?.availability,
pricing: catalogPricing(catalog),
};
}
function isManagedTextModel(model: DigitalOceanSourceModel) {
const output = normalizeModalities(model.modalities?.output ?? [], []);
return output.includes("text") && model.type !== "embedding" && model.type !== "reranking";
return model.availability?.includes("serverless") === true
&& output.includes("text")
&& model.type !== "embedding"
&& model.type !== "reranking";
}
function pricingName(value: string) {
return value
.replace(/\s+(input|output)\s+tokens$/i, "")
.replace(/\s*\(public preview\)\s*/i, " ")
.trim()
.toLowerCase();
function catalogPricing(model: DigitalOceanCatalogModel | undefined): ModelPricing | undefined {
if (model?.pricing == null) return undefined;
const standard = model.pricing_detail?.variants.find((variant) =>
variant.mode === "MODEL_BILLING_MODE_INTERACTIVE"
&& variant.tier === "MODEL_PRICING_TIER_STANDARD"
)?.prices;
const extended = model.pricing_detail?.variants.find((variant) =>
variant.mode === "MODEL_BILLING_MODE_INTERACTIVE"
&& variant.tier?.startsWith("MODEL_PRICING_TIER_EXTENDED_") === true
);
const extendedContext = pricingTierContext(extended?.tier);
return {
input: perMillion(model.pricing.input_price_per_million),
output: perMillion(model.pricing.output_price_per_million),
cacheRead: perMillion(model.pricing.cache_read_input_price_per_million),
cacheWrite: perMillion(standard?.cache_write_5m_input_price_per_million),
extended: extendedContext === undefined || extended?.prices == null
? undefined
: {
context: extendedContext,
input: perMillion(extended.prices.input_price_per_million),
output: perMillion(extended.prices.output_price_per_million),
cacheRead: perMillion(extended.prices.cache_read_input_price_per_million),
cacheWrite: perMillion(extended.prices.cache_write_5m_input_price_per_million),
},
};
}
function normalizedName(value: string) {
return value.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
function pricingTierContext(tier: string | undefined) {
// Tier names describe capacity; Anthropic's 1M surcharge starts above 200K.
if (tier === "MODEL_PRICING_TIER_EXTENDED_1M") return 200_000;
if (tier === "MODEL_PRICING_TIER_EXTENDED_272K") return 272_000;
return undefined;
}
export function buildPricingMap(entries: PricingEntry[], models: DigitalOceanModel[]) {
const names = new Map<string, string[]>();
for (const model of models) {
const key = normalizedName(model.name);
names.set(key, [...names.get(key) ?? [], model.id]);
}
const result = new Map<string, ModelPricing>();
for (const entry of entries) {
const name = pricingName(entry.name);
const matches = names.get(normalizedName(name)) ?? [];
const id = PRICING_NAME_OVERRIDES[name] ?? (matches.length === 1 ? matches[0] : undefined);
if (id === undefined) continue;
const price = Math.round(entry.price.rate * 10_000) / 10_000;
const current = result.get(id) ?? {};
const input = /\sinput\s+tokens$/i.test(entry.name);
const over200k = entry.prompt_tokens === ">200k";
if (input && over200k) current.inputOver200k = price;
else if (!input && over200k) current.outputOver200k = price;
else if (input) current.input = price;
else current.output = price;
result.set(id, current);
}
return result;
function perMillion(value: number | undefined) {
if (value === undefined) return undefined;
// The live catalog currently returns per-token rates despite the field names.
const normalized = value < 0.001 ? value * 1_000_000 : value;
return Math.round(normalized * 10_000) / 10_000;
}
type Modality = "text" | "audio" | "image" | "video" | "pdf";
@@ -279,6 +356,40 @@ function inferFamily(id: string, name: string) {
.find((family) => target.includes(family.toLowerCase()));
}
function reasoningOptionsFor(
model: DigitalOceanSourceModel,
existing: ExistingModel | undefined,
): ExistingModel["reasoning_options"] {
if (model.reasoning_efforts === undefined) return existing?.reasoning_options;
const values = model.reasoning_efforts
.map((value) => value === "null" ? null : value)
.filter(isReasoningEffort);
const preserved = existing?.reasoning_options?.filter((option) => option.type !== "effort") ?? [];
return values.length > 0 ? [...preserved, { type: "effort", values }] : preserved;
}
function isReasoningEffort(value: string | null): value is ReasoningEffort {
return value === null
|| value === "none"
|| value === "minimal"
|| value === "low"
|| value === "medium"
|| value === "high"
|| value === "xhigh"
|| value === "max"
|| value === "default";
}
function status(
lifecycleStatus: string,
existing: ExistingModel["status"],
): ExistingModel["status"] {
const lifecycle = lifecycleStatus.toLowerCase().replaceAll("_", "-");
if (lifecycle === "deprecated" || lifecycle === "end-of-life") return "deprecated";
if (lifecycle === "public-preview") return "beta";
return existing === "deprecated" || existing === "beta" ? undefined : existing;
}
function cost(model: DigitalOceanSourceModel, existing: ExistingModel | undefined) {
const input = model.pricing?.input ?? existing?.cost?.input;
const output = model.pricing?.output ?? existing?.cost?.output;
@@ -288,18 +399,18 @@ function cost(model: DigitalOceanSourceModel, existing: ExistingModel | undefine
const longContext = existingTiers.find((tier) =>
(tier.tier.type === undefined || tier.tier.type === "context") && tier.tier.size >= 200_000
);
const hasLongContextPricing = model.pricing?.inputOver200k !== undefined
&& model.pricing.outputOver200k !== undefined;
const extended = model.pricing?.extended;
const hasLongContextPricing = extended?.input !== undefined && extended.output !== undefined;
const tiers = hasLongContextPricing
? [
...existingTiers.filter((tier) => tier !== longContext),
{
tier: { type: "context" as const, size: longContext?.tier.size ?? 200_000 },
input: model.pricing!.inputOver200k!,
output: model.pricing!.outputOver200k!,
tier: { type: "context" as const, size: extended.context },
input: extended.input!,
output: extended.output!,
reasoning: longContext?.reasoning,
cache_read: longContext?.cache_read,
cache_write: longContext?.cache_write,
cache_read: extended.cacheRead ?? longContext?.cache_read,
cache_write: extended.cacheWrite ?? longContext?.cache_write,
},
]
: existingTiers;
@@ -308,8 +419,8 @@ function cost(model: DigitalOceanSourceModel, existing: ExistingModel | undefine
input,
output,
reasoning: existing?.cost?.reasoning,
cache_read: existing?.cost?.cache_read,
cache_write: existing?.cost?.cache_write,
cache_read: model.pricing?.cacheRead ?? existing?.cost?.cache_read,
cache_write: model.pricing?.cacheWrite ?? existing?.cost?.cache_write,
input_audio: existing?.cost?.input_audio,
output_audio: existing?.cost?.output_audio,
tiers: tiers.length > 0 ? tiers : undefined,
@@ -330,14 +441,19 @@ export function buildDigitalOceanModel(
existing?.modalities?.output ?? ["text"],
);
const context = number(model.context_window) ?? existing?.limit?.context ?? 0;
const maxTokens = model.settings?.find((setting) => setting.name === "max_tokens")?.max;
const maxTokens = number(model.max_output_tokens ?? undefined);
const limit = {
context,
input: existing?.limit?.input,
output: maxTokens ?? existing?.limit?.output ?? 0,
};
const textOutput = output.includes("text") && !output.includes("image") && !output.includes("video");
const reasoning = existing?.reasoning ?? (textOutput && (model.thinking ?? false));
const remoteReasoning = textOutput
&& ((model.thinking ?? false) || (model.reasoning_efforts?.length ?? 0) > 0);
const providerReasoning = remoteReasoning ? true : existing?.reasoning;
const reasoning = providerReasoning ?? false;
const reasoningOptions = reasoning ? reasoningOptionsFor(model, existing) : undefined;
const modelStatus = status(model.lifecycle_status, existing?.status);
const releaseDate = existing?.release_date ?? model.created_at?.slice(0, 10) ?? new Date().toISOString().slice(0, 10);
const values: Partial<SyncedFullModel> = {
name: model.name,
@@ -357,15 +473,13 @@ export function buildDigitalOceanModel(
last_updated: existing?.last_updated ?? releaseDate,
attachment: existing?.attachment ?? input.some((value) => value !== "text"),
reasoning,
reasoning_options: existing?.reasoning_options,
reasoning_options: reasoningOptions,
temperature: existing?.temperature ?? true,
tool_call: existing?.tool_call ?? textOutput,
structured_output: existing?.structured_output,
knowledge: existing?.knowledge,
open_weights: existing?.open_weights ?? false,
status: model.lifecycle_status === "end_of_life"
? "deprecated"
: existing?.status === "deprecated" ? undefined : existing?.status,
status: modelStatus,
interleaved: existing?.interleaved,
cost: cost(model, existing),
limit,
@@ -379,14 +493,12 @@ export function buildDigitalOceanModel(
name: model.name,
description: existing?.description,
attachment: input.some((value) => value !== "text"),
reasoning: model.thinking ?? existing?.reasoning,
reasoning_options: existing?.reasoning_options,
reasoning: providerReasoning,
reasoning_options: reasoningOptions,
temperature: existing?.temperature,
tool_call: existing?.tool_call,
structured_output: existing?.structured_output,
status: model.lifecycle_status === "end_of_life"
? "deprecated"
: existing?.status === "deprecated" ? undefined : existing?.status,
status: modelStatus,
interleaved: existing?.interleaved,
cost: cost(model, existing),
limit,
@@ -0,0 +1,367 @@
import { z } from "zod";
import type { ExistingModel, SyncProvider, SyncedFullModel, SyncedModel } from "../index.js";
import { factorBaseModel, resolveCanonicalBaseModel } from "./openrouter.js";
// EmpirioLabs exposes a public, unauthenticated OpenAI-compatible model
// catalog, so no API key is needed or used for this sync.
const API_ENDPOINT = "https://api.empiriolabs.ai/v1/models";
const CANONICAL_BASE_MODELS: Record<string, string> = {
"fugu-ultra": "sakana/fugu-ultra",
"gemma-4-26b-a4b": "google/gemma-4-26b-a4b-it",
"gemma-4-e4b": "google/gemma-4-E4B-it",
"mistral-medium-3": "mistral/mistral-medium-2505",
"mistral-small-4": "mistral/mistral-small-2603",
"muse-spark-1-1": "meta/muse-spark-1.1",
"qwen3-5-9b": "alibaba/qwen3.5-9b",
"qwen3-7-max": "alibaba/qwen3.7-max",
"qwen3-7-plus": "alibaba/qwen3.7-plus",
"step-3-5-flash": "stepfun/step-3.5-flash",
"step-3-5-flash-2603": "stepfun/step-3.5-flash-2603",
"step-3-7-flash": "stepfun/step-3.7-flash",
};
const EmpiriolabsParameter = z
.object({
name: z.string(),
type: z.string().optional(),
options: z.array(z.string()).optional(),
min: z.number().optional(),
max: z.number().optional(),
})
.passthrough();
const EmpiriolabsPricingTier = z
.object({
prompt: z.string().optional(),
completion: z.string().optional(),
input_cache_read: z.string().optional(),
min_context: z.number().nullable().optional(),
})
.passthrough();
// Pricing is returned either as a single tier object or as an array of tier
// objects (tiered/context-priced models). Accept both shapes.
const EmpiriolabsPricing = z.union([
z.array(EmpiriolabsPricingTier),
EmpiriolabsPricingTier,
]);
const EmpiriolabsModel = z
.object({
id: z.string(),
display_name: z.string().optional(),
name: z.string().optional(),
description: z.string().optional(),
category: z.string().optional(),
context_length: z.number().nullable().optional(),
context_window: z.number().nullable().optional(),
max_output_tokens: z.number().nullable().optional(),
model_released_at: z.string().nullable().optional(),
pricing: EmpiriolabsPricing.optional(),
capabilities: z.record(z.unknown()).optional(),
features: z.array(z.string()).optional(),
structured_output: z.string().nullable().optional(),
input_modalities: z.array(z.string()).optional(),
output_modalities: z.array(z.string()).optional(),
supported_parameters: z.array(EmpiriolabsParameter).optional(),
})
.passthrough();
const EmpiriolabsResponse = z
.object({
data: z.array(EmpiriolabsModel),
})
.passthrough();
export type EmpiriolabsModel = z.infer<typeof EmpiriolabsModel>;
export const empiriolabs = {
id: "empiriolabs",
name: "EmpirioLabs AI",
modelsDir: "providers/empiriolabs/models",
sourceID(model) {
return model.id;
},
skippedNotice(ids) {
if (ids.length === 0) return [];
return [
`${ids.length} EmpirioLabs AI models returned by the API were not created because they could not be mapped exactly to models.dev canonical metadata. `
+ "Existing models and canonical matches are still updated from API-authoritative fields.",
`Skipped remote IDs: ${ids.map((id) => `\`${id}\``).join(", ")}`,
];
},
async fetchModels() {
const response = await fetch(API_ENDPOINT);
if (!response.ok) {
throw new Error(`EmpirioLabs request failed: ${response.status} ${response.statusText}`);
}
return response.json();
},
parseModels(raw) {
// Text chat models only. Skip non-text categories (image, video, audio,
// 3D, research, tools) and regional/capability variant lanes (id has ":").
return EmpiriolabsResponse.parse(raw).data.filter(
(model) => (model.category ?? "").toLowerCase() === "text" && !model.id.includes(":"),
);
},
translateModel(model, context) {
const existing = context.existing(model.id);
const baseModel = existing?.base_model ?? resolveEmpiriolabsBaseModel(model.id);
if (existing === undefined && baseModel === undefined) return undefined;
const built = buildEmpiriolabsModel(model, existing, baseModel);
// A model with no resolvable context window cannot produce a valid TOML
// (limit.context is required), so skip it rather than fail the whole sync.
if (built === undefined) return undefined;
return {
id: model.id,
model: built,
};
},
} satisfies SyncProvider<EmpiriolabsModel>;
type Modality = "text" | "audio" | "image" | "video" | "pdf";
type EffortValue =
| "none"
| "minimal"
| "low"
| "medium"
| "high"
| "xhigh"
| "max"
| "default";
const EFFORT_VALUES: EffortValue[] = [
"none",
"minimal",
"low",
"medium",
"high",
"xhigh",
"max",
"default",
];
function price(value: string | undefined) {
if (value === undefined) return undefined;
const number = Number(value);
// Per-token string converted to a per-1M-token number.
return Number.isFinite(number) && number >= 0
? Math.round(number * 1_000_000_000_000) / 1_000_000
: undefined;
}
function nonZeroPrice(value: string | undefined) {
const result = price(value);
return result !== undefined && result > 0 ? result : undefined;
}
type TierCost = { input: number; output: number; cache_read?: number };
function tierCost(tier: z.infer<typeof EmpiriolabsPricingTier> | undefined): TierCost | undefined {
const input = price(tier?.prompt);
const output = price(tier?.completion);
if (input === undefined || output === undefined) return undefined;
const cacheRead = nonZeroPrice(tier?.input_cache_read);
return { input, output, cache_read: cacheRead };
}
function modalities(values: string[] | undefined, fallback: Modality[]): Modality[] {
const allowed = new Set<Modality>(["text", "audio", "image", "video", "pdf"]);
const result = (values ?? [])
.map((value) => value.toLowerCase())
.map((value) => (value === "file" ? "pdf" : value))
.filter((value): value is Modality => allowed.has(value as Modality));
return [...new Set(result.length > 0 ? result : fallback)];
}
function reasoningOptions(model: EmpiriolabsModel): SyncedModel["reasoning_options"] {
const params = model.supported_parameters ?? [];
const options: NonNullable<SyncedModel["reasoning_options"]> = [];
if (params.some((parameter) => parameter.name === "enable_thinking")) {
options.push({ type: "toggle" });
}
const effort = params.find((parameter) => parameter.name === "reasoning_effort");
if (effort?.options?.length) {
const values = effort.options.filter((value): value is EffortValue =>
(EFFORT_VALUES as string[]).includes(value),
);
if (values.length > 0) options.push({ type: "effort", values });
}
const budget = params.find((parameter) => parameter.name === "thinking_budget");
if (budget !== undefined) {
const option: { type: "budget_tokens"; min?: number; max?: number } = { type: "budget_tokens" };
if (budget.min !== undefined) option.min = budget.min;
if (budget.max !== undefined) option.max = budget.max;
options.push(option);
}
return options;
}
function parameterOutputLimit(model: EmpiriolabsModel) {
const parameter = (model.supported_parameters ?? []).find(
(item) => item.name === "max_tokens" || item.name === "max_completion_tokens",
);
return parameter?.max !== undefined && parameter.max > 0 ? parameter.max : undefined;
}
export function resolveEmpiriolabsBaseModel(id: string) {
const explicit = CANONICAL_BASE_MODELS[id];
if (explicit !== undefined) return explicit;
return canonicalCandidates(id)
.map((candidate) => resolveCanonicalBaseModel(candidate))
.find((candidate) => candidate !== undefined);
}
function canonicalCandidates(id: string) {
const candidates: string[] = [];
if (id.startsWith("deepseek-")) {
candidates.push(`deepseek/${id}`);
candidates.push(`deepseek/${id.replace(/^deepseek-v(\d+)-(\d+)/, "deepseek-v$1.$2")}`);
}
if (id.startsWith("glm-")) {
const normalized = id
.replace(/^glm-(\d+)-(\d+)/, "glm-$1.$2")
.replace(/^glm-(\d+)-(\d+)v/, "glm-$1.$2v");
candidates.push(`z-ai/${id}`);
candidates.push(`z-ai/${normalized}`);
}
if (id.startsWith("kimi-")) {
const normalized = id.replace(/^(kimi-k\d+)-(\d+)/, "$1.$2");
candidates.push(`moonshotai/${id}`);
candidates.push(`moonshotai/${normalized}`);
}
if (id.startsWith("minimax-")) {
const normalized = id.replace(/^minimax-m(\d+)-(\d+)/, "minimax-m$1.$2");
candidates.push(`minimax/${id}`);
candidates.push(`minimax/${normalized}`);
}
if (id.startsWith("mimo-")) {
const normalized = id.replace(/^mimo-v(\d+)-(\d+)/, "mimo-v$1.$2");
candidates.push(`xiaomi/${id}`);
candidates.push(`xiaomi/${normalized}`);
}
if (id.startsWith("qwen")) {
const normalized = id.replace(/^(qwen\d+)-(\d+)/, "$1.$2");
candidates.push(`qwen/${id}`);
candidates.push(`qwen/${normalized}`);
}
return [...new Set(candidates)];
}
export function buildEmpiriolabsModel(
model: EmpiriolabsModel,
existing: ExistingModel | undefined,
baseModel = existing?.base_model ?? resolveEmpiriolabsBaseModel(model.id),
): SyncedModel | undefined {
const features = new Set(model.features ?? []);
const capabilities = (model.capabilities ?? {}) as Record<string, unknown>;
const input = modalities(model.input_modalities, ["text"]);
const output = modalities(model.output_modalities, ["text"]);
const attachment = input.some((value) => value !== "text");
const reasoning =
capabilities.reasoning === true || features.has("reasoning") || existing?.reasoning === true;
const toolCall =
features.has("function_calling") || features.has("tools") || existing?.tool_call === true;
const structuredOutput = features.has("structured_output") || existing?.structured_output === true;
const temperature =
(model.supported_parameters ?? []).some((parameter) => parameter.name === "temperature")
|| existing?.temperature === true;
const pricingTiers = model.pricing === undefined
? []
: Array.isArray(model.pricing)
? [...model.pricing].sort((a, b) => (a.min_context ?? 0) - (b.min_context ?? 0))
: [model.pricing];
const baseCost = tierCost(pricingTiers[0]);
const contextTiers = pricingTiers
.slice(1)
.map((tier) => {
const tierPricing = tierCost(tier);
return tierPricing === undefined || tier.min_context === undefined || tier.min_context === null
? undefined
: { tier: { type: "context" as const, size: tier.min_context }, ...tierPricing };
})
.filter((tier): tier is NonNullable<typeof tier> => tier !== undefined);
const cost = baseCost !== undefined
? {
...baseCost,
reasoning: existing?.cost?.reasoning,
cache_write: existing?.cost?.cache_write,
tiers: contextTiers.length > 0 ? contextTiers : undefined,
}
: existing?.cost;
const context =
model.context_length ?? model.context_window ?? existing?.limit?.context;
// No usable context window: cannot build a valid model TOML, so skip.
if (context === undefined || context === null) return undefined;
const releaseDate = baseModel === undefined
? model.model_released_at ?? existing?.release_date
: undefined;
const lastUpdated = baseModel === undefined
? model.model_released_at ?? existing?.last_updated ?? releaseDate
: existing?.last_updated ?? releaseDate;
const outputTokens = model.max_output_tokens
?? parameterOutputLimit(model)
?? existing?.limit?.output
?? context;
const limit = {
context,
input: existing?.limit?.input,
output: outputTokens,
};
const values: Partial<SyncedFullModel> = {
name: model.display_name ?? model.name ?? model.id,
description: baseModel === undefined ? existing?.description ?? model.description : existing?.description,
family: existing?.family,
release_date: releaseDate,
last_updated: lastUpdated,
attachment,
reasoning,
reasoning_options: reasoning ? reasoningOptions(model) : undefined,
temperature: temperature || undefined,
tool_call: toolCall,
structured_output:
(model.structured_output !== undefined && model.structured_output !== null)
|| structuredOutput
|| undefined,
knowledge: existing?.knowledge,
open_weights: existing?.open_weights,
status: existing?.status,
interleaved: existing?.interleaved,
cost,
limit,
modalities: { input, output },
};
if (baseModel !== undefined) {
return factorBaseModel(baseModel, values, limit, existing?.base_model_omit);
}
if (existing === undefined) return undefined;
const required = z.object({
name: z.string(),
description: z.string(),
release_date: z.string(),
last_updated: z.string(),
open_weights: z.boolean(),
cost: z.object({ input: z.number(), output: z.number() }),
}).safeParse(values);
if (!required.success) {
throw new Error(`EmpirioLabs model ${model.id} has incomplete local metadata required for sync`);
}
return values as SyncedFullModel;
}
+19 -1
View File
@@ -29,13 +29,31 @@ const GoogleResponse = z.object({
type GoogleModel = z.infer<typeof GoogleModel>;
const TrackedModelPrefixes = [
"deep-research-",
"gemini-",
"gemma-",
"imagen-",
"lyria-",
"nano-banana-",
"veo-",
];
export function shouldTrackGoogleModel(id: string) {
return TrackedModelPrefixes.some((prefix) => id.startsWith(prefix));
}
export const google = {
id: "google",
name: "Google",
modelsDir: "providers/google/models",
skipCreates: true,
// /v1beta/models has no lifecycle fields and can retain shut-down,
// superseded, moving-alias, and EAP model IDs.
trackMissingModels: false,
sourceID(model) {
return model.name.replace(/^models\//, "");
const id = model.name.replace(/^models\//, "");
return shouldTrackGoogleModel(id) ? id : undefined;
},
skippedNotice(ids) {
if (ids.length === 0) return [];
+156
View File
@@ -0,0 +1,156 @@
import { existsSync } from "node:fs";
import path from "node:path";
import { z } from "zod";
import type { ExistingModel, SyncProvider, SyncedFullModel, SyncedModel } from "../index.js";
import { factorBaseModel } from "./openrouter.js";
const API_ENDPOINT = "https://hyper.charm.land/v1/models";
const MODELS_DIR = path.join(import.meta.dirname, "..", "..", "..", "..", "..", "models");
function baseModelExists(modelID: string) {
return existsSync(path.join(MODELS_DIR, `${modelID}.toml`));
}
const ReasoningEffort = z.enum([
"default",
"max",
"low",
"high",
"none",
"medium",
"minimal",
"xhigh",
]);
export const HyperModel = z.object({
id: z.string(),
created: z.number(),
display_name: z.string(),
context_window: z.number(),
max_output_tokens: z.number(),
capabilities: z.object({
vision: z.boolean().optional(),
}).optional(),
reasoning: z.object({
effort_levels: z.array(z.object({
value: z.string(),
display: z.string().optional(),
})).optional(),
}).optional(),
pricing: z.object({
input: z.number().optional(),
output: z.number().optional(),
cache_hit: z.number().optional(),
cache_create: z.number().optional(),
}).optional(),
}).passthrough();
const HyperResponse = z.object({
data: z.array(HyperModel),
}).passthrough();
export type HyperModel = z.infer<typeof HyperModel>;
export const hyper = {
id: "hyper",
name: "Charm Hyper",
modelsDir: "providers/hyper/models",
preserveBaseModels: false,
async fetchModels() {
const key = process.env.HYPER_API_KEY;
const response = await fetch(API_ENDPOINT, key
? { headers: { Authorization: `Bearer ${key}` } }
: undefined);
if (!response.ok) {
throw new Error(`Hyper models request failed: ${response.status} ${response.statusText}`);
}
return response.json();
},
parseModels(raw) {
return HyperResponse.parse(raw).data;
},
translateModel(model, context) {
const existing = context.existing(model.id);
const baseModel = existing?.base_model;
if (baseModel === undefined || !baseModelExists(baseModel)) return undefined;
return {
id: model.id,
model: buildHyperModel(model, existing, baseModel),
};
},
} satisfies SyncProvider<HyperModel>;
function dateFromTimestamp(timestamp: number) {
return new Date(timestamp * 1000).toISOString().slice(0, 10);
}
function reasoningOptions(model: HyperModel) {
const effortLevels = model.reasoning?.effort_levels?.map((level) => level.value) ?? [];
if (effortLevels.length === 0) return [];
const values = effortLevels.filter(isReasoningEffort);
if (values.length === 0) return [{ type: "toggle" as const }];
return [{ type: "effort" as const, values }];
}
function isReasoningEffort(value: string): value is z.infer<typeof ReasoningEffort> {
return ReasoningEffort.safeParse(value).success;
}
function price(value: number) {
return Math.round(value * 1_000_000) / 1_000_000;
}
function positivePrice(value: number | undefined) {
return value !== undefined && value > 0 ? price(value) : undefined;
}
function buildCost(model: HyperModel, existing: ExistingModel["cost"] | undefined) {
const pricing = model.pricing;
if (pricing?.input === undefined || pricing.output === undefined) return existing;
return {
input: price(pricing.input),
output: price(pricing.output),
cache_read: positivePrice(pricing.cache_hit)
?? (pricing.cache_hit === undefined ? existing?.cache_read : undefined),
cache_write: positivePrice(pricing.cache_create)
?? (pricing.cache_create === undefined ? existing?.cache_write : undefined),
reasoning: existing?.reasoning,
};
}
function hyperModalities(vision: boolean) {
const input = vision ? ["text" as const, "image" as const] : ["text" as const];
return {
input,
output: ["text" as const],
};
}
export function buildHyperModel(
model: HyperModel,
existing: ExistingModel | undefined,
baseModel: string,
today = new Date().toISOString().slice(0, 10),
): SyncedModel {
const limit = {
context: model.context_window,
input: existing?.limit?.input,
output: model.max_output_tokens,
};
const modalities = hyperModalities(model.capabilities?.vision ?? false);
const values: Partial<SyncedFullModel> = {
attachment: modalities.input.some((value) => value !== "text"),
modalities,
reasoning: model.reasoning != null,
reasoning_options: model.reasoning != null ? reasoningOptions(model) : undefined,
release_date: existing?.release_date ?? dateFromTimestamp(model.created),
last_updated: existing?.last_updated ?? today,
interleaved: existing?.interleaved,
cost: buildCost(model, existing?.cost),
limit,
};
return factorBaseModel(baseModel, values, limit, existing?.base_model_omit);
}
+428
View File
@@ -0,0 +1,428 @@
import { z } from "zod";
import { readFileSync, readdirSync } from "node:fs";
import path from "node:path";
import { describeModel } from "../../describe.js";
import { inferKimiFamily, ModelFamilyValues } from "../../family.js";
import type { ExistingModel, SyncProvider, SyncedFullModel, SyncedModel } from "../index.js";
import { factorBaseModel, resolveCanonicalBaseModel } from "./openrouter.js";
const API_ENDPOINT = "https://api.kilo.ai/api/gateway/models";
const MODELS_DIR = path.join(import.meta.dirname, "..", "..", "..", "..", "..", "models");
const modelMetadataByID = new Map<string, Record<string, unknown>>();
const modelMetadataFilesByProvider = new Map<string, Set<string>>();
export const KiloModel = z.object({
id: z.string(),
name: z.string(),
created: z.number(),
description: z.string().optional(),
hugging_face_id: z.string().nullable().optional(),
knowledge_cutoff: z.string().nullable().optional(),
context_length: z.number(),
architecture: z.object({
modality: z.string().optional(),
input_modalities: z.array(z.string()),
output_modalities: z.array(z.string()),
tokenizer: z.string().optional(),
}),
pricing: z.object({
prompt: z.string(),
completion: z.string(),
internal_reasoning: z.string().optional(),
input_cache_read: z.string().optional(),
input_cache_write: z.string().optional(),
}),
top_provider: z.object({
context_length: z.number().nullable(),
max_completion_tokens: z.number().nullable(),
is_moderated: z.boolean().optional(),
}),
supported_parameters: z.array(z.string()),
opencode: z
.object({
variants: z
.record(
z.object({
reasoning: z
.object({
enabled: z.boolean(),
effort: z.string().optional(),
})
.optional(),
}),
)
.optional(),
})
.optional(),
});
export const KiloResponse = z.object({
data: z.array(KiloModel),
}).passthrough();
export type KiloModel = z.infer<typeof KiloModel>;
export const kilo = {
id: "kilo",
name: "Kilo",
modelsDir: "providers/kilo/models",
async fetchModels() {
const headers = process.env.KILO_API_KEY
? { Authorization: `Bearer ${process.env.KILO_API_KEY}` }
: undefined;
const response = await fetch(API_ENDPOINT, { headers });
if (!response.ok) {
throw new Error(`Kilo request failed: ${response.status} ${response.statusText}`);
}
return response.json();
},
parseModels(raw) {
return KiloResponse.parse(raw).data;
},
translateModel(model, context) {
// Kilo serves deprecated/unavailable routes as degraded stubs:
// negative pricing (`"-1"`) and an empty `supported_parameters` array. Syncing
// those would wrongly flip `reasoning`/`tool_call`/`structured_output` to false
// and strip `reasoning_options`. Leave the authored file untouched instead, and
// skip the model entirely when we have nothing to preserve.
if (isUnavailable(model)) {
const authored = context.authored(model.id);
return authored === undefined ? undefined : { id: model.id, model: authored as SyncedModel };
}
return {
id: model.id,
model: buildKiloModel(model, context.existing(model.id)),
};
},
} satisfies SyncProvider<KiloModel>;
function isUnavailable(model: KiloModel) {
return (
model.supported_parameters.length === 0 ||
Number(model.pricing.prompt) < 0 ||
Number(model.pricing.completion) < 0
);
}
function dateFromTimestamp(timestamp: number) {
return new Date(timestamp * 1000).toISOString().slice(0, 10);
}
function price(value: string | undefined) {
if (value === undefined) return undefined;
const number = Number(value);
return Number.isFinite(number) && number >= 0
? Math.round(number * 1_000_000_000_000) / 1_000_000
: undefined;
}
type Modality = "text" | "audio" | "image" | "video" | "pdf";
function modalities(values: string[], fallback: Modality[]): Modality[] {
const allowed = new Set<Modality>(["text", "audio", "image", "video", "pdf"]);
const result = values
.map((value) => value.toLowerCase())
.map((value) => value === "file" ? "pdf" : value)
.filter((value): value is Modality => allowed.has(value as Modality));
return [...new Set(result.length > 0 ? result : fallback)];
}
function inferFamily(model: KiloModel, name: string) {
const kimiFamily = inferKimiFamily(model.id, name);
if (kimiFamily !== undefined) return kimiFamily;
const target = `${model.id} ${name}`.toLowerCase();
return [...ModelFamilyValues]
.sort((a, b) => b.length - a.length)
.find((family) => {
const value = family.toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
if (family === "o") {
return new RegExp(`(^|[^a-z0-9])${value}(?=\\d|$|[^a-z0-9])`).test(target);
}
return new RegExp(`(^|[^a-z0-9])${value}(?=$|[^a-z0-9])`).test(target);
});
}
export function buildKiloModel(
model: KiloModel,
existing: ExistingModel | undefined,
baseModel?: string,
): SyncedModel {
const params = new Set(model.supported_parameters);
const name = model.name;
const apiDescription = model.description?.replaceAll(/\s+/g, " ").trim();
const input = modalities(model.architecture.input_modalities, ["text"]);
const output = modalities(model.architecture.output_modalities, ["text"]);
const prompt = price(model.pricing.prompt);
const completion = price(model.pricing.completion);
const reasoning = params.has("reasoning") || params.has("include_reasoning");
const reasoning_options = existing?.reasoning_options?.length
? existing.reasoning_options
: KiloReasoningOptions(model.opencode) ?? existing?.reasoning_options;
const context = model.top_provider.context_length ?? model.context_length;
const family = inferFamily(model, name);
const releaseDate = dateFromTimestamp(model.created);
const familyValue = existing?.family === "o" && family !== "o"
? family
: (existing?.family ?? family);
const attachment = input.some((value) => value !== "text");
const toolCall = params.has("tools") || params.has("tool_choice");
const structuredOutput = params.has("structured_outputs");
const knowledge = model.knowledge_cutoff?.slice(0, 10) ?? existing?.knowledge;
const openWeights = Boolean(model.hugging_face_id);
const cost = prompt !== undefined && completion !== undefined
? {
input: prompt,
output: completion,
reasoning: reasoning ? price(model.pricing.internal_reasoning) : undefined,
cache_read: price(model.pricing.input_cache_read),
cache_write: price(model.pricing.input_cache_write),
tiers: existing?.cost?.tiers,
}
: existing?.cost;
const limit = {
context,
input: existing?.limit?.input,
output: model.top_provider.max_completion_tokens ?? existing?.limit?.output ?? context,
};
const canonical = existing?.base_model ?? baseModel ?? resolveCanonicalBaseModel(model.id);
if (canonical !== undefined) {
return factorBaseModel(
canonical,
{
name: baseModel !== undefined || model.id.endsWith(":free") ? name : undefined,
description: existing?.description ?? apiDescription ?? describeModel({
id: model.id,
name,
family: familyValue,
reasoning,
tool_call: toolCall,
structured_output: structuredOutput,
open_weights: openWeights,
limit,
modalities: { input, output },
}),
attachment,
reasoning,
reasoning_options,
temperature: params.has("temperature"),
tool_call: toolCall,
structured_output: structuredOutput,
status: existing?.status,
interleaved: existing?.interleaved,
limit,
modalities: { input, output },
cost,
},
limit,
existing?.base_model === canonical ? existing.base_model_omit : undefined,
);
}
return {
name,
description: existing?.description ?? apiDescription ?? describeModel({
id: model.id,
name,
family: familyValue,
reasoning,
tool_call: toolCall,
structured_output: structuredOutput,
open_weights: openWeights,
limit,
modalities: { input, output },
}),
family: familyValue,
release_date: releaseDate,
last_updated: releaseDate,
attachment,
reasoning,
reasoning_options,
temperature: params.has("temperature"),
tool_call: toolCall,
structured_output: structuredOutput,
knowledge,
open_weights: openWeights,
status: existing?.status,
interleaved: existing?.interleaved,
cost,
limit,
modalities: { input, output },
} satisfies SyncedFullModel;
}
function KiloReasoningOptions(opencode: KiloModel["opencode"]): SyncedFullModel["reasoning_options"] {
if (opencode?.variants === undefined) return undefined;
const options: NonNullable<SyncedFullModel["reasoning_options"]> = [];
const variants = Object.entries(opencode.variants);
if (variants.length === 0) return undefined;
const reasoningEffortOrder = new Map<string, number>([
["none", 0],
["minimal", 1],
["low", 2],
["medium", 3],
["high", 4],
["xhigh", 5],
["max", 6],
]);
const efforts = variants
.filter(([, variant]) => variant.reasoning?.enabled === true)
.map(([, variant]) => variant.reasoning?.effort)
.filter((effort): effort is string => effort !== undefined);
const hasNone = variants.some(([, variant]) => variant.reasoning?.enabled === false);
const allEfforts = hasNone ? [...efforts, "none"] : [...efforts];
if (allEfforts.length > 0) {
const orderedEfforts = allEfforts.sort((a, b) => {
const order = (reasoningEffortOrder.get(a) ?? Number.MAX_SAFE_INTEGER)
- (reasoningEffortOrder.get(b) ?? Number.MAX_SAFE_INTEGER);
return order;
});
options.push({
type: "effort",
values: orderedEfforts as Array<string | null>,
});
}
return options.length > 0 ? options : undefined;
}
function modelMetadataExists(provider: string, modelID: string) {
let files = modelMetadataFilesByProvider.get(provider);
if (files === undefined) {
try {
files = new Set(readdirSync(path.join(MODELS_DIR, provider)));
} catch {
files = new Set();
}
modelMetadataFilesByProvider.set(provider, files);
}
return files.has(`${modelID}.toml`);
}
function baseModelOmit(
modelID: string,
limit: SyncedFullModel["limit"],
) {
const metadata = modelMetadata(modelID);
const omit: string[] = [];
const baseLimit = metadata.limit;
if (
isPlainObject(baseLimit) &&
baseLimit.input !== undefined &&
limit.input === undefined &&
baseLimit.context !== limit.context
) {
omit.push("limit.input");
}
return omit.length > 0 ? omit : undefined;
}
function baseModelOverrides(
modelID: string,
values: Partial<SyncedFullModel>,
) {
const metadata = modelMetadata(modelID);
const result: Record<string, unknown> = {};
for (const [key, value] of Object.entries(values)) {
const override = inheritedOverride(value, metadata[key]);
if (override !== undefined) result[key] = override;
}
return result;
}
function inheritedOverride(value: unknown, inherited: unknown): unknown {
if (value === undefined) return undefined;
if (sameInheritedValue(value, inherited)) return undefined;
if (isPlainObject(value) && isPlainObject(inherited)) {
const overrides = Object.fromEntries(
Object.entries(value)
.map(([key, item]) => [key, inheritedOverride(item, inherited[key])])
.filter(([, item]) => item !== undefined),
);
return Object.keys(overrides).length > 0 ? overrides : undefined;
}
return stripUndefined(value);
}
function stripUndefined(value: unknown): unknown {
if (Array.isArray(value)) return value.map(stripUndefined);
if (isPlainObject(value)) {
return Object.fromEntries(
Object.entries(value)
.filter(([, item]) => item !== undefined)
.map(([key, item]) => [key, stripUndefined(item)]),
);
}
return value;
}
function sameInheritedValue(value: unknown, inherited: unknown) {
return stableInheritedValue(value) === stableInheritedValue(inherited);
}
function stableInheritedValue(value: unknown): string {
if (Array.isArray(value)) {
const items = value.map(stableInheritedValue);
const ordered = value.every((item) => item === null || typeof item !== "object")
? items.sort()
: items;
return `[${ordered.join(",")}]`;
}
if (isPlainObject(value)) {
return `{${Object.entries(value)
.filter(([, item]) => item !== undefined)
.sort(([a], [b]) => a.localeCompare(b))
.map(([key, item]) => `${JSON.stringify(key)}:${stableInheritedValue(item)}`)
.join(",")}}`;
}
return JSON.stringify(value);
}
function isPlainObject(value: unknown): value is Record<string, unknown> {
return value !== null && typeof value === "object" && !Array.isArray(value);
}
function modelMetadata(modelID: string) {
let metadata = modelMetadataByID.get(modelID);
if (metadata === undefined) {
const filePath = path.join(MODELS_DIR, `${modelID}.toml`);
metadata = Bun.TOML.parse(readFileSync(filePath, "utf8")) as Record<string, unknown>;
modelMetadataByID.set(modelID, metadata);
}
return metadata;
}
function canonicalCandidates(provider: string, modelID: string) {
const candidates = [modelID];
if (provider === "anthropic") {
candidates.push(modelID.replace(/(claude-(?:opus|sonnet|haiku)-\d+)\.(\d+)/, "$1-$2"));
candidates.push(modelID.replace(/^claude-3\.5-/, "claude-3-5-"));
}
if (provider === "llama") {
candidates.push(modelID.replace(/^llama-(\d+)-(\d+)/, "llama-$1.$2"));
candidates.push(modelID.replace(/^llama-(4)-(maverick|scout)$/, "llama-$1-$2-17b"));
}
if (provider === "mistral") {
candidates.push(modelID.replace(/-latest$/, ""));
}
if (provider === "minimax") {
candidates.push(modelID.replace(/^minimax-m/, "MiniMax-M"));
}
return [...new Set(candidates)];
}
@@ -0,0 +1,337 @@
import { z } from "zod";
import { describeModel } from "../../describe.js";
import type { ExistingModel, SyncProvider, SyncedFullModel, SyncedModel } from "../index.js";
import { factorBaseModel, resolveCanonicalBaseModel } from "./openrouter.js";
const API_ENDPOINT = "https://api-gateway.merge.dev/v1/models";
const AvailabilityStatus = z.enum(["available", "deprecated"]);
const VendorReasoning = z.object({
configurable: z.boolean().optional(),
disable_supported: z.boolean().optional(),
default_enabled: z.boolean().optional(),
controls: z.array(z.string()).optional(),
output_style: z.string().nullable().optional(),
}).passthrough();
const VendorCapabilities = z.object({
input: z.array(z.enum(["text", "audio", "image", "document", "embedding"])),
output: z.array(z.enum(["text", "audio", "tool_use", "embedding"])),
supports_tool_calling: z.boolean(),
supports_tool_choice: z.boolean().default(false),
supports_structured_outputs: z.boolean(),
supports_reasoning: z.boolean().optional(),
reasoning: VendorReasoning.nullable().optional(),
streaming: z.boolean(),
}).passthrough();
const PromptCaching = z.object({
mode: z.enum(["automatic", "explicit", "none"]).optional(),
cache_read_cost_per_million: z.number().nonnegative().nullable().optional(),
cache_write_cost_per_million: z.number().nonnegative().nullable().optional(),
}).passthrough();
const VendorInfo = z.object({
launch_date: z.string().nullable().optional(),
context_window: z.number().int().nonnegative(),
max_output_tokens: z.number().int().nonnegative(),
availability_status: AvailabilityStatus,
capabilities: VendorCapabilities,
pricing: z.object({
currency: z.literal("USD").default("USD"),
input_per_million: z.number().nonnegative(),
output_per_million: z.number().nonnegative(),
cache_read_per_million: z.number().nonnegative().nullable().optional(),
cache_write_per_million: z.number().nonnegative().nullable().optional(),
}).passthrough(),
prompt_caching: PromptCaching.nullable().optional(),
}).passthrough();
export const MergeGatewayModel = z.object({
model: z.string().min(1),
provider: z.string().min(1),
display_name: z.string().min(1),
vendors: z.record(VendorInfo),
availability_status: AvailabilityStatus,
created_at: z.string().nullable().optional(),
updated_at: z.string().nullable().optional(),
}).passthrough().superRefine((model, context) => {
const namespace = model.model.split("/")[0];
if (namespace !== model.provider) {
context.addIssue({
code: z.ZodIssueCode.custom,
path: ["provider"],
message: `Model namespace ${namespace} does not match provider ${model.provider}`,
});
}
});
export const MergeGatewayResponse = z.object({
object: z.literal("list").default("list"),
data: z.array(MergeGatewayModel),
has_more: z.boolean().default(false),
next_cursor: z.string().nullable().optional(),
}).passthrough();
export type MergeGatewayModel = z.infer<typeof MergeGatewayModel>;
export type MergeGatewayVendor = z.infer<typeof VendorInfo>;
export async function fetchMergeGatewayModels(
fetcher: typeof fetch = fetch,
apiKey = process.env.MERGE_GATEWAY_API_KEY,
) {
if (!apiKey) throw new Error("MERGE_GATEWAY_API_KEY is required to sync Merge Gateway models");
const models = new Map<string, MergeGatewayModel>();
const cursors = new Set<string>();
let cursor: string | undefined;
do {
const url = new URL(API_ENDPOINT);
url.searchParams.set("limit", "500");
if (cursor !== undefined) url.searchParams.set("cursor", cursor);
const response = await fetcher(url, {
headers: { Authorization: `Bearer ${apiKey}` },
});
if (!response.ok) {
throw new Error(`Merge Gateway request failed: ${response.status} ${response.statusText}`);
}
const page = MergeGatewayResponse.parse(await response.json());
for (const model of page.data) {
if (models.has(model.model)) {
throw new Error(`Merge Gateway returned duplicate model ID: ${model.model}`);
}
models.set(model.model, model);
}
if (!page.has_more) break;
if (!page.next_cursor) throw new Error("Merge Gateway returned has_more=true without next_cursor");
if (cursors.has(page.next_cursor)) throw new Error(`Merge Gateway repeated cursor: ${page.next_cursor}`);
cursors.add(page.next_cursor);
cursor = page.next_cursor;
} while (true);
return {
object: "list" as const,
data: [...models.values()],
has_more: false,
next_cursor: null,
};
}
export const mergeGateway = {
id: "merge-gateway",
name: "Merge Gateway",
modelsDir: "providers/merge-gateway/models",
// API-key policy can affect catalog visibility. Retain missing local models
// until Merge exposes an account-independent catalog response.
deleteMissing: false,
sourceID(model) {
return model.model;
},
skippedNotice(ids) {
if (ids.length === 0) return [];
return [
`${ids.length} Merge Gateway models were skipped because they are not text models or lack canonical metadata.`,
`Skipped remote IDs: ${ids.map((id) => `\`${id}\``).join(", ")}`,
];
},
missingNotice(paths) {
if (paths.length === 0) return [];
return [
`${paths.length} local Merge Gateway models were absent from the API response and retained for manual lifecycle review.`,
`Retained local paths: ${paths.map((item) => `\`${item}\``).join(", ")}`,
];
},
fetchModels() {
return fetchMergeGatewayModels();
},
parseModels(raw) {
return MergeGatewayResponse.parse(raw).data;
},
translateModel(model, context) {
const existing = context.existing(model.model);
const translated = buildMergeGatewayModel(model, existing, context.authored(model.model));
return translated === undefined ? undefined : { id: model.model, model: translated };
},
} satisfies SyncProvider<MergeGatewayModel>;
export function selectMergeGatewayVendor(model: MergeGatewayModel) {
const canonical = model.vendors[model.provider];
if (canonical?.availability_status === "available") {
return { id: model.provider, info: canonical };
}
// Match Gateway's default resolver: when the model author's native route is
// unavailable, use the cheapest active route by combined input + output
// price. Object order is preserved for equal prices; the public API emits
// vendors in CMS-priority order, which is Gateway's own tiebreaker.
const available = Object.entries(model.vendors)
.filter(([, info]) => info.availability_status === "available");
const selected = available.reduce<typeof available[number] | undefined>((best, candidate) => {
if (best === undefined) return candidate;
const bestCost = best[1].pricing.input_per_million + best[1].pricing.output_per_million;
const candidateCost = candidate[1].pricing.input_per_million + candidate[1].pricing.output_per_million;
return candidateCost < bestCost ? candidate : best;
}, undefined);
if (selected !== undefined) return { id: selected[0], info: selected[1] };
if (canonical !== undefined) return { id: model.provider, info: canonical };
const fallback = Object.entries(model.vendors)[0];
return fallback === undefined ? undefined : { id: fallback[0], info: fallback[1] };
}
export function buildMergeGatewayModel(
model: MergeGatewayModel,
existing: ExistingModel | undefined,
authored: ExistingModel | undefined = existing,
): SyncedModel | undefined {
const selected = selectMergeGatewayVendor(model);
if (selected === undefined || !selected.info.capabilities.output.includes("text")) return undefined;
const input = modalities(selected.info.capabilities.input);
const output = modalities(selected.info.capabilities.output);
const limit = {
context: selected.info.context_window || existing?.limit?.context || 0,
// Preserve only a provider-authored input cap. `existing` is resolved
// against base-model metadata, so using its inherited input value here
// can keep an impossible cap when the gateway reports a smaller context.
input: authored?.limit?.input,
output: selected.info.max_output_tokens || existing?.limit?.output || selected.info.context_window,
};
const cachePricing = mergeGatewayCachePricing(selected.info, existing);
const cost = {
input: selected.info.pricing.input_per_million,
output: selected.info.pricing.output_per_million,
reasoning: existing?.cost?.reasoning,
cache_read: cachePricing.read,
cache_write: cachePricing.write,
input_audio: existing?.cost?.input_audio,
output_audio: existing?.cost?.output_audio,
tiers: existing?.cost?.tiers,
};
const status = model.availability_status === "deprecated" || selected.info.availability_status === "deprecated"
? "deprecated" as const
: undefined;
const baseModel = existing?.base_model ?? resolveCanonicalBaseModel(model.model);
// `supports_reasoning` is not part of the documented public schema
// (PublicVendorModelCapabilities) and is inconsistently populated across
// vendor routes: the same model can report `true` on one route and `false`
// on another (e.g. anthropic/claude-opus-4-6 reports `false` via `anthropic`
// and `true` via `bedrock`), and reasoning-only models such as
// deepseek/deepseek-r1 report `false` on their sole route. Treat it as a
// positive-only signal: `true` (always accompanied by route `reasoning`
// metadata) confirms the model reasons on the gateway, while `false`/absent
// means unknown and preserves curated reasoning metadata.
const routeConfirmsReasoning = Object.values(model.vendors).some(
(vendor) => vendor.availability_status === "available" && vendor.capabilities.supports_reasoning === true,
);
const reasoning = routeConfirmsReasoning ? true : existing?.reasoning;
const existingReasoningOptions = existing?.reasoning_options ?? [];
const reasoningOptions = reasoning === true && existingReasoningOptions.length === 0
&& selected.info.capabilities.reasoning?.disable_supported === true
? [{ type: "toggle" as const }]
: reasoning === true
? existingReasoningOptions
: existing?.reasoning_options;
const modelSlug = model.model.split("/").at(-1)?.toLowerCase();
const displayNameIsID = model.display_name.includes("/")
|| model.display_name.toLowerCase() === modelSlug;
const authoritative = {
// Some catalog rows use an upstream org/model ID as display_name. Let
// canonical metadata provide the human-readable name for factored models.
name: baseModel !== undefined && displayNameIsID ? undefined : model.display_name,
attachment: input.some((value) => value !== "text"),
tool_call: selected.info.capabilities.supports_tool_calling,
structured_output: selected.info.capabilities.supports_structured_outputs,
status,
cost,
limit,
modalities: { input, output },
};
if (baseModel !== undefined) {
return factorBaseModel(
baseModel,
{
...authoritative,
description: existing?.description,
reasoning,
reasoning_options: reasoningOptions,
temperature: existing?.temperature,
interleaved: existing?.interleaved,
provider: existing?.provider,
experimental: existing?.experimental,
},
limit,
existing?.base_model_omit,
);
}
if (existing === undefined) return undefined;
const releaseDate = selected.info.launch_date
?? model.created_at?.slice(0, 10)
?? existing.release_date;
if (releaseDate === undefined) return undefined;
const lastUpdated = model.updated_at?.slice(0, 10)
?? existing.last_updated
?? releaseDate;
return {
...authoritative,
description: existing.description ?? describeModel({
id: model.model,
name: model.display_name,
family: existing.family,
reasoning,
tool_call: selected.info.capabilities.supports_tool_calling,
structured_output: selected.info.capabilities.supports_structured_outputs,
open_weights: existing.open_weights,
limit,
modalities: { input, output },
}),
family: existing.family,
release_date: releaseDate,
last_updated: lastUpdated,
reasoning: reasoning ?? false,
reasoning_options: reasoningOptions,
temperature: existing.temperature,
knowledge: existing.knowledge,
open_weights: existing.open_weights ?? false,
interleaved: existing.interleaved,
provider: existing.provider,
experimental: existing.experimental,
} satisfies SyncedFullModel;
}
function mergeGatewayCachePricing(
vendor: MergeGatewayVendor,
existing: ExistingModel | undefined,
) {
const promptCaching = vendor.prompt_caching;
const pricing = vendor.pricing;
if (promptCaching?.mode === "none") {
return { read: undefined, write: undefined };
}
return {
read: promptCaching?.cache_read_cost_per_million
?? pricing.cache_read_per_million
?? existing?.cost?.cache_read,
write: promptCaching?.cache_write_cost_per_million
?? pricing.cache_write_per_million
?? existing?.cost?.cache_write,
};
}
type Modality = "text" | "audio" | "image" | "video" | "pdf";
function modalities(values: string[]): Modality[] {
const allowed = new Set<Modality>(["text", "audio", "image", "video", "pdf"]);
return [...new Set(values
.map((value) => value === "document" ? "pdf" : value)
.filter((value): value is Modality => allowed.has(value as Modality))
)];
}
@@ -0,0 +1,348 @@
import { z } from "zod";
import { inferKimiFamily, ModelFamilyValues } from "../../family.js";
import type { ExistingModel, SyncProvider, SyncedFullModel, SyncedModel } from "../index.js";
import { factorBaseModel, resolveModelMetadataBaseModel } from "./openrouter.js";
const API_ENDPOINT = "https://nano-gpt.com/api/v1/models?detailed=true";
// NanoGPT accepts these exact request values, including `max`:
// https://github.com/Nano-GPT-com/nanogpt/blob/073b25b07e9af619333c679e694de664bf1ceb30/lib/utils/reasoningInput.ts#L12-L28
const ReasoningEffort = z.enum(["none", "minimal", "low", "medium", "high", "xhigh", "max"]);
const Pricing = z.object({
prompt: z.number().nullish(),
completion: z.number().nullish(),
input: z.number().nullish(),
output: z.number().nullish(),
cacheReadInputPer1kTokens: z.number().nullish(),
cacheWriteInputPer1kTokens: z.number().nullish(),
note: z.string().optional(),
}).passthrough();
const Architecture = z.object({
input_modalities: z.array(z.string()).optional(),
output_modalities: z.array(z.string()).optional(),
}).passthrough();
const Capabilities = z.object({
vision: z.boolean().optional(),
video_input: z.boolean().optional(),
audio_input: z.boolean().optional(),
reasoning: z.boolean().optional(),
tool_calling: z.boolean().optional(),
structured_output: z.boolean().optional(),
pdf_upload: z.boolean().optional(),
}).passthrough();
export const NanoGptModel = z.object({
id: z.string().min(1),
name: z.string().nullish(),
description: z.string().nullish(),
created: z.number().nullish(),
owned_by: z.string().nullish(),
context_length: z.number().int().nonnegative().nullish(),
max_output_tokens: z.number().int().nonnegative().nullish(),
architecture: Architecture.optional(),
capabilities: Capabilities.optional(),
reasoning_efforts: z.array(ReasoningEffort).nullish(),
open_weights: z.boolean().nullish(),
pricing: Pricing.optional(),
}).passthrough();
export const NanoGptResponse = z.object({
data: z.array(NanoGptModel),
}).passthrough();
export type NanoGptModel = z.infer<typeof NanoGptModel>;
type Modality = "text" | "audio" | "image" | "video" | "pdf";
export const nanoGpt = {
id: "nano-gpt",
name: "NanoGPT",
modelsDir: "providers/nano-gpt/models",
preserveDescriptions: false,
async fetchModels() {
const response = await fetch(process.env.NANO_GPT_MODELS_URL ?? API_ENDPOINT);
if (!response.ok) {
throw new Error(`NanoGPT models request failed: ${response.status} ${response.statusText}`);
}
return response.json();
},
parseModels(raw) {
return NanoGptResponse.parse(raw).data;
},
translateModel(model, context) {
const id = normalizeModelID(model.id);
const existing = context.existing(id);
const baseModel = existing?.base_model ?? resolveNanoGptBaseModel(model.id);
const translated = buildNanoGptModel(model, existing, baseModel);
if (translated === undefined) return undefined;
return {
id,
model: translated,
};
},
} satisfies SyncProvider<NanoGptModel>;
const ORG_ID_NORMALIZATION: Record<string, string | undefined> = {
nousresearch: "NousResearch",
qwen: "qwen",
thedrummer: "TheDrummer",
};
const BASE_MODEL_ALIASES: Record<string, string | undefined> = {
"claude-opus-4": "anthropic/claude-opus-4-0",
"claude-sonnet-4": "anthropic/claude-sonnet-4-0",
"cohere/north-mini-code": "cohere/north-mini-code-1-0",
};
const NANO_GPT_VARIANT_SUFFIX = /(?::(?:thinking|none|minimal|low|medium|high|xhigh|max|\d+)|-thinking)$/i;
const KNOWN_OPEN_WEIGHT_IDS = new Set([
"nex-agi/nex-n2-pro",
]);
export function buildNanoGptModel(
model: NanoGptModel,
existing: ExistingModel | undefined,
baseModel = existing?.base_model ?? resolveNanoGptBaseModel(model.id),
): SyncedModel | undefined {
const capabilities = model.capabilities ?? {};
const explicitInputModalities = model.architecture?.input_modalities;
const hasInputCapabilityMetadata = capabilities.vision !== undefined
|| capabilities.audio_input !== undefined
|| capabilities.video_input !== undefined
|| capabilities.pdf_upload !== undefined;
const addedInputModalities = [
...(capabilities.vision ? ["image"] : []),
...(capabilities.audio_input ? ["audio"] : []),
...(capabilities.video_input ? ["video"] : []),
...(capabilities.pdf_upload ? ["pdf"] : []),
];
const hasInputMetadata = explicitInputModalities !== undefined || hasInputCapabilityMetadata;
const hasOutputMetadata = model.architecture?.output_modalities !== undefined;
const input = normalizeModalities([
...explicitInputModalities
?? (hasInputCapabilityMetadata ? ["text"] : existing?.modalities?.input)
?? ["text"],
...addedInputModalities,
]);
const output = normalizeModalities(
model.architecture?.output_modalities ?? existing?.modalities?.output ?? ["text"],
);
const sourceContext = positive(model.context_length);
const sourceOutputLimit = positive(model.max_output_tokens);
const context = sourceContext ?? existing?.limit?.context;
const inputLimit = sourceContext ?? existing?.limit?.input;
const outputLimit = sourceOutputLimit ?? existing?.limit?.output;
const releaseDate = dateFromTimestamp(model.created) ?? existing?.release_date;
const inferredSourceReasoning = capabilities.reasoning
?? (model.reasoning_efforts != null ? true : undefined);
const reasoning = inferredSourceReasoning ?? existing?.reasoning ?? false;
const cost = buildCost(model.pricing, existing);
if (baseModel !== undefined) {
const existingAlreadyFactored = existing?.base_model === baseModel;
const factoredModalities = {
input: hasInputMetadata || existing !== undefined ? input : undefined,
output: hasOutputMetadata || existing !== undefined ? output : undefined,
};
const factoredLimit = {
context: sourceContext ?? existing?.limit?.context,
input: sourceContext ?? existing?.limit?.input,
output: sourceOutputLimit ?? existing?.limit?.output,
};
const sourceReasoning = inferredSourceReasoning;
const sourceReasoningOptions = reasoningOptions(model, sourceReasoning, existing?.reasoning_options);
return factorBaseModel(
baseModel,
{
name: existing?.name ?? model.name ?? undefined,
description: existingAlreadyFactored ? existing?.description : undefined,
family: existingAlreadyFactored ? existing?.family : undefined,
release_date: existingAlreadyFactored ? existing?.release_date : undefined,
last_updated: existingAlreadyFactored ? existing?.last_updated : undefined,
attachment: hasInputMetadata
? input.some((value) => value !== "text")
: existing?.attachment,
reasoning: sourceReasoning ?? existing?.reasoning,
reasoning_options: sourceReasoningOptions,
temperature: existing?.temperature,
tool_call: capabilities.tool_calling ?? existing?.tool_call,
structured_output: capabilities.structured_output ?? existing?.structured_output,
knowledge: existing?.knowledge,
status: existing?.status,
interleaved: existing?.interleaved,
provider: existing?.provider,
experimental: existing?.experimental,
cost,
limit: factoredLimit,
modalities: factoredModalities,
},
factoredLimit,
existingAlreadyFactored ? existing?.base_model_omit : undefined,
);
}
if (context === undefined || outputLimit === undefined || releaseDate === undefined) {
return undefined;
}
const values = {
name: existing?.name ?? model.name ?? humanizeModelName(model.id),
description: existing?.description ?? model.description ?? `${model.name ?? humanizeModelName(model.id)} on NanoGPT.`,
family: existing?.family ?? inferFamily(model.id, model.name ?? ""),
release_date: releaseDate,
last_updated: existing?.last_updated ?? releaseDate,
attachment: input.some((value) => value !== "text"),
reasoning,
reasoning_options: reasoningOptions(model, reasoning, existing?.reasoning_options),
temperature: existing?.temperature,
tool_call: capabilities.tool_calling ?? existing?.tool_call ?? false,
structured_output: capabilities.structured_output ?? existing?.structured_output,
knowledge: existing?.knowledge,
status: existing?.status,
interleaved: existing?.interleaved,
provider: existing?.provider,
experimental: existing?.experimental,
cost,
limit: { context, input: inputLimit ?? context, output: outputLimit },
modalities: { input, output },
};
return {
...values,
open_weights: model.open_weights
?? (KNOWN_OPEN_WEIGHT_IDS.has(model.id.toLowerCase()) ? true : existing?.open_weights)
?? false,
} satisfies SyncedFullModel;
}
function buildCost(
pricing: NanoGptModel["pricing"],
existing: ExistingModel | undefined,
): SyncedFullModel["cost"] {
if (pricing === undefined) return existing?.cost;
if (pricing.note === "varies_by_modality") return existing?.cost;
const input = pricing.input ?? pricing.prompt;
const output = pricing.output ?? pricing.completion;
if (!validPrice(input) || !validPrice(output)) return existing?.cost;
return {
input: price(input),
output: price(output),
reasoning: existing?.cost?.reasoning,
cache_read: !validPrice(pricing.cacheReadInputPer1kTokens)
? existing?.cost?.cache_read
: price(pricing.cacheReadInputPer1kTokens * 1_000),
cache_write: !validPrice(pricing.cacheWriteInputPer1kTokens)
? existing?.cost?.cache_write
: price(pricing.cacheWriteInputPer1kTokens * 1_000),
input_audio: existing?.cost?.input_audio,
output_audio: existing?.cost?.output_audio,
tiers: existing?.cost?.tiers,
};
}
function reasoningOptions(
model: NanoGptModel,
reasoning: boolean | undefined,
existing: SyncedFullModel["reasoning_options"],
): SyncedFullModel["reasoning_options"] {
if (reasoning === false) return undefined;
if (reasoning === undefined) return existing;
if (model.reasoning_efforts == null) return existing ?? [];
if (model.reasoning_efforts.length === 0) return [];
return [{ type: "effort", values: [...model.reasoning_efforts] }];
}
export function resolveNanoGptBaseModel(modelID: string) {
let normalized = normalizeModelID(modelID);
if (normalized.toLowerCase().startsWith("tee/")) {
normalized = normalizeModelID(normalized.slice("TEE/".length));
}
const exact = resolveNanoGptCanonicalCandidate(normalized);
if (exact !== undefined) return exact;
const stripped = stripNanoGptVariantSuffixes(normalized);
return stripped === normalized ? undefined : resolveNanoGptCanonicalCandidate(stripped);
}
function resolveNanoGptCanonicalCandidate(modelID: string) {
return BASE_MODEL_ALIASES[modelID.toLowerCase()] ?? resolveModelMetadataBaseModel(modelID);
}
function stripNanoGptVariantSuffixes(modelID: string) {
let normalized = modelID;
while (true) {
const stripped = normalized.replace(NANO_GPT_VARIANT_SUFFIX, "");
if (stripped === normalized) return normalized;
normalized = stripped;
}
}
function normalizeModalities(values: string[]): Modality[] {
const allowed = new Set<Modality>(["text", "audio", "image", "video", "pdf"]);
const result = values
.map((value) => normalizeModality(value))
.filter((value): value is Modality => allowed.has(value as Modality));
return [...new Set(result.length > 0 ? result : ["text"] as Modality[])];
}
function normalizeModality(value: string) {
const lower = value.toLowerCase();
if (lower === "images") return "image";
if (lower === "videos") return "video";
if (lower === "audios") return "audio";
if (lower === "documents") return "pdf";
return lower;
}
function normalizeModelID(modelId: string) {
const [org, ...parts] = modelId.split("/");
if (org === undefined || parts.length === 0) return modelId;
const normalizedOrg = ORG_ID_NORMALIZATION[org.toLowerCase()];
return normalizedOrg === undefined ? modelId : `${normalizedOrg}/${parts.join("/")}`;
}
function inferFamily(id: string, name: string) {
const kimiFamily = inferKimiFamily(id, name);
if (kimiFamily !== undefined) return kimiFamily;
const target = `${id} ${name}`.toLowerCase();
return [...ModelFamilyValues]
.sort((a, b) => b.length - a.length)
.find((family) => {
const value = family.toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
if (family === "o") return new RegExp(`(^|[^a-z0-9])${value}(?=\\d)`).test(target);
return new RegExp(`(^|[^a-z0-9])${value}(?=$|[^a-z0-9])`).test(target);
});
}
function humanizeModelName(modelId: string) {
const modelPart = modelId.split("/").at(-1) ?? modelId;
return modelPart
.replace(/[:/_-]+/g, " ")
.replace(/\b\w/g, (value) => value.toUpperCase());
}
function dateFromTimestamp(timestamp: number | null | undefined) {
if (timestamp == null || timestamp <= 0) return undefined;
return new Date(timestamp * 1_000).toISOString().slice(0, 10);
}
function positive(value: number | null | undefined) {
return value == null || value <= 0 ? undefined : value;
}
function price(value: number) {
return Math.round(value * 1_000_000) / 1_000_000;
}
function validPrice(value: number | null | undefined): value is number {
return value !== null && value !== undefined && value >= 0;
}
@@ -56,6 +56,9 @@ export const openai = {
name: "OpenAI",
modelsDir: "providers/openai/models",
skipCreates: true,
// /v1/models is account-scoped and includes legacy, internal, and
// non-catalog surfaces without authoritative lifecycle metadata.
trackMissingModels: false,
deleteMissing: false,
sourceID(model) {
return model.id;
+102 -17
View File
@@ -10,11 +10,14 @@ const API_ENDPOINT = "https://openrouter.ai/api/v1/models";
const MODELS_DIR = path.join(import.meta.dirname, "..", "..", "..", "..", "..", "models");
const modelMetadataByID = new Map<string, Record<string, unknown>>();
const modelMetadataFilesByProvider = new Map<string, Set<string>>();
let allModelMetadataIDs: string[] | undefined;
const CANONICAL_BASE_MODEL_OVERRIDES = {
"openai/gpt-5.6-luna-pro": "openai/gpt-5.6-luna",
"openai/gpt-5.6-sol-pro": "openai/gpt-5.6-sol",
"openai/gpt-5.6-terra-pro": "openai/gpt-5.6-terra",
"anthropic/claude-opus-4.7-fast": "anthropic/claude-opus-4-7",
"anthropic/claude-opus-4.8-fast": "anthropic/claude-opus-4-8",
} as const;
const CANONICAL_PROVIDER_PREFIXES = {
@@ -27,17 +30,22 @@ const CANONICAL_PROVIDER_PREFIXES = {
"meta-llama": { provider: "llama", metadata: "meta" },
minimax: { provider: "minimax", metadata: "minimax" },
mistralai: { provider: "mistral", metadata: "mistral" },
moonshot: { provider: "moonshotai", metadata: "moonshotai" },
moonshotai: { provider: "moonshotai", metadata: "moonshotai" },
openai: { provider: "openai", metadata: "openai" },
nvidia: { provider: "nvidia", metadata: "nvidia" },
qwen: { provider: "alibaba", metadata: "alibaba" },
sakana: { provider: "sakana", metadata: "sakana" },
stepfun: { provider: "stepfun", metadata: "stepfun" },
"stepfun-ai": { provider: "stepfun", metadata: "stepfun" },
tencent: { provider: "tencent", metadata: "tencent" },
thinkingmachines: { provider: "thinkingmachines", metadata: "thinkingmachines" },
"x-ai": { provider: "xai", metadata: "xai" },
xai: { provider: "xai", metadata: "xai" },
xiaomi: { provider: "xiaomi", metadata: "xiaomi" },
zai: { provider: "zai", metadata: "zhipuai" },
"z-ai": { provider: "zai", metadata: "zhipuai" },
"zai-org": { provider: "zai", metadata: "zhipuai" },
} as const;
export const OpenRouterModel = z.object({
@@ -97,7 +105,8 @@ export const openrouter = {
return response.json();
},
parseModels(raw) {
return OpenRouterResponse.parse(raw).data;
// Temporarily skip batch routes (`*:batch`) — they are not catalog targets.
return OpenRouterResponse.parse(raw).data.filter((model) => !model.id.endsWith(":batch"));
},
translateModel(model, context) {
// OpenRouter serves deprecated/unavailable routes as degraded stubs:
@@ -175,9 +184,11 @@ export function buildOpenRouterModel(
const prompt = price(model.pricing.prompt);
const completion = price(model.pricing.completion);
const reasoning = params.has("reasoning") || params.has("include_reasoning");
const reasoning_options = existing?.reasoning_options?.length
? existing.reasoning_options
: openRouterReasoningOptions(model.reasoning) ?? existing?.reasoning_options;
// Prefer OpenRouter's live reasoning metadata over authored options so aliases
// and rotated models pick up new efforts/budget support. Fall back to authored
// only when the API omits a reasoning object.
const reasoning_options = openRouterReasoningOptions(model.reasoning)
?? (reasoning ? existing?.reasoning_options : undefined);
const context = model.context_length;
const family = inferFamily(model, name);
const releaseDate = dateFromTimestamp(model.created);
@@ -211,7 +222,7 @@ export function buildOpenRouterModel(
return factorBaseModel(
canonical,
{
name: baseModel !== undefined || model.id.endsWith(":free") || canonicalOverride === canonical
name: shouldPreserveFactoredName(model.id, canonical, baseModel, canonicalOverride)
? name
: undefined,
description: existing?.description ?? describeModel({
@@ -304,19 +315,39 @@ export function resolveCanonicalBaseModel(openrouterID: string) {
if (prefix === undefined || modelParts.length === 0) return undefined;
if (openrouterID.startsWith("~/") || prefix.startsWith("~")) return undefined;
const canonical = CANONICAL_PROVIDER_PREFIXES[prefix as keyof typeof CANONICAL_PROVIDER_PREFIXES];
const canonical = CANONICAL_PROVIDER_PREFIXES[
prefix.toLowerCase() as keyof typeof CANONICAL_PROVIDER_PREFIXES
];
if (canonical === undefined) return undefined;
const modelID = modelParts.join("/").replace(/:free$/, "");
const candidates = canonicalCandidates(canonical.provider, modelID);
const match = candidates.find((candidate) => {
return modelMetadataExists(canonical.metadata, candidate);
});
const match = matchingModelMetadataFile(canonical.metadata, candidates);
return match === undefined ? undefined : `${canonical.metadata}/${match}`;
}
function modelMetadataExists(provider: string, modelID: string) {
/**
* Resolve provider IDs that are not OpenRouter-shaped against the same canonical
* metadata tree. Exact paths win; bare IDs only resolve when their filename is
* unique across every metadata provider.
*/
export function resolveModelMetadataBaseModel(modelID: string) {
const routed = resolveCanonicalBaseModel(modelID);
if (routed !== undefined) return routed;
const normalized = modelID.replace(/:free$/, "");
const ids = modelMetadataIDs();
const exact = ids.find((candidate) => candidate.toLowerCase() === normalized.toLowerCase());
if (exact !== undefined) return exact;
if (normalized.includes("/")) return undefined;
const lower = normalized.toLowerCase();
const matches = ids.filter((candidate) => candidate.split("/").at(-1)?.toLowerCase() === lower);
return matches.length === 1 ? matches[0] : undefined;
}
function matchingModelMetadataFile(provider: string, candidates: string[]) {
let files = modelMetadataFilesByProvider.get(provider);
if (files === undefined) {
try {
@@ -326,7 +357,30 @@ function modelMetadataExists(provider: string, modelID: string) {
}
modelMetadataFilesByProvider.set(provider, files);
}
return files.has(`${modelID}.toml`);
for (const candidate of candidates) {
const expected = `${candidate}.toml`.toLowerCase();
const match = [...files].find((file) => file.toLowerCase() === expected);
if (match !== undefined) return match.slice(0, -".toml".length);
}
return undefined;
}
function modelMetadataIDs() {
if (allModelMetadataIDs !== undefined) return allModelMetadataIDs;
try {
allModelMetadataIDs = readdirSync(MODELS_DIR, { withFileTypes: true })
.filter((entry) => entry.isDirectory())
.flatMap((entry) => {
return readdirSync(path.join(MODELS_DIR, entry.name))
.filter((file) => file.endsWith(".toml"))
.map((file) => `${entry.name}/${file.slice(0, -".toml".length)}`);
});
} catch {
allModelMetadataIDs = [];
}
return allModelMetadataIDs;
}
function canonicalBaseModelOverride(openrouterID: string) {
@@ -335,10 +389,36 @@ function canonicalBaseModelOverride(openrouterID: string) {
];
}
function shouldPreserveFactoredName(
modelID: string,
canonical: string,
baseModel: string | undefined,
canonicalOverride: string | undefined,
) {
if (baseModel !== undefined) return true;
if (modelID.endsWith(":free")) return true;
if (canonicalOverride === canonical) return true;
const modelSlug = modelID.split("/").slice(1).join("/").replace(/:free$/, "");
const canonicalSlug = canonical.split("/").slice(1).join("/");
return normalizeModelSlug(modelSlug) !== normalizeModelSlug(canonicalSlug);
}
function normalizeModelSlug(value: string) {
return value.toLowerCase().replaceAll(/[^a-z0-9]/g, "");
}
type BaseModelOverrides = Omit<Partial<SyncedFullModel>, "limit" | "modalities"> & {
limit?: Partial<SyncedFullModel["limit"]>;
modalities?: {
input?: SyncedFullModel["modalities"]["input"];
output?: SyncedFullModel["modalities"]["output"];
};
};
export function factorBaseModel(
modelID: string,
values: Partial<SyncedFullModel>,
limit: SyncedFullModel["limit"],
values: BaseModelOverrides,
limit?: Partial<SyncedFullModel["limit"]>,
existingOmit?: string[],
): SyncedModel {
return {
@@ -350,14 +430,16 @@ export function factorBaseModel(
function baseModelOmit(
modelID: string,
limit: SyncedFullModel["limit"],
limit: Partial<SyncedFullModel["limit"]> | undefined,
) {
if (limit === undefined) return undefined;
const metadata = modelMetadata(modelID);
const omit: string[] = [];
const baseLimit = metadata.limit;
if (
isPlainObject(baseLimit) &&
baseLimit.input !== undefined &&
limit.context !== undefined &&
limit.input === undefined &&
baseLimit.context !== limit.context
) {
@@ -369,7 +451,7 @@ function baseModelOmit(
function baseModelOverrides(
modelID: string,
values: Partial<SyncedFullModel>,
values: BaseModelOverrides,
) {
const metadata = modelMetadata(modelID);
const result: Record<string, unknown> = {};
@@ -446,10 +528,13 @@ function modelMetadata(modelID: string) {
function canonicalCandidates(provider: string, modelID: string) {
const candidates = [modelID];
if (modelID.endsWith("-fast")) candidates.push(modelID.slice(0, -"-fast".length));
if (provider === "anthropic") {
candidates.push(modelID.replace(/(claude-(?:opus|sonnet|haiku)-\d+)\.(\d+)/, "$1-$2"));
candidates.push(modelID.replace(/^claude-3\.5-/, "claude-3-5-"));
for (const candidate of [...candidates]) {
candidates.push(candidate.replace(/(claude-(?:opus|sonnet|haiku)-\d+)\.(\d+)/, "$1-$2"));
candidates.push(candidate.replace(/^claude-3\.5-/, "claude-3-5-"));
}
}
if (provider === "llama") {
+232
View File
@@ -0,0 +1,232 @@
import { z } from "zod";
import { describeModel } from "../../describe.js";
import type { ExistingModel, SyncProvider, SyncedFullModel, SyncedModel } from "../index.js";
import { factorBaseModel } from "./openrouter.js";
const API_ENDPOINT = "https://api.pioneer.ai/v1/models";
const BaseModels: Record<string, string> = {
"Qwen/Qwen3.5-9B": "alibaba/qwen3.5-9b",
"google/gemma-4-E2B-it": "google/gemma-4-E2B-it",
"google/gemma-4-E4B-it": "google/gemma-4-E4B-it",
"mistral-medium-3.5": "mistral/mistral-medium-2604",
"moonshotai/Kimi-K2.7-Code": "moonshotai/kimi-k2.7-code",
"openai/gpt-oss-120b": "openai/gpt-oss-120b",
"openai/gpt-oss-20b": "openai/gpt-oss-20b",
"sakana/fugu-ultra": "sakana/fugu-ultra",
"zai-org/GLM-5.2": "zhipuai/glm-5.2",
};
const Capability = z
.object({
supported: z.boolean(),
})
.passthrough();
const ReasoningEffortValues = [
"none",
"minimal",
"low",
"medium",
"high",
"xhigh",
"max",
"default",
] as const;
type ReasoningEffort = typeof ReasoningEffortValues[number];
const ReasoningEfforts = new Set<string>(ReasoningEffortValues);
const PioneerReasoningLevel = z
.object({
effort: z.string(),
description: z.string().optional(),
})
.passthrough();
const PioneerMetadataModel = z
.object({
slug: z.string(),
default_reasoning_level: z.string().nullish(),
supported_reasoning_levels: z.array(PioneerReasoningLevel).nullish(),
})
.passthrough();
const PioneerServedModel = z
.object({
id: z.string(),
display_name: z.string(),
created: z.number().optional(),
created_at: z.string().optional(),
max_input_tokens: z.number().int().nonnegative(),
max_tokens: z.number().int().nonnegative(),
deprecated: z.boolean().optional(),
capabilities: z
.object({
image_input: Capability.optional(),
pdf_input: Capability.optional(),
structured_outputs: Capability.optional(),
thinking: Capability.optional(),
})
.passthrough(),
})
.passthrough();
export const PioneerModel = PioneerServedModel.extend({
metadata: PioneerMetadataModel.optional(),
});
export const PioneerResponse = z
.object({
data: z.array(PioneerServedModel),
models: z.array(PioneerMetadataModel).optional().default([]),
})
.passthrough();
export type PioneerModel = z.infer<typeof PioneerModel>;
export const pioneer = {
id: "pioneer",
name: "Pioneer",
modelsDir: "providers/pioneer/models",
skipCreates: true,
// Pioneer reports 2024-01-01 for every model, so its creation dates cannot
// support a meaningful age cutoff for remote-only model notifications.
trackMissingModels: false,
deleteMissing: false,
async fetchModels() {
const response = await fetch(API_ENDPOINT);
if (!response.ok) {
throw new Error(`Pioneer request failed: ${response.status} ${response.statusText}`);
}
return response.json();
},
parseModels(raw) {
const parsed = PioneerResponse.parse(raw);
const metadata = new Map(parsed.models.map((model) => [model.slug, model]));
return parsed.data.map((model) => ({
...model,
metadata: metadata.get(model.id),
}));
},
translateModel(model, context) {
return {
id: model.id,
model: buildPioneerModel(model, context.existing(model.id)),
};
},
missingNotice(paths) {
if (paths.length === 0) return [];
return [
`${paths.length} local model(s) are not present in Pioneer /v1/models and were retained: ${paths.join(", ")}`,
];
},
skippedNotice(ids) {
if (ids.length === 0) return [];
return [
`${ids.length} remote model(s) are present in Pioneer /v1/models but were not created because Pioneer sync is update-only for new models: ${ids.join(", ")}`,
];
},
} satisfies SyncProvider<PioneerModel>;
function dateFromModel(model: PioneerModel) {
if (model.created !== undefined) return new Date(model.created * 1000).toISOString().slice(0, 10);
if (model.created_at !== undefined) return model.created_at.slice(0, 10);
return "2024-01-01";
}
function supported(model: PioneerModel, capability: keyof PioneerModel["capabilities"]) {
return model.capabilities[capability]?.supported === true;
}
function isReasoningEffort(value: string): value is ReasoningEffort {
return ReasoningEfforts.has(value);
}
function pioneerReasoningOptions(model: PioneerModel): SyncedFullModel["reasoning_options"] {
const levels = model.metadata?.supported_reasoning_levels ?? [];
if (levels.length === 0) return undefined;
const unsupported = levels
.map((level) => level.effort)
.filter((effort) => !isReasoningEffort(effort));
if (unsupported.length > 0) {
throw new Error(
`Unsupported Pioneer reasoning effort(s) for ${model.id}: ${[...new Set(unsupported)].join(", ")}`,
);
}
const values = [...new Set(levels.map((level) => level.effort).filter(isReasoningEffort))];
return values.length > 0 ? [{ type: "effort", values }] : undefined;
}
function buildPioneerModel(
model: PioneerModel,
existing: ExistingModel | undefined,
): SyncedModel {
const status = model.deprecated === true ? "deprecated" : existing?.status;
const baseModel = existing?.base_model ?? BaseModels[model.id];
const apiReasoningOptions = pioneerReasoningOptions(model);
const reasoning = apiReasoningOptions !== undefined || supported(model, "thinking") || existing?.reasoning === true;
const reasoningOptions = apiReasoningOptions ?? (reasoning ? existing?.reasoning_options : undefined);
const interleaved = reasoning ? (existing?.interleaved ?? { field: "reasoning_content" as const }) : undefined;
if (baseModel !== undefined) {
const limit = {
context: model.max_input_tokens,
input: existing?.limit?.input,
output: model.max_tokens,
};
return factorBaseModel(baseModel, {
cost: existing?.cost,
reasoning: apiReasoningOptions !== undefined ? true : undefined,
reasoning_options: reasoningOptions,
status,
interleaved,
limit,
}, limit, existing?.base_model_omit);
}
const input = [
"text",
supported(model, "image_input") ? "image" : undefined,
supported(model, "pdf_input") ? "pdf" : undefined,
].filter((value): value is "text" | "image" | "pdf" => value !== undefined);
return {
name: existing?.name ?? model.display_name,
description: existing?.description ?? describeModel({
id: model.id,
providerId: "pioneer",
name: model.display_name,
family: existing?.family,
reasoning,
tool_call: existing?.tool_call ?? true,
structured_output: supported(model, "structured_outputs") || undefined,
open_weights: existing?.open_weights ?? false,
modalities: { input, output: ["text"] },
}),
family: existing?.family,
release_date: existing?.release_date ?? dateFromModel(model),
last_updated: existing?.last_updated ?? dateFromModel(model),
attachment: input.some((value) => value !== "text"),
reasoning,
reasoning_options: reasoningOptions,
temperature: existing?.temperature ?? true,
tool_call: existing?.tool_call ?? true,
structured_output: supported(model, "structured_outputs") || undefined,
knowledge: existing?.knowledge,
open_weights: existing?.open_weights ?? false,
status,
interleaved,
cost: existing?.cost,
limit: {
context: model.max_input_tokens,
input: existing?.limit?.input,
output: model.max_tokens,
},
modalities: { input, output: ["text"] },
};
}
+20 -8
View File
@@ -206,14 +206,26 @@ export function resolveVeniceBaseModel(id: string, name: string) {
const alias = BASE_MODEL_ALIASES[id];
if (alias !== undefined) return alias;
const entries = getMetadataEntries();
const normalizedID = normalize(id);
const normalizedName = normalize(name);
const ranked = [
entries.filter((entry) => entry.normalizedFull === normalizedID),
entries.filter((entry) => entry.normalizedFilename === normalizedID),
entries.filter((entry) => entry.normalizedFilename === normalizedName),
];
return ranked.find((matches) => matches.length === 1)?.[0]?.id;
for (const candidate of veniceBaseModelCandidates(id, name)) {
const normalized = normalize(candidate);
const ranked = [
entries.filter((entry) => entry.normalizedFull === normalized),
entries.filter((entry) => entry.normalizedFilename === normalized),
];
const match = ranked.find((matches) => matches.length === 1)?.[0]?.id;
if (match !== undefined) return match;
}
return undefined;
}
function veniceBaseModelCandidates(id: string, name: string) {
const candidates = [id, name];
for (const value of [id, name]) {
if (value.toLowerCase().endsWith("-fast")) candidates.push(value.slice(0, -"-fast".length));
const withoutFastLabel = value.replace(/\s*\(?\s*fast\s*\)?\s*$/i, "").trim();
if (withoutFastLabel !== "" && withoutFastLabel !== value) candidates.push(withoutFastLabel);
}
return [...new Set(candidates)];
}
function getMetadataEntries() {

Some files were not shown because too many files have changed in this diff Show More