//! MemoryAdapter trait — 上下文记忆层抽象 //! //! 将 ContextManager 的核心接口提取为 trait,支持多种记忆后端: //! - InMemoryAdapter(当前 ContextManager 的包装,默认实现) //! - VectorMemoryAdapter(未来:接入向量检索,支持语义记忆) //! //! 使用方式:`Box` 替代 `ContextManager`。 use crate::context::ContextManager; use crate::context_helpers::{ContextConfig, TrackedMessage}; use crate::provider::ChatMessage; /// 上下文记忆层抽象接口 /// /// 覆盖 agentic loop / IPC 最常用的 15 个方法。 /// 保留 `ContextManager` 作为默认实现(`InMemoryAdapter`),行为零变化。 pub trait MemoryAdapter: Send + Sync { // ── 写入 ── fn push(&mut self, msg: ChatMessage); fn clear(&mut self); fn insert_at(&mut self, index: usize, message: ChatMessage); fn replace_tool_result_content(&mut self, tool_call_id: &str, new_content: &str) -> bool; fn pop_last_assistant_round(&mut self) -> bool; fn truncate_after_user_message(&mut self, target_content: &str) -> Result; fn replace_last_active_user_content(&mut self, new_content: &str) -> Result<(), ()>; // ── 读取 ── fn build_for_request(&self, sys_tokens: u32) -> (Vec, bool); fn all_messages_clone(&self) -> Vec; fn len(&self) -> usize; fn is_empty(&self) -> bool; fn history_tokens(&self) -> u32; fn budget_limit(&self) -> u32; fn config(&self) -> &ContextConfig; // ── 压缩 ── fn compress_old_messages(&mut self, end: usize) -> Vec; fn has_compressible_messages(&self, protect_start: usize) -> bool; fn is_compressing(&self) -> bool; fn set_compressing(&mut self, v: bool); // ── 生命周期 ── fn restore_from_messages(&mut self, messages: Vec); fn take_topic_marker(&mut self) -> Option; fn messages_mut(&mut self) -> &mut [TrackedMessage]; fn iter(&self) -> Box + '_>; } /// ContextManager 作为默认 MemoryAdapter 实现 impl MemoryAdapter for ContextManager { fn push(&mut self, msg: ChatMessage) { self.push(msg); } fn clear(&mut self) { self.clear(); } fn insert_at(&mut self, index: usize, message: ChatMessage) { self.insert_at(index, message); } fn replace_tool_result_content(&mut self, tool_call_id: &str, new_content: &str) -> bool { self.replace_tool_result_content(tool_call_id, new_content) } fn pop_last_assistant_round(&mut self) -> bool { self.pop_last_assistant_round() } fn truncate_after_user_message(&mut self, target_content: &str) -> Result { self.truncate_after_user_message(target_content) } fn replace_last_active_user_content(&mut self, new_content: &str) -> Result<(), ()> { self.replace_last_active_user_content(new_content) } fn build_for_request(&self, sys_tokens: u32) -> (Vec, bool) { self.build_for_request(sys_tokens) } fn all_messages_clone(&self) -> Vec { self.all_messages_clone() } fn len(&self) -> usize { self.len() } fn is_empty(&self) -> bool { self.is_empty() } fn history_tokens(&self) -> u32 { self.history_tokens() } fn budget_limit(&self) -> u32 { self.budget_limit() } fn config(&self) -> &ContextConfig { self.config() } fn compress_old_messages(&mut self, end: usize) -> Vec { self.compress_old_messages(end) } fn has_compressible_messages(&self, protect_start: usize) -> bool { self.has_compressible_messages(protect_start) } fn is_compressing(&self) -> bool { self.is_compressing() } fn set_compressing(&mut self, v: bool) { self.set_compressing(v); } fn restore_from_messages(&mut self, messages: Vec) { self.restore_from_messages(messages); } fn take_topic_marker(&mut self) -> Option { self.take_topic_marker() } fn messages_mut(&mut self) -> &mut [TrackedMessage] { self.messages_mut() } fn iter(&self) -> Box + '_> { Box::new(self.iter()) } }