Skip to main content

systemprompt_models/services/ai/
model.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4use super::config::ResilienceSettings;
5
6const fn default_true() -> bool {
7    true
8}
9
10#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11pub struct ToolModelSettings {
12    pub model: String,
13
14    #[serde(default)]
15    pub max_output_tokens: Option<u32>,
16}
17
18#[expect(
19    clippy::struct_excessive_bools,
20    reason = "model capability matrix: each bool is an independent provider feature flag, not \
21              state"
22)]
23#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
24pub struct ModelCapabilities {
25    #[serde(default)]
26    pub vision: bool,
27
28    #[serde(default)]
29    pub audio_input: bool,
30
31    #[serde(default)]
32    pub video_input: bool,
33
34    #[serde(default)]
35    pub image_generation: bool,
36
37    #[serde(default)]
38    pub audio_generation: bool,
39
40    #[serde(default)]
41    pub streaming: bool,
42
43    #[serde(default)]
44    pub tools: bool,
45
46    #[serde(default)]
47    pub structured_output: bool,
48
49    #[serde(default)]
50    pub system_prompts: bool,
51
52    #[serde(default)]
53    pub image_resolution_config: bool,
54}
55
56#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
57pub struct ModelLimits {
58    #[serde(default)]
59    pub context_window: u32,
60
61    #[serde(default)]
62    pub max_output_tokens: u32,
63}
64
65#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, schemars::JsonSchema)]
66pub struct ModelPricing {
67    #[serde(default)]
68    pub input_per_million: f64,
69
70    #[serde(default)]
71    pub output_per_million: f64,
72
73    #[serde(default)]
74    pub per_image_cents: Option<f64>,
75}
76
77#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
78pub struct ModelDefinition {
79    #[serde(default)]
80    pub capabilities: ModelCapabilities,
81
82    #[serde(default)]
83    pub limits: ModelLimits,
84
85    #[serde(default)]
86    pub pricing: ModelPricing,
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize)]
90pub struct AiProviderConfig {
91    #[serde(default = "default_true")]
92    pub enabled: bool,
93
94    #[serde(default)]
95    pub api_key: String,
96
97    #[serde(default)]
98    pub endpoint: Option<String>,
99
100    #[serde(default)]
101    pub default_model: String,
102
103    #[serde(default)]
104    pub default_image_model: String,
105
106    #[serde(default)]
107    pub default_image_resolution: String,
108
109    #[serde(default)]
110    pub google_search_enabled: bool,
111
112    #[serde(default)]
113    pub models: HashMap<String, ModelDefinition>,
114
115    /// Resilience policy applied to outbound AI provider calls (timeouts,
116    /// retry, circuit breaker, bulkhead).
117    #[serde(default)]
118    pub resilience: ResilienceSettings,
119}
120
121impl Default for AiProviderConfig {
122    fn default() -> Self {
123        Self {
124            enabled: true,
125            api_key: String::new(),
126            endpoint: None,
127            default_model: String::new(),
128            default_image_model: String::new(),
129            default_image_resolution: String::new(),
130            google_search_enabled: false,
131            models: HashMap::new(),
132            resilience: ResilienceSettings::default(),
133        }
134    }
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize)]
138pub struct ToolModelConfig {
139    pub provider: String,
140    pub model: String,
141
142    #[serde(skip_serializing_if = "Option::is_none")]
143    pub max_output_tokens: Option<u32>,
144
145    #[serde(skip_serializing_if = "Option::is_none")]
146    pub thinking_level: Option<String>,
147}