Skip to main content

systemprompt_models/services/ai/
model.rs

1//! Per-provider AI policy and per-model descriptors.
2//!
3//! [`AiProviderConfig`] is the deployment policy layered on a registry provider
4//! (enable flag, default-model overrides, resilience). [`ModelDefinition`] and
5//! its [`ModelCapabilities`], [`ModelLimits`], and [`ModelPricing`] are the
6//! per-model descriptors shared with `profile.providers`. Connectivity itself
7//! is never modelled here — it lives in the provider registry.
8
9use serde::{Deserialize, Serialize};
10
11use super::config::ResilienceSettings;
12
13const fn default_true() -> bool {
14    true
15}
16
17#[expect(
18    clippy::struct_excessive_bools,
19    reason = "model capability matrix: each bool is an independent provider feature flag, not \
20              state"
21)]
22#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, schemars::JsonSchema)]
23pub struct ModelCapabilities {
24    #[serde(default)]
25    pub vision: bool,
26
27    #[serde(default)]
28    pub audio_input: bool,
29
30    #[serde(default)]
31    pub video_input: bool,
32
33    #[serde(default)]
34    pub image_generation: bool,
35
36    #[serde(default)]
37    pub audio_generation: bool,
38
39    #[serde(default)]
40    pub streaming: bool,
41
42    #[serde(default)]
43    pub tools: bool,
44
45    #[serde(default)]
46    pub structured_output: bool,
47
48    #[serde(default)]
49    pub system_prompts: bool,
50
51    #[serde(default)]
52    pub image_resolution_config: bool,
53}
54
55#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, schemars::JsonSchema)]
56pub struct ModelLimits {
57    #[serde(default)]
58    pub context_window: u32,
59
60    #[serde(default)]
61    pub max_output_tokens: u32,
62}
63
64#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, schemars::JsonSchema)]
65pub struct ModelPricing {
66    #[serde(default)]
67    pub input_per_million: f64,
68
69    #[serde(default)]
70    pub output_per_million: f64,
71
72    #[serde(default)]
73    pub per_image_cents: Option<f64>,
74}
75
76#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
77pub struct ModelDefinition {
78    #[serde(default)]
79    pub capabilities: ModelCapabilities,
80
81    #[serde(default)]
82    pub limits: ModelLimits,
83
84    #[serde(default)]
85    pub pricing: ModelPricing,
86}
87
88/// Per-provider AI *policy*, keyed by registry provider name.
89///
90/// Connectivity (endpoint, credential, model catalog) lives in the profile
91/// `providers` registry; this struct carries only the policy a deployment
92/// layers on top of an entry: whether the provider is enabled, its agent-side
93/// default-model override, image defaults, web-search toggle, and resilience.
94#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct AiProviderConfig {
96    #[serde(default = "default_true")]
97    pub enabled: bool,
98
99    /// Overrides the provider client's built-in default model when non-empty.
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    /// Resilience policy applied to outbound AI provider calls (timeouts,
113    /// retry, circuit breaker, bulkhead).
114    #[serde(default)]
115    pub resilience: ResilienceSettings,
116}
117
118impl Default for AiProviderConfig {
119    fn default() -> Self {
120        Self {
121            enabled: true,
122            default_model: String::new(),
123            default_image_model: String::new(),
124            default_image_resolution: String::new(),
125            google_search_enabled: false,
126            resilience: ResilienceSettings::default(),
127        }
128    }
129}