Skip to main content

bitrouter_core/routers/
routing_table.rs

1use serde::Serialize;
2
3use crate::errors::Result;
4
5/// The target to route a request to.
6pub struct RoutingTarget {
7    /// The provider name to route to.
8    pub provider_name: String,
9    /// The actual upstream provider's model ID to route to.
10    pub model_id: String,
11}
12
13/// A single entry in the route listing, describing a configured model route.
14#[derive(Debug, Clone)]
15pub struct RouteEntry {
16    /// The virtual model name (e.g. "default", "my-gpt4").
17    pub model: String,
18    /// The provider name this model routes to.
19    pub provider: String,
20    /// The API protocol the provider uses ("openai", "anthropic", "google").
21    pub protocol: String,
22}
23
24/// Input token pricing per million tokens.
25#[derive(Debug, Clone, Default, Serialize)]
26pub struct InputTokenPricing {
27    /// Cost per million non-cached input tokens.
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub no_cache: Option<f64>,
30    /// Cost per million cache-read input tokens.
31    #[serde(skip_serializing_if = "Option::is_none")]
32    pub cache_read: Option<f64>,
33    /// Cost per million cache-write input tokens.
34    #[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/// Output token pricing per million tokens.
45#[derive(Debug, Clone, Default, Serialize)]
46pub struct OutputTokenPricing {
47    /// Cost per million text output tokens.
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub text: Option<f64>,
50    /// Cost per million reasoning output tokens.
51    #[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/// Token pricing per million tokens for a model.
62#[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    /// Returns `true` when no pricing data is set.
72    pub fn is_empty(&self) -> bool {
73        self.input_tokens.is_empty() && self.output_tokens.is_empty()
74    }
75}
76
77/// A routing table that maps incoming model names to routing targets (provider + model ID).
78pub trait RoutingTable {
79    /// Routes an incoming model name to a routing target.
80    fn route(
81        &self,
82        incoming_model_name: &str,
83    ) -> impl Future<Output = Result<RoutingTarget>> + Send;
84
85    /// Lists all configured model routes.
86    fn list_routes(&self) -> Vec<RouteEntry> {
87        Vec::new()
88    }
89}