fix(llm): resolve catalog capabilities for reasoning-mode queries
Nightly Build / build (push) Successful in 7m53s

reasoning_mode_for (the add/edit form's reasoning-knob endpoint) evaluated
rules against an empty capability set, so a declared provider whose modes
are capability-gated never offered the knob; only id-glob rules (deepseek,
openai, anthropic) could match. It now resolves the model's capabilities
from the provider catalog first.

DeclaredProvider also gains llm_model_info (find in the listing) — until
now only anthropic/ollama overrode it, which is why a declared model's
context_length never refreshed from the catalog either (maybe_refresh_meta
always got None).

And DeepInfra's entry learns a second mode: models tagged 'reasoning' but
not 'reasoning_effort' (R1, DeepSeek-V4-Flash/Pro) accept the plain effort
levels per DeepInfra's docs — graded steps stay behind the
reasoning_effort tag.
This commit is contained in:
2026-08-07 15:30:45 +01:00
parent ea31fad188
commit 6b827e1b88
3 changed files with 24 additions and 3 deletions
+7 -1
View File
@@ -356,7 +356,13 @@ impl LlmManager {
pub async fn reasoning_mode_for(&self, provider_id: i64, model_id: &str) -> Option<ReasoningMode> {
let record = self.state.read().await.providers.get(&provider_id).cloned()?;
let provider = self.registry.get(&record.provider)?;
provider.reasoning_mode(model_id, &[])
// Capability-gated modes need the model's real capabilities: resolve
// them from the provider's catalog. Empty when unlisted — id-glob
// rules still match.
let caps = self.fetch_model_info(provider_id, model_id).await
.map(|m| m.capabilities)
.unwrap_or_default();
provider.reasoning_mode(model_id, &caps)
}
pub async fn list_models_info(&self) -> Vec<LlmModelInfo> {
@@ -588,6 +588,17 @@ impl ApiProvider for DeclaredProvider {
Ok(Some(self.list_models(record).await?))
}
async fn llm_model_info(
&self,
record: &LlmProviderRecord,
model_id: &str,
) -> Result<Option<RemoteLlmModelInfo>> {
if self.spec.models.is_none() {
return Ok(None);
}
Ok(self.list_models(record).await?.into_iter().find(|m| m.id == model_id))
}
fn reasoning_mode(&self, model_id: &str, capabilities: &[String]) -> Option<ReasoningMode> {
let spec = self.spec.reasoning.as_ref()?;
let rule = spec