objectiveai_sdk/agent/openrouter/
provider.rs1use serde::{Deserialize, Serialize};
7use std::collections::HashSet;
8use schemars::JsonSchema;
9
10#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Hash, JsonSchema, arbitrary::Arbitrary)]
15#[schemars(rename = "agent.openrouter.Provider")]
16pub struct Provider {
17 #[serde(skip_serializing_if = "Option::is_none")]
20 #[schemars(extend("omitempty" = true))]
21 pub allow_fallbacks: Option<bool>,
22 #[serde(skip_serializing_if = "Option::is_none")]
25 #[schemars(extend("omitempty" = true))]
26 pub require_parameters: Option<bool>,
27 #[serde(skip_serializing_if = "Option::is_none")]
29 #[schemars(extend("omitempty" = true))]
30 pub order: Option<Vec<String>>,
31 #[serde(skip_serializing_if = "Option::is_none")]
33 #[schemars(extend("omitempty" = true))]
34 pub only: Option<Vec<String>>,
35 #[serde(skip_serializing_if = "Option::is_none")]
37 #[schemars(extend("omitempty" = true))]
38 pub ignore: Option<Vec<String>>,
39 #[serde(skip_serializing_if = "Option::is_none")]
41 #[schemars(extend("omitempty" = true))]
42 pub quantizations: Option<Vec<ProviderQuantization>>,
43}
44
45impl Provider {
46 pub fn prepare(mut self) -> Option<Self> {
50 if let Some(true) = self.allow_fallbacks {
51 self.allow_fallbacks = None;
52 }
53 if let Some(false) = self.require_parameters {
54 self.require_parameters = None;
55 }
56 if let Some(order) = &mut self.order {
57 if order.is_empty() {
58 self.order = None;
59 } else {
60 let mut dedup = HashSet::with_capacity(order.len());
61 order.retain(|provider| dedup.insert(provider.clone()));
62 }
63 }
64 if let Some(only) = &mut self.only {
65 if only.is_empty() {
66 self.only = None;
67 } else {
68 only.sort();
69 only.dedup();
70 }
71 }
72 if let Some(ignore) = &mut self.ignore {
73 if ignore.is_empty() {
74 self.ignore = None;
75 } else {
76 ignore.sort();
77 ignore.dedup();
78 }
79 }
80 if let Some(quantizations) = &mut self.quantizations {
81 if quantizations.is_empty() {
82 self.quantizations = None;
83 } else {
84 quantizations.sort();
85 quantizations.dedup();
86 }
87 }
88 if self.allow_fallbacks.is_some()
89 || self.require_parameters.is_some()
90 || self.order.is_some()
91 || self.only.is_some()
92 || self.ignore.is_some()
93 || self.quantizations.is_some()
94 {
95 Some(self)
96 } else {
97 None
98 }
99 }
100
101 pub fn validate(&self) -> Result<(), String> {
103 if self.order.iter().any(|s| s.is_empty()) {
104 Err("`provider.order` strings cannot be empty".to_string())
105 } else if self.only.iter().any(|s| s.is_empty()) {
106 Err("`provider.only` strings cannot be empty".to_string())
107 } else if self.ignore.iter().any(|s| s.is_empty()) {
108 Err("`provider.ignore` strings cannot be empty".to_string())
109 } else {
110 Ok(())
111 }
112 }
113}
114
115#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash, JsonSchema, arbitrary::Arbitrary)]
120#[serde(rename_all = "snake_case")]
121#[schemars(rename = "agent.openrouter.ProviderQuantization")]
122pub enum ProviderQuantization {
123 #[schemars(title = "Int4")]
125 Int4,
126 #[schemars(title = "Int8")]
128 Int8,
129 #[schemars(title = "Fp4")]
131 Fp4,
132 #[schemars(title = "Fp6")]
134 Fp6,
135 #[schemars(title = "Fp8")]
137 Fp8,
138 #[schemars(title = "Fp16")]
140 Fp16,
141 #[schemars(title = "Bf16")]
143 Bf16,
144 #[schemars(title = "Fp32")]
146 Fp32,
147 #[schemars(title = "Unknown")]
149 Unknown,
150}
151
152impl PartialOrd for ProviderQuantization {
153 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
154 Some((*self as u16).cmp(&(*other as u16)))
155 }
156}
157
158impl Ord for ProviderQuantization {
159 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
160 self.partial_cmp(other).unwrap()
161 }
162}