agentix 0.12.0

Multi-provider LLM client for Rust — streaming, non-streaming, tool calls, MCP, DeepSeek, OpenAI, Anthropic, Gemini
Documentation
//! Shared types used across the raw provider and request layers.
//!
//! These types are kept separate to avoid circular dependencies between
//! `raw/` (provider wire formats) and `request` (public API).

// ── Usage & Accounting ────────────────────────────────────────────────────────

/// Token usage statistics for a single request or an entire session.
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct UsageStats {
    /// Number of tokens in the prompt.
    pub prompt_tokens: usize,
    /// Number of tokens generated by the model.
    pub completion_tokens: usize,
    /// Total tokens used (prompt + completion).
    pub total_tokens: usize,
}

impl std::ops::AddAssign for UsageStats {
    fn add_assign(&mut self, rhs: Self) {
        self.prompt_tokens += rhs.prompt_tokens;
        self.completion_tokens += rhs.completion_tokens;
        self.total_tokens += rhs.total_tokens;
    }
}

// ── Non-streaming response ────────────────────────────────────────────────────

/// The result of a non-streaming (complete) API call.
#[derive(Debug, Clone, Default)]
pub struct CompleteResponse {
    /// The text content produced by the model (may be empty if only tool calls).
    pub content: Option<String>,
    /// Chain-of-thought / reasoning text, if any.
    pub reasoning: Option<String>,
    /// Tool calls requested by the model.
    pub tool_calls: Vec<crate::request::ToolCall>,
    /// Token usage statistics.
    pub usage: UsageStats,
}

impl CompleteResponse {
    /// Deserialize the response content as JSON into `T`.
    ///
    /// Equivalent to `serde_json::from_str(response.content.unwrap_or_default())`.
    /// Useful with [`Request::json_schema`] or [`Request::json`].
    pub fn json<T: serde::de::DeserializeOwned>(&self) -> serde_json::Result<T> {
        serde_json::from_str(self.content.as_deref().unwrap_or(""))
    }
}

// ── Internal provider events ──────────────────────────────────────────────────

/// A tool call fragment emitted during a streaming turn.
#[derive(Debug, Clone)]
pub struct ToolCallChunk {
    /// Unique call ID assigned by the provider.
    pub id: String,
    /// Tool name being invoked.
    pub name: String,
    /// Incremental JSON argument fragment.
    pub delta: String,
    /// Zero-based index when multiple tool calls happen in one turn.
    pub index: u32,
}

// ── Streaming accumulator ─────────────────────────────────────────────────────

/// Accumulates a single tool-call's incremental SSE deltas until the stream ends.
#[derive(Debug)]
pub struct PartialToolCall {
    /// Unique call ID assigned by the provider.
    pub id: String,
    /// Tool name being invoked.
    pub name: String,
    /// JSON arguments accumulated so far.
    pub arguments: String,
}

/// Provider-agnostic streaming state — accumulates text, reasoning, and
/// tool-call fragments across SSE chunks.
pub struct StreamBufs {
    /// Accumulated text content.
    pub content_buf: String,
    /// Accumulated reasoning / chain-of-thought.
    pub reasoning_buf: String,
    /// Sparse per-index partial tool-call buffers.
    pub tool_call_bufs: Vec<Option<PartialToolCall>>,
}

impl StreamBufs {
    pub fn new() -> Self {
        Self {
            content_buf: String::new(),
            reasoning_buf: String::new(),
            tool_call_bufs: Vec::new(),
        }
    }
}

impl Default for StreamBufs {
    fn default() -> Self {
        Self::new()
    }
}