rig-core 0.35.0

An opinionated library for building LLM powered applications.
Documentation
use futures::stream;
use rig::OneOrMany;
use rig::agent::MultiTurnStreamItem;
use rig::completion::Usage;
use rig::message::{ToolCall, ToolFunction, ToolResult, ToolResultContent};
use rig::streaming::{StreamedAssistantContent, StreamedUserContent};

use crate::reasoning::collect_stream_stats;

#[tokio::test]
async fn collect_stream_stats_tracks_only_final_turn_text() {
    let internal_call_id = "call_internal_1".to_string();
    let tool_call = ToolCall::new(
        "tool_1".to_string(),
        ToolFunction::new(
            "get_weather".to_string(),
            serde_json::json!({ "city": "Tokyo" }),
        ),
    );
    let tool_result = ToolResult {
        id: "tool_1".to_string(),
        call_id: None,
        content: OneOrMany::one(ToolResultContent::text("72F and sunny")),
    };

    let items = vec![
        Ok(MultiTurnStreamItem::StreamAssistantItem(
            StreamedAssistantContent::<()>::text("Sure! Let me check the weather right away!"),
        )),
        Ok(MultiTurnStreamItem::StreamAssistantItem(
            StreamedAssistantContent::ToolCall {
                tool_call,
                internal_call_id: internal_call_id.clone(),
            },
        )),
        Ok(MultiTurnStreamItem::StreamUserItem(
            StreamedUserContent::tool_result(tool_result, internal_call_id),
        )),
        Ok(MultiTurnStreamItem::StreamAssistantItem(
            StreamedAssistantContent::<()>::text("It's 72F and sunny in Tokyo."),
        )),
        Ok(MultiTurnStreamItem::final_response(
            "It's 72F and sunny in Tokyo.",
            Usage::new(),
        )),
    ];

    let stats = collect_stream_stats(stream::iter(items), "test").await;

    assert_eq!(stats.tool_calls_in_stream, vec!["get_weather".to_string()]);
    assert_eq!(stats.tool_results_in_stream, 1);
    assert!(stats.got_final_response, "expected final response event");
    assert_eq!(
        stats.final_turn_text, "It's 72F and sunny in Tokyo.",
        "pre-tool assistant text should not be counted as final-turn text"
    );
    assert_eq!(
        stats.final_response_text.as_deref(),
        Some(stats.final_turn_text.as_str()),
        "final response text should match the final turn's streamed text"
    );
}