feat: Append the memory system prompts (readonly or r/w) to the system prompt when applicable

This commit is contained in:
2026-06-10 18:19:37 -06:00
parent 6d5cbfa56d
commit 4ece3d3df1
3 changed files with 271 additions and 8 deletions
+56 -7
View File
@@ -5,12 +5,7 @@ use super::skill_policy::SkillPolicy;
use super::skill_registry::SkillRegistry;
use super::todo::TodoList;
use super::tool_scope::{McpRuntime, ToolScope};
use super::{
AGENTS_DIR_NAME, Agent, AgentVariables, AppConfig, AppState, AssetCategory, CREATE_TITLE_ROLE,
Input, InstallFilter, LEFT_PROMPT, LastMessage, MESSAGES_FILE_NAME, RIGHT_PROMPT, Role,
RoleLike, SESSIONS_DIR_NAME, SUMMARIZATION_PROMPT, SUMMARY_CONTEXT_PROMPT, StateFlags,
TEMP_ROLE_NAME, TEMP_SESSION_NAME, WorkingMode, ensure_parent_exists, list_agents, paths,
};
use super::{AGENTS_DIR_NAME, Agent, AgentVariables, AppConfig, AppState, AssetCategory, CREATE_TITLE_ROLE, Input, InstallFilter, LEFT_PROMPT, LastMessage, MESSAGES_FILE_NAME, RIGHT_PROMPT, Role, RoleLike, SESSIONS_DIR_NAME, SUMMARIZATION_PROMPT, SUMMARY_CONTEXT_PROMPT, StateFlags, TEMP_ROLE_NAME, TEMP_SESSION_NAME, WorkingMode, ensure_parent_exists, list_agents, paths, memory};
use super::{MessageContentToolCalls, prompts};
use crate::client::{Model, ModelType, list_models};
use crate::function::{
@@ -46,7 +41,7 @@ use std::io::Write;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::{env, fs};
use super::memory::{WorkspaceMemory, MemoryStore};
use super::memory::{WorkspaceMemory, MemoryStore, DEFAULT_MEMORY_CAP_WITH_TOOLS, DEFAULT_MEMORY_CAP_WITHOUT_TOOLS};
pub struct AutoContinueConfig {
pub enabled: bool,
@@ -682,6 +677,35 @@ impl RequestContext {
}
}
if self.should_inject_memory()
&& let Some(cwd) = env::current_dir().ok()
{
let store = MemoryStore::new(&cwd);
let with_tools = self.should_register_memory_tools();
let cap = if with_tools {
app.memory_cap_with_tools
.unwrap_or(DEFAULT_MEMORY_CAP_WITH_TOOLS)
} else {
app.memory_cap_without_tools
.unwrap_or(DEFAULT_MEMORY_CAP_WITHOUT_TOOLS)
};
match memory::build_memory_section(&store, with_tools, cap) {
Ok(Some(section)) => {
let separator = if role.is_empty_prompt() { "" } else { "\n\n" };
role.append_to_prompt(separator);
role.append_to_prompt(&section);
role.append_to_prompt("\n\n");
role.append_to_prompt(if with_tools {
prompts::DEFAULT_MEMORY_INSTRUCTIONS
} else {
prompts::DEFAULT_MEMORY_INSTRUCTIONS_READONLY
});
}
Ok(None) => {}
Err(e) => warn!("memory injection failed: {}", e),
}
}
Ok(self.skill_registry.effective_role(&role, &policy))
}
@@ -3225,6 +3249,31 @@ mod tests {
assert!(!Arc::ptr_eq(&ctx.app.config, &previous));
}
#[test]
fn memory_config_app_some_false_disables_via_cascade() {
let mut ctx = create_test_ctx();
ctx.update_app_config(|app| app.memory = Some(false));
assert!(
!ctx.should_inject_memory(),
"AppConfig.memory=Some(false) must disable memory regardless of on-disk content (this is the --no-memory CLI path)"
);
}
#[test]
fn memory_config_role_false_beats_app_true_in_cascade() {
let mut ctx = create_test_ctx();
ctx.update_app_config(|app| app.memory = Some(true));
let role = Role::new("memory_off_role", "---\nmemory: false\n---\n");
assert_eq!(role.memory(), Some(false), "metadata parser sanity check");
ctx.role = Some(role);
assert!(
!ctx.should_inject_memory(),
"Role::memory=Some(false) must win over AppConfig::memory=Some(true)"
);
}
#[test]
fn use_role_obj_sets_role() {
let mut ctx = create_test_ctx();