use serde::Serialize;
use super::*;
#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
pub struct ResolvedModel {
pub id: String,
pub provider: String,
pub alias: Option<String>,
pub tool_format: String,
pub tier: String,
pub family: String,
pub lineage: String,
}
pub fn resolve_model(alias: &str) -> (String, Option<String>) {
let config = effective_config();
if let Some(a) = config.aliases.get(alias) {
return (a.id.clone(), Some(a.provider.clone()));
}
(normalize_model_id(alias), None)
}
pub fn normalize_model_id(raw: &str) -> String {
for prefix in PROVIDER_SELECTOR_PREFIXES {
if let Some(stripped) = raw.strip_prefix(prefix) {
return stripped.to_string();
}
}
raw.to_string()
}
const PROVIDER_SELECTOR_PREFIXES: &[&str] =
&["ollama:", "local:", "huggingface:", "hf:", "cerebras/"];
pub fn resolve_model_info(selector: &str) -> ResolvedModel {
let config = effective_config();
if let Some(alias) = config.aliases.get(selector) {
let id = alias.id.clone();
let provider = alias.provider.clone();
let requested = alias
.tool_format
.clone()
.unwrap_or_else(|| default_tool_format_with_config(&config, &id, &provider));
let tool_format = guard_tool_format(&provider, &id, &requested, Some(selector));
return ResolvedModel {
tier: model_tier_with_config(&config, &id),
family: model_family_with_config(&config, &provider, &id),
lineage: model_lineage_with_config(&config, &provider, &id),
id,
provider,
alias: Some(selector.to_string()),
tool_format,
};
}
let id = normalize_model_id(selector);
let inference = infer_provider_with_config(&config, selector);
let source = inference.source;
let provider = inference.provider;
let requested = default_tool_format_with_config(&config, &id, &provider);
let tool_format = guard_tool_format(&provider, &id, &requested, None);
let tier = model_tier_with_config(&config, &id);
let family = model_family_with_inference_source(&config, &provider, &id, source);
let lineage = model_lineage_with_inference_source(&config, &provider, &id, source);
ResolvedModel {
id,
provider,
alias: None,
tool_format,
tier,
family,
lineage,
}
}
fn guard_tool_format(provider: &str, model: &str, requested: &str, alias: Option<&str>) -> String {
let decision = crate::llm::capabilities::validate_tool_format(provider, model, requested);
if let Some(reason) = &decision.correction {
tracing::warn!(
target: "harn::llm::tool_format",
alias = alias.unwrap_or(""),
"{reason}"
);
}
decision.effective
}