Skip to main content

vtcode_core/compaction/
mod.rs

1use anyhow::{Context, Result};
2use chrono::{DateTime, Utc};
3use serde_json::{Value, json};
4use std::fmt::Write;
5use std::sync::Arc;
6use vtcode_commons::is_context_capacity_message;
7use vtcode_commons::llm::FinishReason;
8use vtcode_config::constants::context::DEFAULT_COMPACTION_TRIGGER_RATIO;
9
10use crate::config::types::{ReasoningEffortLevel, VerbosityLevel};
11use crate::exec::events::CompactionMode;
12use crate::llm::reasoning_effort::ReasoningEffortMapper;
13use crate::llm::utils::truncate_to_token_limit;
14use crate::llm::{
15    collect_single_response,
16    provider::{
17        LLMProvider, LLMRequest, LLMResponse, Message, MessageContent, MessageRole, ResponsesCompactionOptions,
18        ToolChoice, ToolDefinition,
19    },
20};
21
22pub mod auto;
23pub mod memory_envelope;
24pub mod prefire;
25pub mod two_pass;
26
27pub use crate::compaction::memory_envelope::{effective_context_budget, effective_session_context_budget};
28pub use crate::compaction::prefire::{AsyncCompactionCache, PrefireState};
29
30pub const SUPPRESS_NONE: u8 = 0;
31pub const SUPPRESS_TURN: u8 = 1;
32pub const SUPPRESS_STICKY: u8 = 2;
33pub const SUPPRESS_UNTIL_SUCCESS: u8 = 3;
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub(crate) enum SuppressReason {
37    CreditBlock,
38    Size,
39    Auth,
40    Schema,
41    Other,
42}
43
44impl SuppressReason {
45    fn suppress_state(self) -> u8 {
46        match self {
47            SuppressReason::Size | SuppressReason::Schema => SUPPRESS_STICKY,
48            SuppressReason::CreditBlock | SuppressReason::Auth => SUPPRESS_UNTIL_SUCCESS,
49            SuppressReason::Other => SUPPRESS_TURN,
50        }
51    }
52}
53
54/// Classify a deterministic compaction failure's error text into a fixed
55/// [`SuppressReason`] (drives telemetry + sticky-vs-per-turn scope).
56pub(crate) fn classify_suppress_reason(error_msg: &str) -> SuppressReason {
57    let m = error_msg.to_ascii_lowercase();
58    if m.contains("spending-limit")
59        || m.contains("spending limit")
60        || m.contains("out of credits")
61        || m.contains("usage balance exhausted")
62        || m.contains("usage limit reached")
63    {
64        SuppressReason::CreditBlock
65    } else if m.contains("context length") || m.contains("too many tokens") {
66        SuppressReason::Size
67    } else if m.contains("status 401") || m.contains("unauthorized") {
68        SuppressReason::Auth
69    } else if m.contains("invalid_request_error") {
70        SuppressReason::Schema
71    } else {
72        SuppressReason::Other
73    }
74}
75
76mod config;
77mod continuity;
78mod history_bounds;
79mod history_build;
80mod native_inline;
81mod retention;
82mod strategy;
83mod summarize;
84
85pub use config::*;
86pub use continuity::*;
87pub(crate) use history_bounds::*;
88pub(crate) use history_build::*;
89pub(crate) use retention::*;
90pub use strategy::*;
91pub use summarize::*;
92
93#[cfg(test)]
94mod summarization_fork_bounds_tests;
95
96#[cfg(test)]
97mod tests;