use foundation_errstacks::ErrorTrace;
use crate::agentic::AgenticError;
#[cfg(all(feature = "candle", not(target_family = "wasm")))]
use crate::backends::candle::CandleArchitecture;
#[cfg(all(feature = "candle", not(target_family = "wasm")))]
use crate::backends::huggingface_candle_provider::{
HuggingFaceCandleConfig, HuggingFaceCandleProvider,
};
#[cfg(all(feature = "llamacpp", not(target_family = "wasm")))]
use crate::backends::huggingface_gguf_provider::HuggingFaceGGUFConfig;
use crate::types::ModelId;
use super::providers::{CloudPresets, CLAUDE_OPUS, CLAUDE_SONNET, OPENAI_GPT4O, OPENAI_GPT4O_MINI};
#[cfg(all(feature = "llamacpp", not(target_family = "wasm")))]
use super::providers::{gguf_provider, Gemma4E2b, Gemma4_26b, Glm52, Qwen36};
use super::router::{RouterMix, RouterPreset};
fn named(id: &str) -> ModelId {
ModelId::Name(id.to_string(), None)
}
impl RouterPreset {
#[cfg(all(feature = "llamacpp", not(target_family = "wasm")))]
pub fn hugging_face(
model: impl Into<ModelId>,
config: Option<HuggingFaceGGUFConfig>,
) -> Result<Self, ErrorTrace<AgenticError>> {
Self::hugging_face_mix((model.into(), config), None)
}
#[cfg(all(feature = "llamacpp", not(target_family = "wasm")))]
pub fn huggingface_cpu(
model: impl Into<ModelId>,
config: Option<HuggingFaceGGUFConfig>,
) -> Result<Self, ErrorTrace<AgenticError>> {
Self::hugging_face(model, Some(config.unwrap_or_default().on_cpu()))
}
#[cfg(all(feature = "llamacpp", not(target_family = "wasm")))]
pub fn huggingface_gpu(
model: impl Into<ModelId>,
config: Option<HuggingFaceGGUFConfig>,
) -> Result<Self, ErrorTrace<AgenticError>> {
Self::hugging_face(model, Some(config.unwrap_or_default().on_gpu()))
}
#[cfg(all(feature = "llamacpp", not(target_family = "wasm")))]
fn hugging_face_mix(
primary: (ModelId, Option<HuggingFaceGGUFConfig>),
memory: Option<(ModelId, Option<HuggingFaceGGUFConfig>)>,
) -> Result<Self, ErrorTrace<AgenticError>> {
let (primary_model, primary_config) = primary;
let mut mix = RouterMix::new().primary(gguf_provider(primary_config)?, primary_model);
if let Some((memory_model, memory_config)) = memory {
mix = mix.memory(gguf_provider(memory_config)?, memory_model);
}
Ok(mix.build())
}
#[cfg(all(feature = "llamacpp", not(target_family = "wasm")))]
pub fn glm52_gemma(
main: Option<HuggingFaceGGUFConfig>,
memory: Option<HuggingFaceGGUFConfig>,
) -> Result<Self, ErrorTrace<AgenticError>> {
Self::hugging_face_mix(
(named(Glm52::MODEL_ID), main),
Some((named(Gemma4E2b::MODEL_ID), memory)),
)
}
#[cfg(all(feature = "llamacpp", not(target_family = "wasm")))]
pub fn qwen36_gemma(
main: Option<HuggingFaceGGUFConfig>,
memory: Option<HuggingFaceGGUFConfig>,
) -> Result<Self, ErrorTrace<AgenticError>> {
Self::hugging_face_mix(
(named(Qwen36::MODEL_ID), main),
Some((named(Gemma4E2b::MODEL_ID), memory)),
)
}
#[cfg(all(feature = "llamacpp", not(target_family = "wasm")))]
pub fn gemma(
main: Option<HuggingFaceGGUFConfig>,
memory: Option<HuggingFaceGGUFConfig>,
) -> Result<Self, ErrorTrace<AgenticError>> {
Self::hugging_face_mix(
(named(Gemma4_26b::MODEL_ID), main),
Some((named(Gemma4E2b::MODEL_ID), memory)),
)
}
pub fn claude(api_key: &str) -> Result<Self, ErrorTrace<AgenticError>> {
let main_provider = CloudPresets::claude_opus(api_key)?;
let memory_provider = CloudPresets::claude_sonnet(api_key)?;
Ok(RouterMix::new()
.primary(main_provider, named(CLAUDE_OPUS))
.memory(memory_provider, named(CLAUDE_SONNET))
.build())
}
pub fn openai_chat(api_key: &str) -> Result<Self, ErrorTrace<AgenticError>> {
let main_provider = CloudPresets::openai_gpt4o(api_key)?;
let memory_provider = CloudPresets::openai_gpt4o(api_key)?;
Ok(RouterMix::new()
.primary(main_provider, named(OPENAI_GPT4O))
.memory(memory_provider, named(OPENAI_GPT4O_MINI))
.build())
}
pub fn openai_responses(api_key: &str) -> Result<Self, ErrorTrace<AgenticError>> {
let main_provider = CloudPresets::openai_responses(api_key)?;
let memory_provider = CloudPresets::openai_responses(api_key)?;
Ok(RouterMix::new()
.primary(main_provider, named(OPENAI_GPT4O))
.memory(memory_provider, named(OPENAI_GPT4O_MINI))
.build())
}
#[cfg(all(feature = "candle", not(target_family = "wasm")))]
pub fn candle_llama(
repo_id: &str,
config: Option<HuggingFaceCandleConfig>,
) -> Result<Self, ErrorTrace<AgenticError>> {
let config = config.unwrap_or_else(|| {
HuggingFaceCandleConfig::builder()
.architecture(CandleArchitecture::Llama)
.build()
});
let provider = HuggingFaceCandleProvider::new(config).map_err(|e| {
ErrorTrace::new(AgenticError::Provider(format!(
"failed to create Candle provider for {repo_id}: {e}"
)))
})?;
Ok(RouterMix::new().primary(provider, named(repo_id)).build())
}
}