bitrouter_core/routers/
routing_table.rs1use serde::Serialize;
2
3use crate::errors::Result;
4
5pub struct RoutingTarget {
7 pub provider_name: String,
9 pub model_id: String,
11}
12
13#[derive(Debug, Clone)]
15pub struct RouteEntry {
16 pub model: String,
18 pub provider: String,
20 pub protocol: String,
22}
23
24#[derive(Debug, Clone, Default, Serialize)]
26pub struct InputTokenPricing {
27 #[serde(skip_serializing_if = "Option::is_none")]
29 pub no_cache: Option<f64>,
30 #[serde(skip_serializing_if = "Option::is_none")]
32 pub cache_read: Option<f64>,
33 #[serde(skip_serializing_if = "Option::is_none")]
35 pub cache_write: Option<f64>,
36}
37
38impl InputTokenPricing {
39 fn is_empty(&self) -> bool {
40 self.no_cache.is_none() && self.cache_read.is_none() && self.cache_write.is_none()
41 }
42}
43
44#[derive(Debug, Clone, Default, Serialize)]
46pub struct OutputTokenPricing {
47 #[serde(skip_serializing_if = "Option::is_none")]
49 pub text: Option<f64>,
50 #[serde(skip_serializing_if = "Option::is_none")]
52 pub reasoning: Option<f64>,
53}
54
55impl OutputTokenPricing {
56 fn is_empty(&self) -> bool {
57 self.text.is_none() && self.reasoning.is_none()
58 }
59}
60
61#[derive(Debug, Clone, Default, Serialize)]
63pub struct ModelPricing {
64 #[serde(skip_serializing_if = "InputTokenPricing::is_empty")]
65 pub input_tokens: InputTokenPricing,
66 #[serde(skip_serializing_if = "OutputTokenPricing::is_empty")]
67 pub output_tokens: OutputTokenPricing,
68}
69
70impl ModelPricing {
71 pub fn is_empty(&self) -> bool {
73 self.input_tokens.is_empty() && self.output_tokens.is_empty()
74 }
75}
76
77pub trait RoutingTable {
79 fn route(
81 &self,
82 incoming_model_name: &str,
83 ) -> impl Future<Output = Result<RoutingTarget>> + Send;
84
85 fn list_routes(&self) -> Vec<RouteEntry> {
87 Vec::new()
88 }
89}