State the context window where a vendor documents one

This commit is contained in:
Thorsten Sommer committed 2026-09-12 15:53:03 +02:00
1 parent 6d80e6de8a
commit e8ec2c1bef
20 files changed
+562 -314

No files matched your search

@@ -26,7 +26,7 @@ public sealed class ModelStudioQwenFamily : ModelFamily
public override ModelVendor Vendor => ModelVendor.ALIBABA;
/// <inheritdoc />
public override ModelSource Source => new("https://www.alibabacloud.com/help/en/model-studio/models", new DateOnly(2026, 9, 11), "Ported unchanged from the rules in ProviderExtensions.Alibaba.cs, which follow Alibaba's own list of models that call functions.");
public override ModelSource Source => new("https://www.alibabacloud.com/help/en/model-studio/models", new DateOnly(2026, 9, 12), "Capabilities ported unchanged from ProviderExtensions.Alibaba.cs, which follow Alibaba's own list of models that call functions. Alibaba's announcement of Qwen3.8-Max states a window of up to one million tokens; the other Qwen models are served at sizes their list does not state per model.");
/// <inheritdoc />
protected override void Declare(ModelFamilyBuilder builder)
@@ -77,6 +77,7 @@ public sealed class ModelStudioQwenFamily : ModelFamily
// it is reached through Model Studio:
//
builder.Rule("qwen3.8-max").AsPrefix().OnlyOn(LLMProviders.ALIBABA_CLOUD).InheritsFrom("qwen3.8-flash")
.Reasoning(ReasoningSupport.ALWAYS);
.Reasoning(ReasoningSupport.ALWAYS)
.ContextWindow(1_000_000);
}
}
@@ -21,14 +21,21 @@ public sealed class ClaudeFamily : ModelFamily
public override ModelVendor Vendor => ModelVendor.ANTHROPIC;
/// <inheritdoc />
public override ModelSource Source => new("https://docs.anthropic.com/en/docs/about-claude/models", new DateOnly(2026, 9, 11), "Ported unchanged from the rules in ProviderExtensions.Anthropic.cs: one shape for all of Claude, and one sentence per generation about how it thinks.");
public override ModelSource Source => new("https://platform.claude.com/docs/en/build-with-claude/context-windows", new DateOnly(2026, 9, 12), "Capabilities ported unchanged from ProviderExtensions.Anthropic.cs: one shape for all of Claude, and one sentence per generation about how it thinks. The context window page names the models with a 1M window and says every other Claude has 200k.");
/// <inheritdoc />
protected override void Declare(ModelFamilyBuilder builder)
{
//
// 200k is the window of every Claude which is not named on the list of the 1M ones, which is
// how Anthropic states it themselves: the page names the exceptions and says "other Claude
// models" for the rest. So the fallback carries it, and the generations which got the larger
// window say so one by one below.
//
builder.Rule("claude").AsSegment()
.Capabilities(TEXT_INPUT | MULTIPLE_IMAGE_INPUT | TEXT_OUTPUT | FUNCTION_CALLING)
.Apis(CHAT_COMPLETION_API);
.Apis(CHAT_COMPLETION_API)
.ContextWindow(200_000);
//
// The 3.x models say nothing beyond the shape above, so nothing is written for them: the
@@ -45,15 +52,27 @@ public sealed class ClaudeFamily : ModelFamily
builder.Rule("claude-sonnet-4").AsPrefix().InheritsFrom("claude-opus-4");
builder.Rule("claude-haiku-4-5").AsPrefix().InheritsFrom("claude-opus-4");
//
// Where the window grew inside the 4 line. These rules say nothing but the number: Opus 4.6
// through 4.8 and Sonnet 4.6 have the 1M window, while the 4.0, 4.1 and 4.5 models of the
// same prefixes keep the 200k they were released with.
//
builder.Rule("claude-opus-4-6").AsPrefix().InheritsFrom("claude-opus-4").ContextWindow(1_000_000);
builder.Rule("claude-opus-4-7").AsPrefix().InheritsFrom("claude-opus-4").ContextWindow(1_000_000);
builder.Rule("claude-opus-4-8").AsPrefix().InheritsFrom("claude-opus-4").ContextWindow(1_000_000);
builder.Rule("claude-sonnet-4-6").AsPrefix().InheritsFrom("claude-opus-4").ContextWindow(1_000_000);
// Opus 5 and Sonnet 5 think adaptively unless thinking is turned off:
builder.Rule("claude-opus-5").AsPrefix().InheritsFrom("claude")
.Reasoning(ReasoningSupport.ON_BY_DEFAULT);
.Reasoning(ReasoningSupport.ON_BY_DEFAULT)
.ContextWindow(1_000_000);
builder.Rule("claude-sonnet-5").AsPrefix().InheritsFrom("claude-opus-5");
// Fable 5 and Mythos 5 always think, and there is no switch for it:
builder.Rule("claude-fable-5").AsPrefix().InheritsFrom("claude")
.Reasoning(ReasoningSupport.ALWAYS);
.Reasoning(ReasoningSupport.ALWAYS)
.ContextWindow(1_000_000);
builder.Rule("claude-mythos-5").AsPrefix().InheritsFrom("claude-fable-5");
}
@@ -25,7 +25,7 @@ public sealed class DeepSeekFamily : ModelFamily
public override ModelVendor Vendor => ModelVendor.DEEP_SEEK;
/// <inheritdoc />
public override ModelSource Source => new("https://api-docs.deepseek.com/", new DateOnly(2026, 9, 11), "Ported unchanged from the rules in ProviderExtensions.DeepSeek.cs and the DeepSeek block of ProviderExtensions.OpenSource.cs.");
public override ModelSource Source => new("https://api-docs.deepseek.com/quick_start/pricing", new DateOnly(2026, 9, 12), "Capabilities ported unchanged from ProviderExtensions.DeepSeek.cs and the DeepSeek block of ProviderExtensions.OpenSource.cs. The pricing page states a 1M window for the V4 models; the older lines are served at different sizes depending on who serves them, so no window is stated for them.");
/// <inheritdoc />
protected override void Declare(ModelFamilyBuilder builder)
@@ -58,7 +58,8 @@ public sealed class DeepSeekFamily : ModelFamily
.Removes(FUNCTION_CALLING);
builder.Rule("deepseek-v4").AsPrefix().InheritsFrom("deepseek-v3")
.Reasoning(ReasoningSupport.ON_BY_DEFAULT);
.Reasoning(ReasoningSupport.ON_BY_DEFAULT)
.ContextWindow(1_000_000);
builder.Rule("deepseek-v4").AsPrefix().AlsoContains("vision").Inherits()
.Capabilities(MULTIPLE_IMAGE_INPUT);
@@ -24,7 +24,7 @@ public sealed class GeminiFamily : ModelFamily
public override ModelVendor Vendor => ModelVendor.GOOGLE;
/// <inheritdoc />
public override ModelSource Source => new("https://ai.google.dev/gemini-api/docs/models", new DateOnly(2026, 9, 11), "Ported unchanged from the rules in ProviderExtensions.Google.cs: one shape for all of Gemini, one sentence per generation about thinking.");
public override ModelSource Source => new("https://ai.google.dev/gemini-api/docs/gemini-3", new DateOnly(2026, 9, 12), "Capabilities ported unchanged from ProviderExtensions.Google.cs: one shape for all of Gemini, one sentence per generation about thinking. The Gemini 3 guide states a one million token input window; the 2.5 model pages state their input limit as 1,048,576, and both numbers are written here as their page gives them.");
/// <inheritdoc />
protected override void Declare(ModelFamilyBuilder builder)
@@ -46,18 +46,25 @@ public sealed class GeminiFamily : ModelFamily
.Capabilities(TEXT_INPUT | AUDIO_INPUT | SPEECH_INPUT | VIDEO_INPUT | TEXT_OUTPUT | SPEECH_OUTPUT | FUNCTION_CALLING)
.Apis(CHAT_COMPLETION_API);
//
// Google states an input limit and an output limit rather than one window. The input limit
// is the one a conversation is measured against, because that is where the conversation
// accumulates, so that is the number written here.
//
builder.Rule("gemini-2.5").AsPrefix().InheritsFrom("gemini")
.Reasoning(ReasoningSupport.ALWAYS);
.Reasoning(ReasoningSupport.ALWAYS)
.ContextWindow(1_048_576);
//
// The one exception of the 2.5 line: it can think, but only when asked. From the 3.x line
// on, even the Flash Lite models think at their lowest level.
//
builder.Rule("gemini-2.5-flash-lite").AsPrefix().InheritsFrom("gemini")
builder.Rule("gemini-2.5-flash-lite").AsPrefix().InheritsFrom("gemini-2.5")
.Reasoning(ReasoningSupport.OPTIONAL);
builder.Rule("gemini-3").AsPrefix().InheritsFrom("gemini")
.Reasoning(ReasoningSupport.ALWAYS);
.Reasoning(ReasoningSupport.ALWAYS)
.ContextWindow(1_000_000);
builder.Rule("gemini-3.1").AsPrefix().InheritsFrom("gemini-3");
builder.Rule("gemini-3.7").AsPrefix().InheritsFrom("gemini-3");
@@ -21,7 +21,7 @@ public sealed class LlamaFamily : ModelFamily
public override ModelVendor Vendor => ModelVendor.META;
/// <inheritdoc />
public override ModelSource Source => new("https://www.llama.com/docs/model-cards-and-prompt-formats/", new DateOnly(2026, 9, 11), "Ported unchanged from the Llama block of ProviderExtensions.OpenSource.cs.");
public override ModelSource Source => new("https://www.llama.com/docs/model-cards-and-prompt-formats/", new DateOnly(2026, 9, 12), "Capabilities ported unchanged from the Llama block of ProviderExtensions.OpenSource.cs. The model cards give the 3.x generations a 128k window; the 4 line is not stated here, because Scout and Maverick differ by an order of magnitude and the name alone does not say which one it is.");
/// <inheritdoc />
protected override void Declare(ModelFamilyBuilder builder)
@@ -41,10 +41,16 @@ public sealed class LlamaFamily : ModelFamily
.Capabilities(TEXT_INPUT | MULTIPLE_IMAGE_INPUT | TEXT_OUTPUT)
.Apis(CHAT_COMPLETION_API);
// From 3.1 on, Llama calls functions. Three spellings, one statement:
//
// From 3.1 on, Llama calls functions and reads 128k tokens. Three spellings, one statement.
// What an operator actually serves is another matter: Ollama ships with a far smaller window
// until somebody raises num_ctx, which is why the window of a self-hosted model is a ceiling
// rather than a promise.
//
builder.Rule("llama3.").AsSubstring().NotContains("vision")
.Capabilities(TEXT_INPUT | TEXT_OUTPUT | FUNCTION_CALLING)
.Apis(CHAT_COMPLETION_API);
.Apis(CHAT_COMPLETION_API)
.ContextWindow(131_072);
builder.Rule("llama-3.").AsSubstring().NotContains("vision").Inherits();
@@ -8,7 +8,7 @@ namespace AIStudio.Models.Mistral;
public sealed class MistralLargeFamily : MistralReleaseDatedFamily
{
/// <inheritdoc />
public override ModelSource Source => new("https://docs.mistral.ai/getting-started/models/models_overview/", new DateOnly(2026, 9, 11), "Ported unchanged from the rules in ProviderExtensions.Mistral.cs: images and reasoning from Mistral Large 3 on.");
public override ModelSource Source => new("https://docs.mistral.ai/models/mistral-large-3-25-12", new DateOnly(2026, 9, 12), "Capabilities ported unchanged from ProviderExtensions.Mistral.cs: images and reasoning from Mistral Large 3 on. The model card states a 256k window.");
/// <inheritdoc />
protected override int VisionSince => 2512;
@@ -23,5 +23,6 @@ public sealed class MistralLargeFamily : MistralReleaseDatedFamily
protected override void Declare(ModelFamilyBuilder builder) =>
builder.Rule("mistral-large").AsSegment()
.Capabilities(WHAT_THEY_COULD_ALWAYS_DO)
.Apis(CHAT_COMPLETION_API);
.Apis(CHAT_COMPLETION_API)
.ContextWindow(256_000);
}
@@ -8,7 +8,7 @@ namespace AIStudio.Models.Mistral;
public sealed class MistralMediumFamily : MistralReleaseDatedFamily
{
/// <inheritdoc />
public override ModelSource Source => new("https://docs.mistral.ai/getting-started/models/models_overview/", new DateOnly(2026, 9, 11), "Ported unchanged from the rules in ProviderExtensions.Mistral.cs: images from Mistral Medium 3 on, reasoning from Mistral Medium 3.5 on.");
public override ModelSource Source => new("https://docs.mistral.ai/models/model-cards/mistral-medium-3-5-26-04", new DateOnly(2026, 9, 12), "Capabilities ported unchanged from ProviderExtensions.Mistral.cs: images from Mistral Medium 3 on, reasoning from Mistral Medium 3.5 on. The model card states a 256k window.");
/// <inheritdoc />
protected override int VisionSince => 2505;
@@ -23,5 +23,6 @@ public sealed class MistralMediumFamily : MistralReleaseDatedFamily
protected override void Declare(ModelFamilyBuilder builder) =>
builder.Rule("mistral-medium").AsSegment()
.Capabilities(WHAT_THEY_COULD_ALWAYS_DO)
.Apis(CHAT_COMPLETION_API);
.Apis(CHAT_COMPLETION_API)
.ContextWindow(256_000);
}
@@ -14,11 +14,12 @@ public sealed class PixtralFamily : ModelFamily
public override ModelVendor Vendor => ModelVendor.MISTRAL_AI;
/// <inheritdoc />
public override ModelSource Source => new("https://docs.mistral.ai/getting-started/models/models_overview/", new DateOnly(2026, 9, 11), "Ported unchanged from the rules in ProviderExtensions.Mistral.cs: images in every release.");
public override ModelSource Source => new("https://docs.mistral.ai/getting-started/models/models_overview/", new DateOnly(2026, 9, 12), "Capabilities ported unchanged from ProviderExtensions.Mistral.cs: images in every release. Mistral states a 128k window for Pixtral.");
/// <inheritdoc />
protected override void Declare(ModelFamilyBuilder builder) =>
builder.Rule("pixtral").AsSegment()
.Capabilities(TEXT_INPUT | MULTIPLE_IMAGE_INPUT | TEXT_OUTPUT | FUNCTION_CALLING)
.Apis(CHAT_COMPLETION_API);
.Apis(CHAT_COMPLETION_API)
.ContextWindow(128_000);
}
@@ -186,6 +186,22 @@ public sealed class ModelRuleBuilder(string patternText, ModelRuleKind ruleKind,
return this;
}
/// <summary>
/// Takes back a context window this rule inherited, because nobody states one for this variant.
/// </summary>
/// <remarks>
/// A variant can already hand back a capability its family granted; a number has to be handed
/// back too. Without this, a generation whose window nobody documents would quietly carry the
/// number of the generation it inherits from -- and the app would then show a person that
/// number as a fact about their model.
/// </remarks>
/// <returns>The rule, to go on stating.</returns>
public ModelRuleBuilder WithoutContextWindow()
{
this.context = Models.ContextWindow.UNKNOWN;
return this;
}
/// <summary>
/// Which tokenizer counts this model's tokens.
/// </summary>
@@ -16,16 +16,18 @@ public sealed class Gpt4Family : ModelFamily
public override ModelVendor Vendor => ModelVendor.OPEN_AI;
/// <inheritdoc />
public override ModelSource Source => new("https://platform.openai.com/docs/models", new DateOnly(2026, 9, 11), "Ported unchanged from the rules in ProviderExtensions.OpenAI.cs: GPT-4 is text only, Turbo adds images and tool calling.");
public override ModelSource Source => new("https://developers.openai.com/api/docs/models/gpt-4-turbo", new DateOnly(2026, 9, 12), "Capabilities ported unchanged from ProviderExtensions.OpenAI.cs: GPT-4 is text only, Turbo adds images and tool calling. The windows are the documented 8,192 tokens of GPT-4 and the 128,000 Turbo raised it to.");
/// <inheritdoc />
protected override void Declare(ModelFamilyBuilder builder)
{
builder.Rule("gpt-4").AsPrefix()
.Capabilities(TEXT_INPUT | TEXT_OUTPUT)
.Apis(RESPONSES_API);
.Apis(RESPONSES_API)
.ContextWindow(8_192);
builder.Rule("gpt-4-turbo").AsPrefix().Inherits()
.Capabilities(MULTIPLE_IMAGE_INPUT | FUNCTION_CALLING);
.Capabilities(MULTIPLE_IMAGE_INPUT | FUNCTION_CALLING)
.ContextWindow(128_000);
}
}
@@ -18,14 +18,15 @@ public sealed class Gpt4oFamily : ModelFamily
public override ModelVendor Vendor => ModelVendor.OPEN_AI;
/// <inheritdoc />
public override ModelSource Source => new("https://platform.openai.com/docs/models/gpt-4o", new DateOnly(2026, 9, 11), "The answer the previous rules gave these models through their fallback: images, tool calling, and web search on the Responses API.");
public override ModelSource Source => new("https://developers.openai.com/api/docs/models/gpt-4o", new DateOnly(2026, 9, 12), "The answer the previous rules gave these models through their fallback: images, tool calling, and web search on the Responses API. The model page states a 128,000 token window, which the minis and the search previews share.");
/// <inheritdoc />
protected override void Declare(ModelFamilyBuilder builder)
{
builder.Rule("gpt-4o").AsPrefix()
.Capabilities(TEXT_INPUT | MULTIPLE_IMAGE_INPUT | TEXT_OUTPUT | FUNCTION_CALLING | WEB_SEARCH)
.Apis(RESPONSES_API);
.Apis(RESPONSES_API)
.ContextWindow(128_000);
//
// The search previews are the same generation and almost nothing like it: they search the
@@ -35,10 +36,12 @@ public sealed class Gpt4oFamily : ModelFamily
//
builder.Rule("gpt-4o-search-preview").AsExact()
.Capabilities(TEXT_INPUT | TEXT_OUTPUT | WEB_SEARCH)
.Apis(CHAT_COMPLETION_API);
.Apis(CHAT_COMPLETION_API)
.ContextWindow(128_000);
builder.Rule("gpt-4o-mini-search-preview").AsExact()
.Capabilities(TEXT_INPUT | TEXT_OUTPUT | WEB_SEARCH)
.Apis(CHAT_COMPLETION_API);
.Apis(CHAT_COMPLETION_API)
.ContextWindow(128_000);
}
}
@@ -24,15 +24,21 @@ public sealed class Gpt5Family : ModelFamily
public override ModelVendor Vendor => ModelVendor.OPEN_AI;
/// <inheritdoc />
public override ModelSource Source => new("https://platform.openai.com/docs/models", new DateOnly(2026, 9, 11), "Ported unchanged from the rules in ProviderExtensions.OpenAI.cs, one rule per generation, except that the chat alias no longer inherits the reasoning it is named for not having.");
public override ModelSource Source => new("https://developers.openai.com/api/docs/models", new DateOnly(2026, 9, 12), "Capabilities ported unchanged from ProviderExtensions.OpenAI.cs, one rule per generation, except that the chat alias no longer inherits the reasoning it is named for not having. Context windows read per generation from the model pages below that URL.");
/// <inheritdoc />
protected override void Declare(ModelFamilyBuilder builder)
{
//
// The window grows once in this line, between 5.3 and 5.4: everything up to 5.2 is
// documented at 400,000 tokens and everything from 5.4 on at 1,050,000. Both numbers are
// the whole window, input and output together, which is how OpenAI states them.
//
builder.Rule("gpt-5").AsPrefix()
.Capabilities(TEXT_INPUT | MULTIPLE_IMAGE_INPUT | TEXT_OUTPUT | FUNCTION_CALLING | WEB_SEARCH)
.Apis(RESPONSES_API)
.Reasoning(ReasoningSupport.ALWAYS);
.Reasoning(ReasoningSupport.ALWAYS)
.ContextWindow(400_000);
//
// The alias for the model of this generation which does not reason. The previous rules had
@@ -47,10 +53,19 @@ public sealed class Gpt5Family : ModelFamily
.Reasoning(ReasoningSupport.OPTIONAL);
builder.Rule("gpt-5.2").AsPrefix().InheritsFrom("gpt-5.1");
builder.Rule("gpt-5.3").AsPrefix().InheritsFrom("gpt-5.1");
builder.Rule("gpt-5.4").AsPrefix().InheritsFrom("gpt-5.1");
builder.Rule("gpt-5.5").AsPrefix().InheritsFrom("gpt-5.1")
//
// The one generation OpenAI documents nothing about: there is no model page for it, so the
// rule exists to keep a 5.3 answering like the rest of the line if one ever appears. What it
// must not do is carry 5.1's window as if somebody had looked it up.
//
builder.Rule("gpt-5.3").AsPrefix().InheritsFrom("gpt-5.1")
.WithoutContextWindow();
builder.Rule("gpt-5.4").AsPrefix().InheritsFrom("gpt-5.1")
.ContextWindow(1_050_000);
builder.Rule("gpt-5.5").AsPrefix().InheritsFrom("gpt-5.4")
.Reasoning(ReasoningSupport.ON_BY_DEFAULT);
builder.Rule("gpt-5.6").AsPrefix().InheritsFrom("gpt-5.5");
@@ -15,12 +15,13 @@ public sealed class Gpt6AstraFamily : ModelFamily
public override ModelVendor Vendor => ModelVendor.OPEN_AI;
/// <inheritdoc />
public override ModelSource Source => new("https://platform.openai.com/docs/models", new DateOnly(2026, 9, 11), "Ported unchanged from the rules in ProviderExtensions.OpenAI.cs: reasons on every request, both APIs.");
public override ModelSource Source => new("https://developers.openai.com/api/docs/models", new DateOnly(2026, 9, 12), "Capabilities ported unchanged from ProviderExtensions.OpenAI.cs: reasons on every request, both APIs. The models page states the window as 1.05M tokens.");
/// <inheritdoc />
protected override void Declare(ModelFamilyBuilder builder) =>
builder.Rule("gpt-6-astra").AsPrefix()
.Capabilities(TEXT_INPUT | MULTIPLE_IMAGE_INPUT | TEXT_OUTPUT | FUNCTION_CALLING | WEB_SEARCH)
.Apis(RESPONSES_API | CHAT_COMPLETION_API)
.Reasoning(ReasoningSupport.ALWAYS);
.Reasoning(ReasoningSupport.ALWAYS)
.ContextWindow(1_050_000);
}
@@ -20,11 +20,12 @@ public sealed class GptOssFamily : ModelFamily
public override ModelVendor Vendor => ModelVendor.OPEN_AI;
/// <inheritdoc />
public override ModelSource Source => new("https://huggingface.co/openai/gpt-oss-120b", new DateOnly(2026, 9, 11), "Ported unchanged from the gpt-oss check of ProviderExtensions.OpenSource.cs.");
public override ModelSource Source => new("https://huggingface.co/openai/gpt-oss-120b", new DateOnly(2026, 9, 12), "Capabilities ported unchanged from the gpt-oss check of ProviderExtensions.OpenSource.cs. The model card states a 128k token window, which both sizes share.");
/// <inheritdoc />
protected override void Declare(ModelFamilyBuilder builder) =>
builder.Rule("gpt-oss").AsSegment()
.Capabilities(TEXT_INPUT | TEXT_OUTPUT | FUNCTION_CALLING | WEB_SEARCH)
.Apis(CHAT_COMPLETION_API);
.Apis(CHAT_COMPLETION_API)
.ContextWindow(131_072);
}
@@ -20,7 +20,7 @@ public sealed class OSeriesFamily : ModelFamily
public override ModelVendor Vendor => ModelVendor.OPEN_AI;
/// <inheritdoc />
public override ModelSource Source => new("https://platform.openai.com/docs/models", new DateOnly(2026, 9, 11), "Ported unchanged from the rules in ProviderExtensions.OpenAI.cs, one rule per generation and one per mini.");
public override ModelSource Source => new("https://developers.openai.com/api/docs/models", new DateOnly(2026, 9, 12), "Capabilities ported unchanged from ProviderExtensions.OpenAI.cs, one rule per generation and one per mini. The o1 and o3 pages state 200,000 tokens; the two cut-down minis have no page of their own, so no window is stated for them.");
/// <inheritdoc />
protected override void Declare(ModelFamilyBuilder builder)
@@ -28,7 +28,8 @@ public sealed class OSeriesFamily : ModelFamily
builder.Rule("o1").AsPrefix()
.Capabilities(TEXT_INPUT | MULTIPLE_IMAGE_INPUT | TEXT_OUTPUT | FUNCTION_CALLING)
.Apis(RESPONSES_API)
.Reasoning(ReasoningSupport.ALWAYS);
.Reasoning(ReasoningSupport.ALWAYS)
.ContextWindow(200_000);
builder.Rule("o1-mini").AsPrefix()
.Capabilities(TEXT_INPUT | TEXT_OUTPUT)
@@ -38,7 +39,8 @@ public sealed class OSeriesFamily : ModelFamily
builder.Rule("o3").AsPrefix()
.Capabilities(TEXT_INPUT | MULTIPLE_IMAGE_INPUT | TEXT_OUTPUT | FUNCTION_CALLING | WEB_SEARCH)
.Apis(RESPONSES_API)
.Reasoning(ReasoningSupport.ALWAYS);
.Reasoning(ReasoningSupport.ALWAYS)
.ContextWindow(200_000);
builder.Rule("o3-mini").AsPrefix()
.Capabilities(TEXT_INPUT | TEXT_OUTPUT | FUNCTION_CALLING)
@@ -20,7 +20,7 @@ public sealed class GrokFamily : ModelFamily
public override ModelVendor Vendor => ModelVendor.XAI;
/// <inheritdoc />
public override ModelSource Source => new("https://docs.x.ai/docs/models", new DateOnly(2026, 9, 11), "Ported unchanged from the Grok block of ProviderExtensions.OpenSource.cs.");
public override ModelSource Source => new("https://docs.x.ai/docs/models", new DateOnly(2026, 9, 12), "Capabilities ported unchanged from the Grok block of ProviderExtensions.OpenSource.cs. The windows come from the pricing table on the same page, which states one per model.");
/// <inheritdoc />
protected override void Declare(ModelFamilyBuilder builder)
@@ -40,7 +40,8 @@ public sealed class GrokFamily : ModelFamily
//
builder.Rule("grok-build").AsPrefix()
.Capabilities(TEXT_INPUT | MULTIPLE_IMAGE_INPUT | TEXT_OUTPUT | FUNCTION_CALLING)
.Apis(CHAT_COMPLETION_API);
.Apis(CHAT_COMPLETION_API)
.ContextWindow(256_000);
builder.Rule("grok-3-mini").AsPrefix()
.Capabilities(TEXT_INPUT | TEXT_OUTPUT | FUNCTION_CALLING)
@@ -57,7 +58,17 @@ public sealed class GrokFamily : ModelFamily
.Apis(CHAT_COMPLETION_API)
.Reasoning(ReasoningSupport.ALWAYS);
builder.Rule("grok-4.20").AsPrefix().InheritsFrom("grok-4");
//
// The window is the one thing which differs across the 4 line, so each version states it:
// 4.5 and 4.6 are served at 500k, while 4.3 and the whole 4.20 line are served at 1M. Plain
// "grok-4" gets none, because xAI's table has no row for it any more.
//
builder.Rule("grok-4.3").AsPrefix().InheritsFrom("grok-4").ContextWindow(1_000_000);
builder.Rule("grok-4.5").AsPrefix().InheritsFrom("grok-4").ContextWindow(500_000);
builder.Rule("grok-4.6").AsPrefix().InheritsFrom("grok-4").ContextWindow(500_000);
builder.Rule("grok-4.20").AsPrefix().InheritsFrom("grok-4")
.ContextWindow(1_000_000);
// One member of the 4.20 line answers without thinking, and it says so in its name:
builder.Rule("grok-4.20").AsPrefix().AlsoContains("non-reasoning").Inherits()