()
| 640 | |
| 641 | #[tokio::test] |
| 642 | async fn test_generate_streaming_tool_mode() { |
| 643 | let client = MockStructuredClient::new(vec![MockStructuredClient::tool_call_response( |
| 644 | "emit_result", |
| 645 | serde_json::json!({"items": ["a", "b", "c"]}), |
| 646 | )]); |
| 647 | |
| 648 | let req = StructuredRequest { |
| 649 | prompt: "List items".to_string(), |
| 650 | system: None, |
| 651 | schema: serde_json::json!({ |
| 652 | "type": "object", |
| 653 | "required": ["items"], |
| 654 | "properties": { |
| 655 | "items": {"type": "array", "items": {"type": "string"}} |
| 656 | } |
| 657 | }), |
| 658 | schema_name: "result".to_string(), |
| 659 | schema_description: None, |
| 660 | mode: StructuredMode::Tool, |
| 661 | max_repair_attempts: 0, |
| 662 | }; |
| 663 | |
| 664 | let partials = Arc::new(Mutex::new(Vec::new())); |
| 665 | let partials_clone = Arc::clone(&partials); |
| 666 | let callback: PartialObjectCallback = Box::new(move |v: &Value| { |
| 667 | partials_clone.lock().unwrap().push(v.clone()); |
| 668 | }); |
| 669 | |
| 670 | let result = generate_streaming(&client, &req, callback).await.unwrap(); |
| 671 | assert_eq!(result.object["items"][0], "a"); |
| 672 | assert_eq!(result.object["items"][2], "c"); |
| 673 | |
| 674 | let p = partials.lock().unwrap(); |
| 675 | assert!(!p.is_empty()); |
| 676 | } |
| 677 | |
| 678 | // ======================================================================== |
| 679 | // Edge case: extract_json_value |
nothing calls this directly
no test coverage detected