feat: memory read path (#11459)

This commit is contained in:
jif-oai
2026-02-11 18:22:45 +00:00
committed by GitHub
parent 0697d43aba
commit d4b2c230f1
4 changed files with 100 additions and 24 deletions
+8
View File
@@ -2295,6 +2295,14 @@ impl Session {
DeveloperInstructions::new(SEARCH_TOOL_DEVELOPER_INSTRUCTIONS.to_string()).into(),
);
}
// Add developer instructions for memories.
if let Some(memory_prompt) =
memories::build_memory_tool_developer_instructions(&turn_context.config.codex_home)
.await
&& turn_context.features.enabled(Feature::MemoryTool)
{
items.push(DeveloperInstructions::new(memory_prompt).into());
}
// Add developer instructions from collaboration_mode if they exist and are non-empty
let (collaboration_mode, base_instructions) = {
let state = self.state.lock().await;
+2 -1
View File
@@ -61,7 +61,7 @@ struct StageOneOutput {
_rollout_slug: Option<String>,
}
fn memory_root(codex_home: &Path) -> PathBuf {
pub fn memory_root(codex_home: &Path) -> PathBuf {
codex_home.join("memories")
}
@@ -77,6 +77,7 @@ async fn ensure_layout(root: &Path) -> std::io::Result<()> {
tokio::fs::create_dir_all(rollout_summaries_dir(root)).await
}
pub(crate) use prompts::build_memory_tool_developer_instructions;
/// Starts the memory startup pipeline for eligible root sessions.
///
/// This is the single entrypoint that `codex` uses to trigger memory startup.
+40 -23
View File
@@ -1,9 +1,10 @@
use askama::Template;
use std::path::Path;
use tracing::warn;
use super::text::prefix_at_char_boundary;
use super::text::suffix_at_char_boundary;
use crate::memories::memory_root;
use askama::Template;
use std::path::Path;
use tokio::fs;
use tracing::warn;
// TODO(jif) use proper truncation
const MAX_ROLLOUT_BYTES_FOR_PROMPT: usize = 100_000;
@@ -22,22 +23,24 @@ struct StageOneInputTemplate<'a> {
rollout_contents: &'a str,
}
#[derive(Template)]
#[template(path = "memory_tool/developer_instructions.md", escape = "none")]
struct MemoryToolDeveloperInstructionsTemplate<'a> {
base_path: &'a str,
memory_summary: &'a str,
}
/// Builds the consolidation subagent prompt for a specific memory root.
///
/// Falls back to a simple string replacement if Askama rendering fails.
pub(super) fn build_consolidation_prompt(memory_root: &Path) -> String {
let memory_root = memory_root.display().to_string();
let template = ConsolidationPromptTemplate {
memory_root: &memory_root,
};
match template.render() {
Ok(prompt) => prompt,
Err(err) => {
warn!("failed to render memories consolidation prompt template: {err}");
include_str!("../../templates/memories/consolidation.md")
.replace("{{ memory_root }}", &memory_root)
}
}
template.render().unwrap_or_else(|err| {
warn!("failed to render memories consolidation prompt template: {err}");
format!("## Memory Phase 2 (Consolidation)\nConsolidate Codex memories in: {memory_root}")
})
}
/// Builds the stage-1 user message containing rollout metadata and content.
@@ -65,17 +68,31 @@ pub(super) fn build_stage_one_input_message(
rollout_cwd: &rollout_cwd,
rollout_contents: &rollout_contents,
};
// TODO(jif) use askama
match template.render() {
Ok(prompt) => prompt,
Err(err) => {
warn!("failed to render memories stage-one input template: {err}");
include_str!("../../templates/memories/stage_one_input.md")
.replace("{{ rollout_path }}", &rollout_path)
.replace("{{ rollout_cwd }}", &rollout_cwd)
.replace("{{ rollout_contents }}", &rollout_contents)
}
template.render().unwrap_or_else(|err| {
warn!("failed to render memories stage-one input template: {err}");
format!(
"Analyze this rollout and produce JSON with `raw_memory`, `rollout_summary`, and optional `rollout_slug`.\n\nrollout_context:\n- rollout_path: {rollout_path}\n- rollout_cwd: {rollout_cwd}\n\nrendered conversation:\n{rollout_contents}"
)
})
}
pub(crate) async fn build_memory_tool_developer_instructions(codex_home: &Path) -> Option<String> {
let base_path = memory_root(codex_home);
let memory_summary_path = base_path.join("memory_summary.md");
let memory_summary = fs::read_to_string(&memory_summary_path)
.await
.ok()?
.trim()
.to_string();
if memory_summary.is_empty() {
return None;
}
let base_path = base_path.display().to_string();
let template = MemoryToolDeveloperInstructionsTemplate {
base_path: &base_path,
memory_summary: &memory_summary,
};
template.render().ok()
}
fn truncate_rollout_for_prompt(input: &str) -> (String, bool) {