Skip to main content

oxicode_catalog/catalog/
model.rs

1//! Model metadata structures — used by the materialize pipeline.
2
3use serde::{Deserialize, Serialize};
4
5use super::provider::AuthMethod;
6
7/// A single built-in model entry.
8///
9/// Produced by [`crate::catalog::materialize::materialize`] from the
10/// models.dev catalog. The TOML-based path that previously populated
11/// these entries has been removed.
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct BuiltinModelEntry {
14    /// Model identifier (e.g., "claude-sonnet-4-20250514")
15    pub id: String,
16    /// Human-readable model name (e.g., "Claude Sonnet 4")
17    pub name: String,
18    /// API protocol to use
19    pub api: String,
20    /// Provider name (e.g., "anthropic", "openai")
21    pub provider: String,
22    /// Whether this model supports reasoning/thinking
23    #[serde(default)]
24    pub reasoning: bool,
25    /// Supported input modalities
26    #[serde(default)]
27    pub input: Vec<String>,
28    /// Cost per million input tokens (USD)
29    #[serde(default)]
30    pub cost_input: f64,
31    /// Cost per million output tokens (USD)
32    #[serde(default)]
33    pub cost_output: f64,
34    /// Cost per million cached read tokens (USD)
35    #[serde(default)]
36    pub cost_cache_read: f64,
37    /// Cost per million cached write tokens (USD)
38    #[serde(default)]
39    pub cost_cache_write: f64,
40    /// Maximum context window in tokens
41    #[serde(default)]
42    pub context_window: u32,
43    /// Maximum output tokens
44    #[serde(default)]
45    pub max_tokens: u32,
46    /// Authentication method (overrides provider default).
47    #[serde(default)]
48    pub auth_method: AuthMethod,
49    /// Per-model base URL override (None = inherit from provider).
50    #[serde(default)]
51    pub base_url: Option<String>,
52}
53
54impl BuiltinModelEntry {
55    /// Check if this model supports image/vision input.
56    pub fn supports_vision(&self) -> bool {
57        self.input.iter().any(|m| m == "image" || m == "Image")
58    }
59
60    /// Check if this model supports reasoning/thinking.
61    pub fn supports_reasoning(&self) -> bool {
62        self.reasoning
63    }
64
65    /// Calculate the cost for a given token usage.
66    pub fn calculate_cost(
67        &self,
68        input_tokens: u64,
69        output_tokens: u64,
70        cache_read: u64,
71        cache_write: u64,
72    ) -> f64 {
73        let in_cost = (input_tokens as f64 / 1_000_000.0) * self.cost_input;
74        let out_cost = (output_tokens as f64 / 1_000_000.0) * self.cost_output;
75        let cr_cost = (cache_read as f64 / 1_000_000.0) * self.cost_cache_read;
76        let cw_cost = (cache_write as f64 / 1_000_000.0) * self.cost_cache_write;
77        in_cost + out_cost + cr_cost + cw_cost
78    }
79}