fix(memory): filter autosave noise and scope recall/store by session (#3695)

* fix(memory): filter autosave noise and scope memory by session

* style: format rebase-resolved gateway and memory loader

* fix(tests): update memory loader mock for session-aware context

* fix(openai-codex): decode utf-8 safely across stream chunks
This commit is contained in:
Ericsunsk
2026-03-17 04:36:35 +08:00
committed by GitHub
parent dcb182cdd5
commit 83803cef5b
9 changed files with 349 additions and 49 deletions
+19 -5
View File
@@ -4,8 +4,12 @@ use std::fmt::Write;
#[async_trait]
pub trait MemoryLoader: Send + Sync {
async fn load_context(&self, memory: &dyn Memory, user_message: &str)
-> anyhow::Result<String>;
async fn load_context(
&self,
memory: &dyn Memory,
user_message: &str,
session_id: Option<&str>,
) -> anyhow::Result<String>;
}
pub struct DefaultMemoryLoader {
@@ -37,8 +41,9 @@ impl MemoryLoader for DefaultMemoryLoader {
&self,
memory: &dyn Memory,
user_message: &str,
session_id: Option<&str>,
) -> anyhow::Result<String> {
let entries = memory.recall(user_message, self.limit, None).await?;
let entries = memory.recall(user_message, self.limit, session_id).await?;
if entries.is_empty() {
return Ok(String::new());
}
@@ -48,6 +53,9 @@ impl MemoryLoader for DefaultMemoryLoader {
if memory::is_assistant_autosave_key(&entry.key) {
continue;
}
if memory::should_skip_autosave_content(&entry.content) {
continue;
}
if let Some(score) = entry.score {
if score < self.min_relevance_score {
continue;
@@ -191,7 +199,10 @@ mod tests {
#[tokio::test]
async fn default_loader_formats_context() {
let loader = DefaultMemoryLoader::default();
let context = loader.load_context(&MockMemory, "hello").await.unwrap();
let context = loader
.load_context(&MockMemory, "hello", None)
.await
.unwrap();
assert!(context.contains("[Memory context]"));
assert!(context.contains("- k: v"));
}
@@ -222,7 +233,10 @@ mod tests {
]),
};
let context = loader.load_context(&memory, "answer style").await.unwrap();
let context = loader
.load_context(&memory, "answer style", None)
.await
.unwrap();
assert!(context.contains("user_fact"));
assert!(!context.contains("assistant_resp_legacy"));
assert!(!context.contains("fabricated detail"));