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