Sorted every model list by what a model is made for (#984)
Build and Release / Determine run mode (push) Waiting to run
Build and Release / Read metadata (push) Blocked by required conditions
Build and Release / Sync Flatpak repo (push) Blocked by required conditions
Build and Release / Collect Flatpak artifacts (push) Blocked by required conditions
Build and Release / Verify (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions

This commit is contained in:
Thorsten Sommer authored and GitHub committed 2026-09-19 17:54:10 +02:00
1 parent e42277beba
commit f9c6075c50
36 files changed
+947 -333

No files matched your search

@@ -20,10 +20,7 @@
# what each of them must answer, but it states capabilities alone.
#
ALIBABA_CLOUD | qvq-max | ALWAYS_REASONING, CHAT_COMPLETION_API, MULTIPLE_IMAGE_INPUT, TEXT_INPUT, TEXT_OUTPUT | CHAT | (unknown) | (unknown) | (unknown)
ALIBABA_CLOUD | qwen-max-latest | CHAT_COMPLETION_API, FUNCTION_CALLING, TEXT_INPUT, TEXT_OUTPUT | CHAT | (unknown) | (unknown) | (unknown)
ALIBABA_CLOUD | qwen-mt-plus | CHAT_COMPLETION_API, FUNCTION_CALLING, TEXT_INPUT, TEXT_OUTPUT | CHAT | (unknown) | (unknown) | (unknown)
ALIBABA_CLOUD | qwen-plus-latest | CHAT_COMPLETION_API, FUNCTION_CALLING, TEXT_INPUT, TEXT_OUTPUT | CHAT | (unknown) | (unknown) | (unknown)
ALIBABA_CLOUD | qwen-turbo-latest | CHAT_COMPLETION_API, FUNCTION_CALLING, TEXT_INPUT, TEXT_OUTPUT | CHAT | (unknown) | (unknown) | (unknown)
ALIBABA_CLOUD | qwen-vl-max | CHAT_COMPLETION_API, MULTIPLE_IMAGE_INPUT, TEXT_INPUT, TEXT_OUTPUT | CHAT | (unknown) | (unknown) | (unknown)
ALIBABA_CLOUD | qwen2.5-14b-instruct-1m | CHAT_COMPLETION_API, FUNCTION_CALLING, TEXT_INPUT, TEXT_OUTPUT | CHAT | (unknown) | (unknown) | (unknown)
ALIBABA_CLOUD | qwen2.5-72b-instruct | CHAT_COMPLETION_API, FUNCTION_CALLING, TEXT_INPUT, TEXT_OUTPUT | CHAT | (unknown) | (unknown) | (unknown)
@@ -67,7 +64,7 @@ FIREWORKS | accounts/fireworks/models/qwen3-235b-a22b | CHAT_COMPLETION_API, FUN
FIREWORKS | whisper-v3 | SPEECH_INPUT, TEXT_OUTPUT | TRANSCRIPTION | (unknown) | (unknown) | (unknown)
GOOGLE | gemini-1.0-pro-vision | CHAT_COMPLETION_API, MULTIPLE_IMAGE_INPUT, TEXT_INPUT, TEXT_OUTPUT | CHAT | (unknown) | (unknown) | (unknown)
GOOGLE | gemini-2.0-flash | AUDIO_INPUT, CHAT_COMPLETION_API, FUNCTION_CALLING, MULTIPLE_IMAGE_INPUT, SPEECH_INPUT, TEXT_INPUT, TEXT_OUTPUT, VIDEO_INPUT | CHAT | (unknown) | 3600 per request | PROVIDER_API countTokens
GOOGLE | gemini-2.0-flash-live-001 | AUDIO_INPUT, CHAT_COMPLETION_API, FUNCTION_CALLING, SPEECH_INPUT, SPEECH_OUTPUT, TEXT_INPUT, TEXT_OUTPUT, VIDEO_INPUT | CHAT | (unknown) | (unknown) | (unknown)
GOOGLE | gemini-2.0-flash-live-001 | AUDIO_INPUT, CHAT_COMPLETION_API, FUNCTION_CALLING, SPEECH_INPUT, SPEECH_OUTPUT, TEXT_INPUT, TEXT_OUTPUT, VIDEO_INPUT | REALTIME | (unknown) | (unknown) | (unknown)
GOOGLE | gemini-2.5-flash | ALWAYS_REASONING, AUDIO_INPUT, CHAT_COMPLETION_API, FUNCTION_CALLING, MULTIPLE_IMAGE_INPUT, SPEECH_INPUT, TEXT_INPUT, TEXT_OUTPUT, VIDEO_INPUT | CHAT | 1048576 | 3600 per request | PROVIDER_API countTokens
GOOGLE | gemini-2.5-flash-image | CHAT_COMPLETION_API, IMAGE_OUTPUT, MULTIPLE_IMAGE_INPUT, TEXT_INPUT, TEXT_OUTPUT | IMAGE_GENERATION | (unknown) | (unknown) | (unknown)
GOOGLE | gemini-2.5-flash-lite | AUDIO_INPUT, CHAT_COMPLETION_API, FUNCTION_CALLING, MULTIPLE_IMAGE_INPUT, OPTIONAL_REASONING, SPEECH_INPUT, TEXT_INPUT, TEXT_OUTPUT, VIDEO_INPUT | CHAT | 1048576 | 3600 per request | PROVIDER_API countTokens
@@ -115,7 +112,7 @@ LITE_LLM | anthropic/claude-sonnet-5 | CHAT_COMPLETION_API, FUNCTION_CALLING, MU
LITE_LLM | azure/gpt-5.6 | CHAT_COMPLETION_API, FUNCTION_CALLING, MULTIPLE_IMAGE_INPUT, REASONING_BY_DEFAULT, TEXT_INPUT, TEXT_OUTPUT, WEB_SEARCH | CHAT | 1050000 | (unknown) | TIKTOKEN o200k_base
LITE_LLM | bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0 | CHAT_COMPLETION_API, FUNCTION_CALLING, TEXT_INPUT, TEXT_OUTPUT | CHAT | (unknown) | (unknown) | (unknown)
LITE_LLM | the-fast-one | CHAT_COMPLETION_API, FUNCTION_CALLING, TEXT_INPUT, TEXT_OUTPUT | CHAT | (unknown) | (unknown) | (unknown)
MISTRAL | codestral-2508 | CHAT_COMPLETION_API, FUNCTION_CALLING, TEXT_INPUT, TEXT_OUTPUT | CHAT | (unknown) | (unknown) | (unknown)
MISTRAL | codestral-2508 | CHAT_COMPLETION_API, FUNCTION_CALLING, TEXT_INPUT, TEXT_OUTPUT | TEXT_COMPLETION | (unknown) | (unknown) | (unknown)
MISTRAL | magistral-medium-2506 | ALWAYS_REASONING, CHAT_COMPLETION_API, FUNCTION_CALLING, MULTIPLE_IMAGE_INPUT, TEXT_INPUT, TEXT_OUTPUT | CHAT | (unknown) | (unknown) | (unknown)
MISTRAL | ministral-14b-2512 | CHAT_COMPLETION_API, FUNCTION_CALLING, MULTIPLE_IMAGE_INPUT, TEXT_INPUT, TEXT_OUTPUT | CHAT | (unknown) | (unknown) | (unknown)
MISTRAL | ministral-3b-latest | CHAT_COMPLETION_API, FUNCTION_CALLING, MULTIPLE_IMAGE_INPUT, TEXT_INPUT, TEXT_OUTPUT | CHAT | (unknown) | (unknown) | (unknown)
+2 -2
View File
@@ -17,8 +17,8 @@ public enum CorpusOrigin
NAMED_BY_A_RULE,
/// <summary>
/// The app carries this model in a built-in list, such as the one Alibaba Cloud models are
/// picked from when the provider serves no catalog.
/// The app carries this model in a built-in list, such as the aliases Anthropic answers to but
/// does not list, or the transcription model GWDG serves without naming it.
/// </summary>
BUILT_INTO_THE_APP,
+19 -14
View File
@@ -134,23 +134,28 @@ public static class ModelCorpus
];
/// <summary>
/// Alibaba Cloud. Everything below the two dozen models the app carries is one Qwen tier per
/// entry, because each tier answers differently about thinking and vision.
/// Alibaba Cloud. One Qwen tier per entry, because each tier answers differently about thinking
/// and vision.
/// </summary>
/// <remarks>
/// The app carried two dozen of these names in a list of its own until the catalog became the
/// only source. Three went with it and are not replaced: qwen-max-latest, qwen-plus-latest and
/// qwen-turbo-latest are a naming convention Alibaba has left behind -- its rolling names carry
/// no suffix now, and the tier once called turbo is called flash. The ones which stayed are
/// here for the other reason: no rule spells any of them out, so they say what becomes of a
/// name the rules were not written for.
/// </remarks>
private static readonly CorpusEntry[] ALIBABA_ENTRIES =
[
new(ALIBABA_CLOUD, "qwq-plus", BUILT_INTO_THE_APP),
new(ALIBABA_CLOUD, "qwen-max-latest", BUILT_INTO_THE_APP),
new(ALIBABA_CLOUD, "qwen-plus-latest", BUILT_INTO_THE_APP),
new(ALIBABA_CLOUD, "qwen-turbo-latest", BUILT_INTO_THE_APP),
new(ALIBABA_CLOUD, "qvq-max", BUILT_INTO_THE_APP),
new(ALIBABA_CLOUD, "qwen-vl-max", BUILT_INTO_THE_APP),
new(ALIBABA_CLOUD, "qwen-mt-plus", BUILT_INTO_THE_APP),
new(ALIBABA_CLOUD, "qwen2.5-72b-instruct", BUILT_INTO_THE_APP),
new(ALIBABA_CLOUD, "qwen2.5-14b-instruct-1m", BUILT_INTO_THE_APP),
new(ALIBABA_CLOUD, "qwen2.5-omni-7b", BUILT_INTO_THE_APP),
new(ALIBABA_CLOUD, "qwen2.5-vl-72b-instruct", BUILT_INTO_THE_APP),
new(ALIBABA_CLOUD, "text-embedding-v3", BUILT_INTO_THE_APP),
new(ALIBABA_CLOUD, "qwq-plus", NAMED_BY_NO_RULE),
new(ALIBABA_CLOUD, "qvq-max", NAMED_BY_NO_RULE),
new(ALIBABA_CLOUD, "qwen-vl-max", NAMED_BY_NO_RULE),
new(ALIBABA_CLOUD, "qwen-mt-plus", NAMED_BY_NO_RULE),
new(ALIBABA_CLOUD, "qwen2.5-72b-instruct", NAMED_BY_NO_RULE),
new(ALIBABA_CLOUD, "qwen2.5-14b-instruct-1m", NAMED_BY_NO_RULE),
new(ALIBABA_CLOUD, "qwen2.5-omni-7b", NAMED_BY_NO_RULE),
new(ALIBABA_CLOUD, "qwen2.5-vl-72b-instruct", NAMED_BY_NO_RULE),
new(ALIBABA_CLOUD, "text-embedding-v3", NAMED_BY_NO_RULE),
new(ALIBABA_CLOUD, "qwen3-omni-flash", NAMED_BY_A_RULE),
new(ALIBABA_CLOUD, "qwen3-vl-plus", NAMED_BY_A_RULE),
new(ALIBABA_CLOUD, "qwen3-235b-a22b", NAMED_BY_A_RULE),
+214 -1
View File
@@ -33,6 +33,39 @@ public static class ModelKindCorpus
// The one name whose only marker used to be the organization it was published under:
new(SELF_HOSTED, "sentence-transformers/all-MiniLM-L6-v2", EMBEDDING),
// Mistral's embedding checkpoint for code. It carries the name of a family which is a text
// completion model on this very provider, and stays an embedding model regardless: what a
// model is for is said by the word which says it, not by the family it was built from.
new(MISTRAL, "codestral-embed", EMBEDDING),
// Alibaba names its own by the prefix the provider used to filter the catalog by. The rule
// says it now, so the prefix is free to go:
new(ALIBABA_CLOUD, "text-embedding-v3", EMBEDDING),
new(ALIBABA_CLOUD, "text-embedding-v4", EMBEDDING),
//
// What a local Ollama installation serves, taken off its models endpoint rather than
// written from memory. The last two are the ones worth having: neither name carries the
// word "embed", so both were lost by the phrase the self-hosted provider used to filter
// with, and turned up among the chat models instead. Here they are answered by "bge" and
// "minilm", which is what those words are written for.
//
new(SELF_HOSTED, "qwen3-embedding:0.6b", EMBEDDING),
new(SELF_HOSTED, "qwen3-embedding:latest", EMBEDDING),
new(SELF_HOSTED, "nomic-embed-text:latest", EMBEDDING),
new(SELF_HOSTED, "bge-m3:latest", EMBEDDING),
new(SELF_HOSTED, "all-minilm:latest", EMBEDDING),
//
// The four whose names say nothing about embedding at all. They are here because the list
// above answers them through a word they happen to carry, and these carry none: without a
// rule of their own they would count as chat models, which is where they stood.
//
new(SELF_HOSTED, "stella_en_400M_v5", EMBEDDING),
new(SELF_HOSTED, "LaBSE", EMBEDDING),
new(SELF_HOSTED, "instructor-xl", EMBEDDING),
new(SELF_HOSTED, "gtr-t5-large", EMBEDDING),
];
/// <summary>
@@ -57,6 +90,12 @@ public static class ModelKindCorpus
new(GOOGLE, "gemini-3-pro-image", IMAGE_GENERATION),
new(GOOGLE, "imagen-4.0-generate-001", IMAGE_GENERATION, AnsweredTodayAs: CHAT, Reason: "The markers never knew the name; the family ported in the Google step states it. Nobody noticed because the Google provider shows only names beginning with gemini."),
new(ALIBABA_CLOUD, "qwen-image-edit", IMAGE_GENERATION),
// Google ships one image model under a codename instead of a description. Nothing in it
// says drawing, and the provider only ever saw it because its catalog was read whole.
new(GOOGLE, "nano-banana-pro-preview", IMAGE_GENERATION),
];
/// <summary>
@@ -82,6 +121,29 @@ public static class ModelKindCorpus
new(SELF_HOSTED, "parakeet-tdt-0.6b-v2", TRANSCRIPTION),
new(SELF_HOSTED, "wav2vec2-large-xlsr-53", TRANSCRIPTION),
new(MISTRAL, "voxtral-mini-latest", TRANSCRIPTION),
// The rest of what Mistral actually serves, off its own catalog. The app offered the one
// name above alone, because that is the one the documentation names; these three were there
// the whole time. Both sizes come as a rolling name and as a dated snapshot.
new(MISTRAL, "voxtral-small-latest", TRANSCRIPTION),
new(MISTRAL, "voxtral-mini-2602", TRANSCRIPTION),
new(MISTRAL, "voxtral-small-2507", TRANSCRIPTION),
// NVIDIA's other speech line, once plain and once as the hub names it. The second one is
// what makes the rule a segment worth keeping: the organization comes off before any rule
// sees the name, so what is left has to carry the word on its own.
new(SELF_HOSTED, "canary-1b-flash", TRANSCRIPTION),
new(SELF_HOSTED, "nvidia/canary-180m-flash", TRANSCRIPTION),
//
// Alibaba's speech line. Every one of these begins with the letter the Alibaba Cloud
// provider kept its whole chat list by, so all of them stood among the models somebody
// talks to. The last one carries two words at once, and the one which decides is not the
// longer one.
//
new(ALIBABA_CLOUD, "qwen3-asr-flash", TRANSCRIPTION),
new(ALIBABA_CLOUD, "qwen3-asr-1.7b", TRANSCRIPTION),
new(ALIBABA_CLOUD, "qwen-audio-3.0-asr-flash-streaming", TRANSCRIPTION),
];
/// <summary>
@@ -97,6 +159,13 @@ public static class ModelKindCorpus
// The one name which glues the word to something else, and the reason the three words are
// not loosened into substrings:
new(SELF_HOSTED, "xtts-v2", SPEECH_SYNTHESIS),
new(ALIBABA_CLOUD, "qwen-tts", SPEECH_SYNTHESIS),
// The Voxtral which speaks instead of listening. It stands here to hold the other half of
// Mistral's transcription list: the catalog is asked now, so what is not a transcription
// model has to be kept out by what it is, not by the list having been short.
new(MISTRAL, "voxtral-mini-tts-latest", SPEECH_SYNTHESIS),
];
/// <summary>
@@ -111,6 +180,75 @@ public static class ModelKindCorpus
new(OPEN_AI, "gpt-realtime-whisper", REALTIME),
new(OPEN_AI, "gpt-live-1", REALTIME, AnsweredTodayAs: CHAT, Reason: "Found in the chat list while testing. The line which succeeds the realtime models dropped the word, and it is even less of a chat partner: it listens and speaks at once and leaves the thinking to a text model behind it."),
//
// Alibaba builds the word into both of its speech lines, and both are here to hold the
// rank the realtime rule carries: a connection AI Studio cannot open stays out of every
// list, whether the model would otherwise have spoken or listened.
//
new(ALIBABA_CLOUD, "qwen-tts-realtime", REALTIME),
new(ALIBABA_CLOUD, "qwen3-asr-flash-realtime", REALTIME),
// The other two of Mistral's Voxtral line. The second one carries "transcribe" and stays
// out of the transcription list all the same: whatever it does, it does over a connection
// the app cannot open, and that is what the rank on the realtime rule is for.
new(MISTRAL, "voxtral-mini-realtime-latest", REALTIME),
new(MISTRAL, "voxtral-mini-transcribe-realtime-2602", REALTIME),
//
// Google's whole two-way line, taken off its catalog rather than written from memory. It
// uses the other word for the thing OpenAI calls realtime, so none of these was recognized
// and all four stood among the models to talk to -- which none of them can be. The last
// one translates between two people speaking, which is as far from a chat as it gets.
//
new(GOOGLE, "gemini-3.8-live", REALTIME),
new(GOOGLE, "gemini-3.8-live-extended-thinking", REALTIME),
new(GOOGLE, "gemini-3.1-flash-live-preview", REALTIME),
new(GOOGLE, "gemini-3.5-live-translate-preview", REALTIME),
// Google's experimental music model, which is recognized already: it carries the other
// word, and this holds that the two rules do not fall out with each other.
new(GOOGLE, "lyria-realtime-exp", REALTIME),
];
/// <summary>
/// The models which write music.
/// </summary>
/// <remarks>
/// All four off Google's own catalog. They were never seen because the provider showed only
/// names beginning with "gemini" -- the same prefix which kept Gemma out, which is why it had
/// to go and why these needed a rule of their own before it could.
/// </remarks>
private static readonly ModelKindExample[] MUSIC_ENTRIES =
[
new(GOOGLE, "lyria-3.5", MUSIC_GENERATION),
new(GOOGLE, "lyria-3-pro-preview", MUSIC_GENERATION),
new(GOOGLE, "lyria-3-clip-preview", MUSIC_GENERATION),
];
/// <summary>
/// The models which are handed a job instead of a message.
/// </summary>
/// <remarks>
/// The last two are the point of binding these rules to Google. Perplexity sells deep research
/// as well, and what it sells is a chat model -- so the same two words have to mean different
/// things at different providers, which is exactly what a binding is for.
/// </remarks>
private static readonly ModelKindExample[] AGENT_ENTRIES =
[
new(GOOGLE, "deep-research-preview-04-2026", AGENT),
new(GOOGLE, "deep-research-max-preview-04-2026", AGENT),
new(GOOGLE, "deep-research-pro-preview-12-2025", AGENT),
new(GOOGLE, "antigravity-preview-05-2026", AGENT),
new(GOOGLE, "antigravity-preview-09-2026", AGENT),
];
/// <summary>
/// The model which answers out of what it was handed, and says where the answer came from.
/// </summary>
private static readonly ModelKindExample[] GROUNDED_ANSWERING_ENTRIES =
[
new(GOOGLE, "aqa", GROUNDED_ANSWERING),
];
/// <summary>
@@ -122,13 +260,23 @@ public static class ModelKindCorpus
];
/// <summary>
/// The models from before chat completions existed.
/// The models which continue a text instead of answering in a conversation.
/// </summary>
private static readonly ModelKindExample[] TEXT_COMPLETION_ENTRIES =
[
new(HELMHOLTZ, "text-davinci-003", TEXT_COMPLETION),
// The model Mistral serves for filling a gap in a file. Its name does not begin with the
// word the provider used to sort its list by, so it stood among the chat models -- next to
// Codestral, which does the same job and was kept out by that very word.
new(MISTRAL, "mistral-code-fim-latest", TEXT_COMPLETION),
new(OPEN_AI, "babbage-002", TEXT_COMPLETION),
new(OPEN_AI, "gpt-3.5-turbo-instruct", TEXT_COMPLETION),
// The one of these which is not old: Mistral serves Codestral to fill in the middle of a
// file. It says so only for Mistral's own catalog, which is why the open weights of the
// same name stay a chat model further down.
new(MISTRAL, "codestral-latest", TEXT_COMPLETION),
];
/// <summary>
@@ -137,6 +285,7 @@ public static class ModelKindCorpus
private static readonly ModelKindExample[] OCR_ENTRIES =
[
new(MISTRAL, "mistral-ocr-latest", OCR),
new(ALIBABA_CLOUD, "qwen-vl-ocr", OCR),
];
/// <summary>
@@ -173,6 +322,67 @@ public static class ModelKindCorpus
new(SELF_HOSTED, "llama3.3:70b", CHAT),
new(OPEN_AI, "gpt-5.1", CHAT),
// The open weights of the model Mistral itself serves to fill in the middle of a file.
// Whoever runs them runs them behind a chat completion API, so here the name means
// something to talk to -- which is what binding that other rule to Mistral protects.
new(SELF_HOSTED, "codestral-22b-v0.1", CHAT),
// The other half of that same Ollama installation, and the pair which makes the point:
// qwen3.8 and qwen3-embedding are one family and two answers. A rule written to select
// rather than to modify would have to beat the family name to get there.
new(SELF_HOSTED, "qwen3.8:latest", CHAT),
new(SELF_HOSTED, "gpt-oss:latest", CHAT),
// Half the chat models of the world carry this word, and one of the embedding names above
// is one letter longer than it. A name part is what keeps the two apart:
new(SELF_HOSTED, "mistral-7b-instruct", CHAT),
//
// What somebody actually comes to Alibaba Cloud for, held here because the provider is
// about to stop keeping its chat list by the letter every one of these begins with. The
// last one translates rather than converses, and it does so through the chat completion
// API like the others, so this is where it belongs.
//
new(ALIBABA_CLOUD, "qwen3.8-max", CHAT),
new(ALIBABA_CLOUD, "qwq-plus", CHAT),
new(ALIBABA_CLOUD, "qvq-max", CHAT),
new(ALIBABA_CLOUD, "qwen-mt-turbo", CHAT),
//
// Perplexity's whole catalog, which the app carries as a list because there is no route to
// ask. A list somebody picked by hand is not filtered at runtime -- a filter over it could
// only ever take a model away, never find one -- so it is held here instead: a rule which
// turns one of these into something other than a chat model fails the build rather than
// quietly emptying the dropdown.
//
new(PERPLEXITY, "sonar", CHAT),
new(PERPLEXITY, "sonar-pro", CHAT),
new(PERPLEXITY, "sonar-reasoning", CHAT),
new(PERPLEXITY, "sonar-reasoning-pro", CHAT),
new(PERPLEXITY, "sonar-deep-research", CHAT),
//
// The other two deep research models of the world, and the reason Google's rule is bound
// to Google and written as a prefix. Perplexity and OpenAI both sell something under that
// name which answers over the API the app already speaks, so both stay chat models. Only
// Google's own line, whose names start with the words, is handed a job instead.
//
new(OPEN_AI, "o3-deep-research", CHAT),
new(OPEN_AI, "o4-mini-deep-research", CHAT),
//
// The counter-sample to the three rules above, taken off the same three catalogs. Every
// one of these carries a word which now means something -- code, live, image -- without
// being what that word says, and every one of them has to stay a chat model.
//
new(MISTRAL, "mistral-code-latest", CHAT),
new(MISTRAL, "mistral-vibe-cli-latest", CHAT),
new(MISTRAL, "zai-glm-latest", CHAT),
new(GOOGLE, "gemma-4-31b-it", CHAT),
new(GOOGLE, "gemini-3.8-flash", CHAT),
new(X, "grok-4.6", CHAT),
new(X, "grok-build-0.1", CHAT),
//
// Three which were questioned while testing and stay all the same. Grok Build is the coding
// model behind the xAI CLI and answers like any other Grok. The Groq compound systems are
@@ -199,6 +409,9 @@ public static class ModelKindCorpus
..TRANSCRIPTION_ENTRIES,
..SPEECH_ENTRIES,
..REALTIME_ENTRIES,
..MUSIC_ENTRIES,
..AGENT_ENTRIES,
..GROUNDED_ANSWERING_ENTRIES,
..COMPUTER_USE_ENTRIES,
..TEXT_COMPLETION_ENTRIES,
..OCR_ENTRIES,