mod builder;
mod chat;
mod config;
mod embed_cache;
mod provider_impl;
mod select;
pub mod asi;
pub mod aware;
pub mod bandit;
pub mod cascade;
pub mod coe;
pub mod reputation;
pub mod state;
pub mod thompson;
pub mod triage;
pub use aware::RouterAware;
pub use config::{AsiRouterConfig, BanditRouterConfig, CascadeRouterConfig, RouterStrategy};
pub use state::RouterState;
pub(crate) use embed_cache::BanditEmbedCache;
use std::sync::Arc;
use std::sync::atomic::AtomicU64;
use parking_lot::Mutex;
use asi::AsiState;
use bandit::BanditState;
use cascade::CascadeState;
use coe::CoeRouter;
use reputation::ReputationTracker;
use thompson::ThompsonState;
use crate::ema::EmaTracker;
use crate::provider::StatusTx;
static ASI_WARN_LAST_SECS: AtomicU64 = AtomicU64::new(0);
const MAX_ASI_TASKS: usize = 8;
fn blocking_load<T>(f: impl FnOnce() -> T) -> T {
if tokio::runtime::Handle::try_current()
.is_ok_and(|h| h.runtime_flavor() == tokio::runtime::RuntimeFlavor::MultiThread)
{
tokio::task::block_in_place(f)
} else {
f()
}
}
pub(crate) fn messages_contain_image(messages: &[crate::provider::Message]) -> bool {
messages.iter().any(|m| {
m.parts
.iter()
.any(|p| matches!(p, crate::provider::MessagePart::Image(_)))
})
}
pub(crate) fn strip_image_parts(
messages: &[crate::provider::Message],
) -> Vec<crate::provider::Message> {
messages
.iter()
.cloned()
.map(|mut m| {
m.parts = crate::provider::MessagePart::strip_images(&m.parts);
m
})
.collect()
}
#[derive(Debug, Clone)]
pub struct RouterProvider {
pub(crate) state: RouterState,
status_tx: Option<StatusTx>,
ema: Option<EmaTracker>,
strategy: RouterStrategy,
thompson: Option<Arc<Mutex<ThompsonState>>>,
thompson_state_path: Option<std::path::PathBuf>,
cascade_state: Option<Arc<Mutex<CascadeState>>>,
cascade_config: Option<CascadeRouterConfig>,
reputation: Option<Arc<Mutex<ReputationTracker>>>,
reputation_state_path: Option<std::path::PathBuf>,
reputation_weight: f64,
bandit: Option<Arc<Mutex<BanditState>>>,
bandit_state_path: Option<std::path::PathBuf>,
bandit_config: Option<BanditRouterConfig>,
bandit_embedding_provider: Option<Arc<dyn crate::provider_dyn::LlmProviderDyn>>,
bandit_embed_cache: Arc<Mutex<BanditEmbedCache>>,
asi: Option<Arc<Mutex<AsiState>>>,
asi_config: Option<AsiRouterConfig>,
quality_gate: Option<f32>,
coe: Option<Arc<CoeRouter>>,
embed_timeout_ms: u64,
asi_tasks: Arc<Mutex<tokio::task::JoinSet<()>>>,
}
#[cfg(test)]
mod tests;