Enable memories for paginated threads (#34386)

## Why

Paginated threads keep metadata updates in SQLite, while their rollout retains the initial `memory_mode`. Reconciliation could therefore overwrite the current setting with a stale value, and memory processing excluded these threads entirely.

## What changed

- Include paginated threads in stage 1 memory job selection and global memory output lookup.
- Preserve the SQLite `memory_mode` when reconciling or backfilling an existing paginated thread, while continuing to seed missing rows and restore legacy threads from rollouts.
- Omit `memory_mode` alongside Git metadata when flushing resumed paginated history.

## Testing

Added coverage for preserving disabled memory mode during reconciliation and backfill, selecting eligible paginated threads, and omitting initial metadata on paginated resume.

GitOrigin-RevId: 2a6e16068e69680728757fbec27aeefae45b8110
This commit is contained in:
Owen Lin authored and copyberry committed 2026-07-20 17:41:33 +00:00
1 parent 6f785632b0
commit 2793c826e8
6 files changed
+154 -29

No files matched your search

+53 -2
View File
@@ -10,6 +10,7 @@ use codex_protocol::protocol::EventMsg;
use codex_protocol::protocol::RolloutLine;
use codex_protocol::protocol::SessionMeta;
use codex_protocol::protocol::SessionMetaLine;
use codex_protocol::protocol::ThreadHistoryMode;
use codex_protocol::protocol::UserMessageEvent;
use pretty_assertions::assert_eq;
use std::path::Path;
@@ -111,7 +112,8 @@ async fn try_init_times_out_waiting_for_stuck_startup_backfill() -> anyhow::Resu
async fn reconcile_rollout_preserves_existing_explicit_title() -> anyhow::Result<()> {
let home = TempDir::new().expect("temp dir");
let thread_id = ThreadId::new();
let rollout_path = write_rollout_with_user_message(home.path(), thread_id, "Hey")?;
let rollout_path =
write_rollout_with_user_message(home.path(), thread_id, "Hey", ThreadHistoryMode::Legacy)?;
let runtime =
codex_state::StateRuntime::init(home.path().to_path_buf(), "test-provider".to_string())
.await?;
@@ -145,10 +147,59 @@ async fn reconcile_rollout_preserves_existing_explicit_title() -> anyhow::Result
Ok(())
}
#[tokio::test]
async fn reconcile_rollout_preserves_existing_paginated_memory_mode() -> anyhow::Result<()> {
let home = TempDir::new().expect("temp dir");
let thread_id = ThreadId::new();
let rollout_path = write_rollout_with_user_message(
home.path(),
thread_id,
"Hey",
ThreadHistoryMode::Paginated,
)?;
let runtime =
codex_state::StateRuntime::init(home.path().to_path_buf(), "test-provider".to_string())
.await?;
reconcile_rollout(
Some(runtime.as_ref()),
rollout_path.as_path(),
"test-provider",
/*builder*/ None,
&[],
/*archived_only*/ None,
/*new_thread_memory_mode*/ None,
)
.await;
assert!(
runtime
.set_thread_memory_mode(thread_id, "disabled")
.await?
);
reconcile_rollout(
Some(runtime.as_ref()),
rollout_path.as_path(),
"test-provider",
/*builder*/ None,
&[],
/*archived_only*/ None,
/*new_thread_memory_mode*/ None,
)
.await;
assert_eq!(
runtime.get_thread_memory_mode(thread_id).await?.as_deref(),
Some("disabled")
);
Ok(())
}
fn write_rollout_with_user_message(
home: &Path,
thread_id: ThreadId,
message: &str,
history_mode: ThreadHistoryMode,
) -> anyhow::Result<std::path::PathBuf> {
let dir = home.join("sessions/2026/06/01");
std::fs::create_dir_all(dir.as_path())?;
@@ -177,7 +228,7 @@ fn write_rollout_with_user_message(
dynamic_tools: None,
selected_capability_roots: Vec::new(),
memory_mode: None,
history_mode: Default::default(),
history_mode,
history_base: None,
subagent_history_start_ordinal: None,
multi_agent_version: None,