pub struct ContextManager { /* private fields */ }Expand description
Context manager: maintains full conversation history and automatically triggers compression when tokens exceed the limit.
§Typical usage
use echo_core::error::Result;
use echo_core::llm::types::Message;
use echo_state::compression::compressor::SlidingWindowCompressor;
use echo_state::compression::{ContextCompressor, ContextManager};
let mut ctx = ContextManager::builder(4096)
.compressor(SlidingWindowCompressor::new(20))
.build();
ctx.push(Message::system("You are an assistant".to_string()));
ctx.push(Message::user("Hello".to_string()));
// Call prepare() before each LLM call to auto-compress over-limit messages
let result = ctx.prepare(None).await?;
let messages = result.messages;§Hybrid pipeline example
use echo_core::error::Result;
use echo_core::llm::LlmClient;
use echo_state::compression::compressor::{
HybridCompressor, SlidingWindowCompressor, SummaryCompressor,
};
use echo_state::compression::{ContextCompressor, ContextManager};
use std::sync::Arc;
let compressor = HybridCompressor::builder()
.stage(SlidingWindowCompressor::new(30))
.stage(SummaryCompressor::new(llm, 8))
.build();
let mut ctx = ContextManager::builder(8192)
.compressor(compressor)
.build();Implementations§
Source§impl ContextManager
impl ContextManager
pub fn builder(token_limit: usize) -> ContextManagerBuilder
Sourcepub fn push(&mut self, message: Message)
pub fn push(&mut self, message: Message)
Append a message to the context buffer.
When the message count exceeds the max_messages hard cap, automatically applies sliding window degradation:
preserves system messages and recent messages, discards the earliest conversation messages in the middle.
This is the last line of defense; even if no compressor is configured or compression fails, OOM will not occur.
Sourcepub fn push_many(&mut self, messages: impl IntoIterator<Item = Message>)
pub fn push_many(&mut self, messages: impl IntoIterator<Item = Message>)
Batch-append messages
Sourcepub fn messages(&self) -> &[Message]
pub fn messages(&self) -> &[Message]
Return all messages currently in the buffer (no compression)
Sourcepub fn set_messages(&mut self, messages: Vec<Message>)
pub fn set_messages(&mut self, messages: Vec<Message>)
Replace the internal message buffer (used to restore conversation from persistent storage)
Messages should include the system prompt as the first entry (if needed).
Sourcepub fn token_estimate(&self) -> usize
pub fn token_estimate(&self) -> usize
Estimate the token count of the current context
Uses the configured Tokenizer implementation (default HeuristicTokenizer, distinguishes ASCII/CJK).
Sourcepub fn set_tokenizer(&mut self, tokenizer: Arc<dyn Tokenizer>)
pub fn set_tokenizer(&mut self, tokenizer: Arc<dyn Tokenizer>)
Dynamically replace the Tokenizer
Sourcepub fn clear(&mut self)
pub fn clear(&mut self)
Clear the context buffer (preserves configured compressor and protection markers)
Sourcepub fn add_protected_marker(&mut self, marker: String)
pub fn add_protected_marker(&mut self, marker: String)
Register a content marker that protects messages from compression.
Any message whose content contains this marker string will be excluded from compression passes. This is used by the skill system to protect activated skill instructions from being evicted during context compaction.
§Example
let mut ctx = ContextManager::builder(4096).build();
ctx.add_protected_marker("<skill_content".to_string());Sourcepub fn set_compressor(&mut self, compressor: impl ContextCompressor + 'static)
pub fn set_compressor(&mut self, compressor: impl ContextCompressor + 'static)
Dynamically replace the compressor without affecting the existing message buffer
Sourcepub fn remove_compressor(&mut self)
pub fn remove_compressor(&mut self)
Remove the compressor, reverting to unlimited mode
Sourcepub fn has_compressor(&self) -> bool
pub fn has_compressor(&self) -> bool
Whether a compressor is configured
Sourcepub async fn force_compress(
&mut self,
fallback_window: usize,
) -> Result<ForceCompressStats, ReactError>
pub async fn force_compress( &mut self, fallback_window: usize, ) -> Result<ForceCompressStats, ReactError>
Force-compress the context, regardless of whether the current token count exceeds the limit.
- If a compressor is configured, use it;
- Otherwise, temporarily use
SlidingWindowCompressor::new(fallback_window).
Protected messages are excluded from compression and preserved.
Sourcepub async fn force_compress_with(
&mut self,
compressor: &dyn ContextCompressor,
) -> Result<ForceCompressStats, ReactError>
pub async fn force_compress_with( &mut self, compressor: &dyn ContextCompressor, ) -> Result<ForceCompressStats, ReactError>
Force-compress using a specific compressor, without affecting the currently installed compressor config.
Suitable for temporary strategy overrides like /compress sliding 10.
Sourcepub fn update_system(&mut self, new_system_prompt: String)
pub fn update_system(&mut self, new_system_prompt: String)
Update the system message content
Typically called when add_skill() injects extra system prompts:
finds the first message with role == “system” and replaces its content;
if no system message exists, inserts one at the head of the queue.
Sourcepub async fn prepare(
&mut self,
current_query: Option<&str>,
) -> Result<PrepareResult, ReactError>
pub async fn prepare( &mut self, current_query: Option<&str>, ) -> Result<PrepareResult, ReactError>
Prepare the list of messages to send to the LLM.
When the estimated token count exceeds token_limit and a compressor is configured, automatically trigger compression and update the internal buffer.
The compressed messages replace the original buffer.
Protected messages (containing registered markers, e.g. <skill_content>) are
excluded from compression and re-inserted after system messages.
current_query is a reserved field; pass None.
Returns a PrepareResult containing the prepared messages and optional
compression stats (populated only when auto-compression was triggered).
Auto Trait Implementations§
impl Freeze for ContextManager
impl !RefUnwindSafe for ContextManager
impl Send for ContextManager
impl Sync for ContextManager
impl Unpin for ContextManager
impl UnsafeUnpin for ContextManager
impl !UnwindSafe for ContextManager
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
Source§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request