1use serde::{Serialize, de::DeserializeOwned};
2
3pub trait AgentOutputT: Serialize + DeserializeOwned + Send + Sync {
5 fn output_schema() -> &'static str;
7
8 fn structured_output_format() -> serde_json::Value;
10}
11
12impl AgentOutputT for String {
14 fn output_schema() -> &'static str {
15 "{}"
16 }
17
18 fn structured_output_format() -> serde_json::Value {
19 serde_json::Value::Null
20 }
21}
22
23#[cfg(test)]
24mod tests {
25 use super::*;
26 use serde::{Deserialize, Serialize};
27 use serde_json::json;
28
29 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
30 struct TestOutput {
31 message: String,
32 count: u32,
33 }
34
35 impl AgentOutputT for TestOutput {
36 fn output_schema() -> &'static str {
37 r#"{"type":"object","properties":{"message":{"type":"string"},"count":{"type":"integer"}},"required":["message","count"]}"#
38 }
39
40 fn structured_output_format() -> serde_json::Value {
41 json!({
42 "type": "object",
43 "properties": {
44 "message": {"type": "string"},
45 "count": {"type": "integer"}
46 },
47 "required": ["message", "count"]
48 })
49 }
50 }
51
52 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
53 struct SimpleOutput {
54 value: String,
55 }
56
57 impl AgentOutputT for SimpleOutput {
58 fn output_schema() -> &'static str {
59 r#"{"type":"object","properties":{"value":{"type":"string"}},"required":["value"]}"#
60 }
61
62 fn structured_output_format() -> serde_json::Value {
63 json!({
64 "type": "object",
65 "properties": {
66 "value": {"type": "string"}
67 },
68 "required": ["value"]
69 })
70 }
71 }
72
73 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
74 struct ComplexOutput {
75 name: String,
76 age: u32,
77 active: bool,
78 tags: Vec<String>,
79 }
80
81 impl AgentOutputT for ComplexOutput {
82 fn output_schema() -> &'static str {
83 r#"{"type":"object","properties":{"name":{"type":"string"},"age":{"type":"integer"},"active":{"type":"boolean"},"tags":{"type":"array","items":{"type":"string"}}},"required":["name","age","active","tags"]}"#
84 }
85
86 fn structured_output_format() -> serde_json::Value {
87 json!({
88 "type": "object",
89 "properties": {
90 "name": {"type": "string"},
91 "age": {"type": "integer"},
92 "active": {"type": "boolean"},
93 "tags": {
94 "type": "array",
95 "items": {"type": "string"}
96 }
97 },
98 "required": ["name", "age", "active", "tags"]
99 })
100 }
101 }
102
103 #[test]
104 fn test_agent_output_trait_basic() {
105 fn assert_agent_output<T: AgentOutputT>() {}
107 assert_agent_output::<String>();
108 assert_agent_output::<TestOutput>();
109 }
110
111 #[test]
112 fn test_string_output_schema() {
113 let schema = String::output_schema();
114 assert_eq!(schema, "{}");
115 }
116
117 #[test]
118 fn test_string_structured_output_format() {
119 let format = String::structured_output_format();
120 assert_eq!(format, serde_json::Value::Null);
121 }
122
123 #[test]
124 fn test_test_output_schema() {
125 let schema = TestOutput::output_schema();
126 assert!(schema.contains("object"));
127 assert!(schema.contains("message"));
128 assert!(schema.contains("count"));
129 assert!(schema.contains("string"));
130 assert!(schema.contains("integer"));
131 assert!(schema.contains("required"));
132 }
133
134 #[test]
135 fn test_test_output_structured_format() {
136 let format = TestOutput::structured_output_format();
137 assert_eq!(format["type"], "object");
138 assert_eq!(format["properties"]["message"]["type"], "string");
139 assert_eq!(format["properties"]["count"]["type"], "integer");
140 assert_eq!(format["required"][0], "message");
141 assert_eq!(format["required"][1], "count");
142 }
143
144 #[test]
145 fn test_test_output_serialization() {
146 let output = TestOutput {
147 message: "Hello World".to_string(),
148 count: 42,
149 };
150 let serialized = serde_json::to_string(&output).unwrap();
151 assert!(serialized.contains("Hello World"));
152 assert!(serialized.contains("42"));
153 }
154
155 #[test]
156 fn test_test_output_deserialization() {
157 let json = r#"{"message":"Test Message","count":123}"#;
158 let output: TestOutput = serde_json::from_str(json).unwrap();
159 assert_eq!(output.message, "Test Message");
160 assert_eq!(output.count, 123);
161 }
162
163 #[test]
164 fn test_test_output_clone() {
165 let output = TestOutput {
166 message: "Clone Test".to_string(),
167 count: 999,
168 };
169 let cloned = output.clone();
170 assert_eq!(output, cloned);
171 }
172
173 #[test]
174 fn test_test_output_debug() {
175 let output = TestOutput {
176 message: "Debug Test".to_string(),
177 count: 456,
178 };
179 let debug_str = format!("{output:?}");
180 assert!(debug_str.contains("TestOutput"));
181 assert!(debug_str.contains("Debug Test"));
182 assert!(debug_str.contains("456"));
183 }
184
185 #[test]
186 fn test_simple_output_schema() {
187 let schema = SimpleOutput::output_schema();
188 assert!(schema.contains("object"));
189 assert!(schema.contains("value"));
190 assert!(schema.contains("string"));
191 }
192
193 #[test]
194 fn test_simple_output_structured_format() {
195 let format = SimpleOutput::structured_output_format();
196 assert_eq!(format["type"], "object");
197 assert_eq!(format["properties"]["value"]["type"], "string");
198 assert_eq!(format["required"][0], "value");
199 }
200
201 #[test]
202 fn test_simple_output_serialization() {
203 let output = SimpleOutput {
204 value: "simple value".to_string(),
205 };
206 let serialized = serde_json::to_string(&output).unwrap();
207 assert!(serialized.contains("simple value"));
208 }
209
210 #[test]
211 fn test_simple_output_deserialization() {
212 let json = r#"{"value":"deserialized value"}"#;
213 let output: SimpleOutput = serde_json::from_str(json).unwrap();
214 assert_eq!(output.value, "deserialized value");
215 }
216
217 #[test]
218 fn test_complex_output_schema() {
219 let schema = ComplexOutput::output_schema();
220 assert!(schema.contains("object"));
221 assert!(schema.contains("name"));
222 assert!(schema.contains("age"));
223 assert!(schema.contains("active"));
224 assert!(schema.contains("tags"));
225 assert!(schema.contains("array"));
226 assert!(schema.contains("boolean"));
227 }
228
229 #[test]
230 fn test_complex_output_structured_format() {
231 let format = ComplexOutput::structured_output_format();
232 assert_eq!(format["type"], "object");
233 assert_eq!(format["properties"]["name"]["type"], "string");
234 assert_eq!(format["properties"]["age"]["type"], "integer");
235 assert_eq!(format["properties"]["active"]["type"], "boolean");
236 assert_eq!(format["properties"]["tags"]["type"], "array");
237 assert_eq!(format["properties"]["tags"]["items"]["type"], "string");
238 }
239
240 #[test]
241 fn test_complex_output_serialization() {
242 let output = ComplexOutput {
243 name: "Test User".to_string(),
244 age: 25,
245 active: true,
246 tags: vec!["tag1".to_string(), "tag2".to_string()],
247 };
248 let serialized = serde_json::to_string(&output).unwrap();
249 assert!(serialized.contains("Test User"));
250 assert!(serialized.contains("25"));
251 assert!(serialized.contains("true"));
252 assert!(serialized.contains("tag1"));
253 assert!(serialized.contains("tag2"));
254 }
255
256 #[test]
257 fn test_complex_output_deserialization() {
258 let json = r#"{"name":"Complex User","age":30,"active":false,"tags":["work","personal"]}"#;
259 let output: ComplexOutput = serde_json::from_str(json).unwrap();
260 assert_eq!(output.name, "Complex User");
261 assert_eq!(output.age, 30);
262 assert!(!output.active);
263 assert_eq!(output.tags, vec!["work", "personal"]);
264 }
265
266 #[test]
267 fn test_complex_output_with_empty_tags() {
268 let output = ComplexOutput {
269 name: "Empty Tags".to_string(),
270 age: 35,
271 active: true,
272 tags: vec![],
273 };
274 let serialized = serde_json::to_string(&output).unwrap();
275 let deserialized: ComplexOutput = serde_json::from_str(&serialized).unwrap();
276 assert_eq!(deserialized.tags.len(), 0);
277 }
278
279 #[test]
280 fn test_output_with_special_characters() {
281 let output = TestOutput {
282 message: "Special chars: !@#$%^&*()".to_string(),
283 count: 0,
284 };
285 let serialized = serde_json::to_string(&output).unwrap();
286 let deserialized: TestOutput = serde_json::from_str(&serialized).unwrap();
287 assert_eq!(deserialized.message, "Special chars: !@#$%^&*()");
288 }
289
290 #[test]
291 fn test_output_with_unicode() {
292 let output = TestOutput {
293 message: "Unicode: 你好世界 🌍".to_string(),
294 count: 42,
295 };
296 let serialized = serde_json::to_string(&output).unwrap();
297 let deserialized: TestOutput = serde_json::from_str(&serialized).unwrap();
298 assert_eq!(deserialized.message, "Unicode: 你好世界 🌍");
299 }
300
301 #[test]
302 fn test_output_with_newlines() {
303 let output = TestOutput {
304 message: "Multi\nLine\nMessage".to_string(),
305 count: 3,
306 };
307 let serialized = serde_json::to_string(&output).unwrap();
308 let deserialized: TestOutput = serde_json::from_str(&serialized).unwrap();
309 assert_eq!(deserialized.message, "Multi\nLine\nMessage");
310 }
311
312 #[test]
313 fn test_output_with_large_count() {
314 let output = TestOutput {
315 message: "Large count".to_string(),
316 count: u32::MAX,
317 };
318 let serialized = serde_json::to_string(&output).unwrap();
319 let deserialized: TestOutput = serde_json::from_str(&serialized).unwrap();
320 assert_eq!(deserialized.count, u32::MAX);
321 }
322
323 #[test]
324 fn test_output_with_zero_count() {
325 let output = TestOutput {
326 message: "Zero count".to_string(),
327 count: 0,
328 };
329 let serialized = serde_json::to_string(&output).unwrap();
330 let deserialized: TestOutput = serde_json::from_str(&serialized).unwrap();
331 assert_eq!(deserialized.count, 0);
332 }
333
334 #[test]
335 fn test_output_with_empty_string() {
336 let output = TestOutput {
337 message: "".to_string(),
338 count: 100,
339 };
340 let serialized = serde_json::to_string(&output).unwrap();
341 let deserialized: TestOutput = serde_json::from_str(&serialized).unwrap();
342 assert_eq!(deserialized.message, "");
343 assert_eq!(deserialized.count, 100);
344 }
345
346 #[test]
347 fn test_output_equality() {
348 let output1 = TestOutput {
349 message: "Equal test".to_string(),
350 count: 50,
351 };
352 let output2 = TestOutput {
353 message: "Equal test".to_string(),
354 count: 50,
355 };
356 let output3 = TestOutput {
357 message: "Different test".to_string(),
358 count: 50,
359 };
360 assert_eq!(output1, output2);
361 assert_ne!(output1, output3);
362 }
363
364 #[test]
365 fn test_multiple_output_types() {
366 let _test_output = TestOutput {
367 message: "test".to_string(),
368 count: 1,
369 };
370 let _simple_output = SimpleOutput {
371 value: "simple".to_string(),
372 };
373 let _complex_output = ComplexOutput {
374 name: "complex".to_string(),
375 age: 25,
376 active: true,
377 tags: vec!["tag".to_string()],
378 };
379
380 assert_ne!(TestOutput::output_schema(), SimpleOutput::output_schema());
382 assert_ne!(
383 SimpleOutput::output_schema(),
384 ComplexOutput::output_schema()
385 );
386 assert_ne!(TestOutput::output_schema(), ComplexOutput::output_schema());
387 }
388
389 #[test]
390 fn test_schema_json_validity() {
391 let schemas = vec![
393 String::output_schema(),
394 TestOutput::output_schema(),
395 SimpleOutput::output_schema(),
396 ComplexOutput::output_schema(),
397 ];
398
399 for schema in schemas {
400 if schema != "{}" {
401 let _: serde_json::Value = serde_json::from_str(schema).unwrap();
402 }
403 }
404 }
405
406 #[test]
407 fn test_structured_format_json_validity() {
408 let formats = vec![
410 String::structured_output_format(),
411 TestOutput::structured_output_format(),
412 SimpleOutput::structured_output_format(),
413 ComplexOutput::structured_output_format(),
414 ];
415
416 for format in formats {
417 if format != serde_json::Value::Null {
418 assert!(format.is_object() || format.is_null());
419 }
420 }
421 }
422
423 #[test]
424 fn test_send_sync_traits() {
425 fn assert_send_sync<T: Send + Sync>() {}
427 assert_send_sync::<TestOutput>();
428 assert_send_sync::<SimpleOutput>();
429 assert_send_sync::<ComplexOutput>();
430 }
431
432 #[test]
433 fn test_round_trip_serialization() {
434 let outputs = vec![
435 TestOutput {
436 message: "Round trip test".to_string(),
437 count: 789,
438 },
439 TestOutput {
440 message: "Another test".to_string(),
441 count: 0,
442 },
443 ];
444
445 for output in outputs {
446 let serialized = serde_json::to_string(&output).unwrap();
447 let deserialized: TestOutput = serde_json::from_str(&serialized).unwrap();
448 assert_eq!(output, deserialized);
449 }
450 }
451}