1use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct EndpointDefinition {
11 pub base_url: String,
12 #[serde(skip_serializing_if = "Option::is_none")]
13 pub protocol: Option<String>, #[serde(skip_serializing_if = "Option::is_none")]
15 pub timeout_ms: Option<u32>,
16}
17
18#[derive(Debug, Clone, Serialize)]
20pub struct EndpointConfig {
21 pub path: String,
22 pub method: String,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub adapter: Option<String>,
25}
26
27impl<'de> Deserialize<'de> for EndpointConfig {
28 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
29 where
30 D: serde::Deserializer<'de>,
31 {
32 #[derive(Deserialize)]
33 #[serde(untagged)]
34 enum Input {
35 Path(String),
37 Obj {
39 path: String,
40 #[serde(default = "default_method")]
41 method: String,
42 #[serde(default)]
43 adapter: Option<String>,
44 },
45 }
46
47 match Input::deserialize(deserializer)? {
48 Input::Path(path) => Ok(EndpointConfig {
49 path,
50 method: default_method(),
51 adapter: None,
52 }),
53 Input::Obj {
54 path,
55 method,
56 adapter,
57 } => Ok(EndpointConfig {
58 path,
59 method,
60 adapter,
61 }),
62 }
63 }
64}
65
66fn default_method() -> String {
67 "POST".to_string()
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct ServiceConfig {
73 pub path: String,
74 #[serde(default = "default_method_get")]
75 pub method: String,
76 #[serde(skip_serializing_if = "Option::is_none")]
77 pub headers: Option<HashMap<String, String>>,
78 #[serde(skip_serializing_if = "Option::is_none")]
79 pub query_params: Option<HashMap<String, String>>,
80 #[serde(skip_serializing_if = "Option::is_none")]
81 pub response_binding: Option<String>,
82}
83
84fn default_method_get() -> String {
85 "GET".to_string()
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct Capabilities {
92 pub streaming: bool,
93 pub tools: bool,
94 pub vision: bool,
95 #[serde(default, skip_serializing_if = "is_false")]
96 pub agentic: bool,
97 #[serde(default, skip_serializing_if = "is_false")]
98 pub parallel_tools: bool,
99 #[serde(default, skip_serializing_if = "is_false")]
100 pub reasoning: bool,
101 #[serde(default, skip_serializing_if = "is_false")]
102 pub multimodal: bool,
103 #[serde(default, skip_serializing_if = "is_false")]
104 pub audio: bool,
105}
106
107fn is_false(b: &bool) -> bool {
108 !*b
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct AuthConfig {
114 #[serde(rename = "type")]
115 pub auth_type: String,
116 #[serde(default, skip_serializing_if = "Option::is_none")]
117 pub token_env: Option<String>,
118 #[serde(default, skip_serializing_if = "Option::is_none")]
119 pub key_env: Option<String>,
120 #[serde(default, skip_serializing_if = "Option::is_none")]
121 pub param_name: Option<String>,
122 #[serde(default, skip_serializing_if = "Option::is_none")]
123 pub header_name: Option<String>,
124 #[serde(default, skip_serializing_if = "Option::is_none")]
125 pub extra_headers: Option<Vec<HeaderConfig>>,
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize)]
130pub struct HeaderConfig {
131 pub name: String,
132 pub value: String,
133}
134
135#[derive(Debug, Clone, Serialize, Deserialize)]
137pub struct StreamingConfig {
138 #[serde(skip_serializing_if = "Option::is_none")]
139 pub event_format: Option<String>,
140 #[serde(skip_serializing_if = "Option::is_none")]
141 pub decoder: Option<DecoderConfig>,
142 #[serde(skip_serializing_if = "Option::is_none")]
143 pub frame_selector: Option<String>,
144 #[serde(default, skip_serializing_if = "Option::is_none")]
146 pub content_path: Option<String>,
147 #[serde(default, skip_serializing_if = "Option::is_none")]
149 pub tool_call_path: Option<String>,
150 #[serde(default, skip_serializing_if = "Option::is_none")]
152 pub usage_path: Option<String>,
153 #[serde(skip_serializing_if = "Option::is_none")]
154 pub candidate: Option<CandidateConfig>,
155 #[serde(skip_serializing_if = "Option::is_none")]
156 pub accumulator: Option<AccumulatorConfig>,
157 #[serde(default)]
158 pub event_map: Vec<EventMapRule>,
159 #[serde(skip_serializing_if = "Option::is_none")]
160 pub stop_condition: Option<String>,
161}
162
163#[derive(Debug, Clone, Serialize, Deserialize)]
165pub struct DecoderConfig {
166 pub format: String,
167 #[serde(skip_serializing_if = "Option::is_none")]
168 pub strategy: Option<String>,
169 #[serde(skip_serializing_if = "Option::is_none")]
170 pub delimiter: Option<String>,
171 #[serde(skip_serializing_if = "Option::is_none")]
172 pub prefix: Option<String>,
173 #[serde(skip_serializing_if = "Option::is_none")]
174 pub done_signal: Option<String>,
175}
176
177#[derive(Debug, Clone, Serialize, Deserialize)]
179pub struct CandidateConfig {
180 #[serde(skip_serializing_if = "Option::is_none")]
181 pub candidate_id_path: Option<String>,
182 #[serde(skip_serializing_if = "Option::is_none")]
183 pub fan_out: Option<bool>,
184}
185
186#[derive(Debug, Clone, Serialize, Deserialize)]
188pub struct AccumulatorConfig {
189 #[serde(default)]
190 pub stateful_tool_parsing: bool,
191 #[serde(skip_serializing_if = "Option::is_none")]
192 pub key_path: Option<String>,
193 #[serde(skip_serializing_if = "Option::is_none")]
194 pub flush_on: Option<String>,
195}
196
197#[derive(Debug, Clone, Serialize, Deserialize)]
199pub struct EventMapRule {
200 #[serde(rename = "match")]
201 pub match_expr: String,
202 pub emit: String,
203 #[serde(default, skip_serializing_if = "Option::is_none")]
204 pub fields: Option<HashMap<String, String>>,
205}
206
207#[derive(Debug, Clone, Serialize, Deserialize)]
209pub struct FeaturesConfig {
210 #[serde(default, skip_serializing_if = "Option::is_none")]
211 pub multi_candidate: Option<MultiCandidateConfig>,
212 #[serde(default, skip_serializing_if = "Option::is_none")]
213 pub response_mapping: Option<ResponseMappingConfig>,
214}
215
216#[derive(Debug, Clone, Serialize, Deserialize)]
218pub struct MultiCandidateConfig {
219 pub support_type: String,
220 #[serde(default, skip_serializing_if = "Option::is_none")]
221 pub param_name: Option<String>,
222 #[serde(default, skip_serializing_if = "Option::is_none")]
223 pub max_concurrent: Option<u32>,
224}
225
226#[derive(Debug, Clone, Serialize, Deserialize)]
228pub struct ResponseMappingConfig {
229 #[serde(default, skip_serializing_if = "Option::is_none")]
230 pub tool_calls: Option<ToolCallsMapping>,
231 #[serde(default, skip_serializing_if = "Option::is_none")]
232 pub error: Option<ErrorMapping>,
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize)]
237pub struct ToolCallsMapping {
238 pub path: String,
239 #[serde(default, skip_serializing_if = "Option::is_none")]
240 pub filter: Option<String>,
241 pub fields: HashMap<String, String>,
242 #[serde(default, skip_serializing_if = "Option::is_none")]
243 pub array_fan_out: Option<bool>,
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize)]
248pub struct ErrorMapping {
249 #[serde(default, skip_serializing_if = "Option::is_none")]
250 pub message_path: Option<String>,
251 #[serde(default, skip_serializing_if = "Option::is_none")]
252 pub code_path: Option<String>,
253 #[serde(default, skip_serializing_if = "Option::is_none")]
254 pub type_path: Option<String>,
255}
256
257#[derive(Debug, Clone, Serialize, Deserialize)]
259pub struct TerminationConfig {
260 pub source_field: String,
261 #[serde(default, skip_serializing_if = "Option::is_none")]
262 pub mapping: Option<HashMap<String, String>>,
263}
264
265#[derive(Debug, Clone, Serialize, Deserialize)]
267pub struct ToolingConfig {
268 pub source_model: String,
269 #[serde(default, skip_serializing_if = "Option::is_none")]
270 pub tool_use: Option<ToolUseMapping>,
271 #[serde(default, skip_serializing_if = "Option::is_none")]
272 pub tool_result: Option<ToolResultMapping>,
273}
274
275#[derive(Debug, Clone, Serialize, Deserialize)]
277pub struct ToolUseMapping {
278 #[serde(default, skip_serializing_if = "Option::is_none")]
279 pub id_path: Option<String>,
280 #[serde(default, skip_serializing_if = "Option::is_none")]
281 pub name_path: Option<String>,
282 #[serde(default, skip_serializing_if = "Option::is_none")]
283 pub input_path: Option<String>,
284 #[serde(default, skip_serializing_if = "Option::is_none")]
285 pub input_format: Option<String>,
286}
287
288#[derive(Debug, Clone, Serialize, Deserialize)]
290pub struct ToolResultMapping {
291 #[serde(default, skip_serializing_if = "Option::is_none")]
292 pub id_path: Option<String>,
293 #[serde(default, skip_serializing_if = "Option::is_none")]
294 pub name_path: Option<String>,
295 #[serde(default, skip_serializing_if = "Option::is_none")]
296 pub response_path: Option<String>,
297}
298
299#[derive(Debug, Clone, Serialize, Deserialize)]
301pub struct RetryPolicy {
302 pub strategy: String,
303 #[serde(default, skip_serializing_if = "Option::is_none")]
304 pub max_retries: Option<u32>,
305 #[serde(default, skip_serializing_if = "Option::is_none")]
306 pub min_delay_ms: Option<u32>,
307 #[serde(default, skip_serializing_if = "Option::is_none")]
308 pub max_delay_ms: Option<u32>,
309 #[serde(default, skip_serializing_if = "Option::is_none")]
310 pub jitter: Option<String>,
311 #[serde(default, skip_serializing_if = "Option::is_none")]
312 pub retry_on_http_status: Option<Vec<u16>>,
313 #[serde(default, skip_serializing_if = "Option::is_none")]
314 pub retry_on_error_status: Option<Vec<String>>,
315}
316
317#[derive(Debug, Clone, Serialize, Deserialize)]
319pub struct ErrorClassification {
320 #[serde(default, skip_serializing_if = "Option::is_none")]
321 pub by_http_status: Option<HashMap<String, String>>,
322 #[serde(default, skip_serializing_if = "Option::is_none")]
323 pub by_error_status: Option<HashMap<String, String>>,
324}
325
326#[derive(Debug, Clone, Serialize, Deserialize)]
329pub struct AvailabilityConfig {
330 pub required: bool,
331 pub regions: Vec<String>, pub check: HealthCheckConfig,
333 #[serde(skip_serializing_if = "Option::is_none")]
334 pub notes: Option<Vec<String>>,
335}
336
337#[derive(Debug, Clone, Serialize, Deserialize)]
340pub struct HealthCheckConfig {
341 pub method: String, pub path: String,
343 pub expected_status: Vec<u16>,
344 #[serde(skip_serializing_if = "Option::is_none")]
345 pub timeout_ms: Option<u32>,
346}
347
348#[derive(Debug, Clone, Serialize, Deserialize)]
350pub struct RateLimitHeaders {
351 #[serde(default, skip_serializing_if = "Option::is_none")]
352 pub requests_limit: Option<String>,
353 #[serde(default, skip_serializing_if = "Option::is_none")]
354 pub requests_remaining: Option<String>,
355 #[serde(default, skip_serializing_if = "Option::is_none")]
356 pub requests_reset: Option<String>,
357 #[serde(default, skip_serializing_if = "Option::is_none")]
358 pub tokens_limit: Option<String>,
359 #[serde(default, skip_serializing_if = "Option::is_none")]
360 pub tokens_remaining: Option<String>,
361 #[serde(default, skip_serializing_if = "Option::is_none")]
362 pub tokens_reset: Option<String>,
363 #[serde(default, skip_serializing_if = "Option::is_none")]
364 pub retry_after: Option<String>,
365}