codetether-agent 4.7.0-a-002.4

A2A-native AI coding agent for the CodeTether ecosystem
Documentation
use super::constants::{RESPONSE_RESERVE_TOKENS, TRUNCATION_THRESHOLD};
use super::estimation::estimate_total_tokens;
use super::summary::summarize_removed_messages;
use super::truncation::truncate_large_tool_results;
use crate::provider::{ContentPart, Message, Role};

pub fn truncate_messages_to_fit(messages: &mut Vec<Message>, context_limit: usize) -> usize {
    let target_tokens =
        ((context_limit as f64) * TRUNCATION_THRESHOLD) as usize - RESPONSE_RESERVE_TOKENS;
    if estimate_total_tokens(messages) <= target_tokens {
        return 0;
    }
    truncate_large_tool_results(messages, 2000);
    if estimate_total_tokens(messages) <= target_tokens || messages.len() <= 6 {
        return 0;
    }
    remove_middle_messages(messages)
}

fn remove_middle_messages(messages: &mut Vec<Message>) -> usize {
    let keep_start = 2;
    let keep_end = 4;
    let removable_count = messages.len().saturating_sub(keep_start + keep_end);
    if removable_count == 0 {
        return 0;
    }
    let removed: Vec<_> = messages
        .drain(keep_start..keep_start + removable_count)
        .collect();
    let summary = summarize_removed_messages(&removed);
    messages.insert(keep_start, summary_message(removed.len(), summary));
    removed.len()
}

fn summary_message(removed: usize, summary: String) -> Message {
    Message {
        role: Role::User,
        content: vec![ContentPart::Text {
            text: format!(
                "[Context truncated: {removed} earlier messages removed to fit context window]\n{summary}"
            ),
        }],
    }
}