supercode-interchange 0.4.6

Canonical, provider-neutral session interchange primitives for Supercode
Documentation
//! Provider-independent token estimates over canonical session messages.
//!
//! This module is deliberately smaller than `tokens`: request guards that
//! account for provider tool schemas remain runtime concerns, while reduction
//! and interchange only need deterministic text/message estimates.

use crate::message::ChatMessage;

/// Deterministic token estimate: `ceil(utf8_bytes / 4)`.
pub fn estimate_tokens(value: &str) -> u64 {
    (value.len() as u64).div_ceil(4)
}

/// Estimate the serialized wire size of canonical messages.
pub fn estimate_view_tokens(messages: &[ChatMessage]) -> u64 {
    messages.iter().map(estimate_message_tokens).sum()
}

fn estimate_message_tokens(message: &ChatMessage) -> u64 {
    match serde_json::to_string(message) {
        Ok(wire) => estimate_tokens(&wire),
        Err(_) => estimate_tokens(&format!("{message:?}")),
    }
}

/// Render `n` with comma thousands separators.
pub fn format_commas(n: usize) -> String {
    let digits = n.to_string();
    let bytes = digits.as_bytes();
    let mut output = String::with_capacity(bytes.len() + bytes.len() / 3);
    for (index, byte) in bytes.iter().enumerate() {
        if index > 0 && (bytes.len() - index) % 3 == 0 {
            output.push(',');
        }
        output.push(*byte as char);
    }
    output
}