diff --git a/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs b/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs index 71138df9..17ad8309 100644 --- a/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs +++ b/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs @@ -213,9 +213,14 @@ public sealed class ProviderAnthropic() : BaseProvider(LLMProviders.ANTHROPIC, n var result = await this.LoadModels(SecretStoreType.LLM_PROVIDER, apiKeyProvisional, token); return result with { + // // The API is the authority: when it reports a model we also keep as a fallback above, - // its entry comes first and the fallback is dropped. - Models = [..result.Models.Concat(additionalModels).DistinctBy(x => x.Id).OrderBy(x => x.Id)] + // its entry comes first and the fallback is dropped. What it reports is asked about + // first, though -- the route says nothing about what a model is made for, and Claude + // has not always been only something to talk to. The six above skip that question + // because they are not a catalog: every one of them was picked by hand. + // + Models = [..result.Models.Where(model => model.IsChatModel(this.Provider)).Concat(additionalModels).DistinctBy(x => x.Id).OrderBy(x => x.Id)] }; } diff --git a/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs b/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs index 0ff35fb0..98bbbc17 100644 --- a/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs +++ b/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs @@ -137,6 +137,11 @@ public sealed class ProviderOpenRouter() : BaseProvider(LLMProviders.OPEN_ROUTER /// Nothing is reported from here: this route answers with the embedding models alone, and what /// is reported replaces everything an instance said before. The windows of the chat models /// would go missing the moment somebody opens the embedding settings. + /// + /// Nothing is filtered either, for the same reason. The route is the statement: OpenRouter + /// serves these to embed with, which is more than a name can say. Asking the registry on top + /// could only drop a model whose name we do not recognize -- and where the two disagree, the + /// answer is a rule in Models/, not a model missing from this list. /// /// An API key which is not stored yet. /// The cancellation token to use. @@ -156,4 +161,4 @@ public sealed class ProviderOpenRouter() : BaseProvider(LLMProviders.OPEN_ROUTER }, token: token); } -} +} \ No newline at end of file diff --git a/app/Tests/Models/Corpus/ModelKindCorpus.cs b/app/Tests/Models/Corpus/ModelKindCorpus.cs index cdcac754..290a62fa 100644 --- a/app/Tests/Models/Corpus/ModelKindCorpus.cs +++ b/app/Tests/Models/Corpus/ModelKindCorpus.cs @@ -266,6 +266,19 @@ public static class ModelKindCorpus 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), + // // 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