use serde::Serialize;
use super::{provider_for_cli, AgentKind, MeteringShape, ProviderId};
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Route {
pub cli: AgentKind,
pub provider: ProviderId,
pub model: Option<String>,
}
impl Route {
pub fn for_cli(cli: AgentKind) -> Self {
let (provider, _) = provider_for_cli(cli);
Self { cli, provider, model: None }
}
pub fn with_model(mut self, model: Option<impl Into<String>>) -> Self {
self.model = model.map(Into::into);
self
}
pub fn via(mut self, provider: ProviderId) -> Self {
self.provider = provider;
self
}
pub fn metering(&self) -> MeteringShape {
let (default_provider, shape) = provider_for_cli(self.cli);
if default_provider == self.provider {
shape
} else {
MeteringShape::Unknown
}
}
pub fn id(&self) -> String {
format!(
"{}/{}/{}",
self.cli.as_str(),
self.provider.as_str(),
self.model.as_deref().unwrap_or("-")
)
}
pub fn shares_pool_with(&self, other: &Route) -> bool {
if self.provider.is_unknown() || other.provider.is_unknown() {
return false;
}
if self.provider != other.provider {
return false;
}
match self.metering() {
MeteringShape::PerModelFamily => model_family(self.model.as_deref())
.zip(model_family(other.model.as_deref()))
.is_some_and(|(a, b)| a == b),
MeteringShape::None | MeteringShape::Unknown => false,
_ => true,
}
}
}
fn model_family(model: Option<&str>) -> Option<&'static str> {
model.map(super::provider::model_family)
}
#[cfg(test)]
#[path = "route_tests.rs"]
mod tests;