Allow background persistence for steered user input (#45506)

## Why

Persisting user input received during an active turn currently blocks the next model request. Stores that support background persistence can overlap this checkpoint with inference.

## What changed

- Add `PersistContext::SteeredUserInput` and `allows_background_persistence()` so stores may enqueue these checkpoints, with durability and error reporting enforced by later flush or shutdown operations.
- Use the new context for accepted steered user input and apply the same metadata handling as turn-start persistence.
- Keep tool outputs synchronous, including in mixed input batches, and allow stores to retain synchronous persistence for all contexts.

## Testing

Add gated-store integration tests covering background user-input persistence, synchronous stores, and synchronous tool-output checkpoints. Verify that the next request includes the steered input and waits for persistence when required.

GitOrigin-RevId: c60b7b6c9b483245fd3169306bcf0de248ccdf35
This commit is contained in:
Bryan Ashley authored and copyberry committed 2026-09-14 19:39:31 +00:00
1 parent 4d5d37c5f8
commit b9bfc0aff8
6 files changed
+293 -7

No files matched your search

+11 -1
View File
@@ -341,9 +341,15 @@ pub struct TestCodexBuilder {
code_mode_host_program: Option<PathBuf>,
history_mode: Option<ThreadHistoryMode>,
models_manager: Option<SharedModelsManager>,
thread_store: Option<Arc<dyn ThreadStore>>,
}
impl TestCodexBuilder {
pub fn with_thread_store(mut self, thread_store: Arc<dyn ThreadStore>) -> Self {
self.thread_store = Some(thread_store);
self
}
pub fn with_config<T>(mut self, mutator: T) -> Self
where
T: FnOnce(&mut Config) + Send + 'static,
@@ -694,7 +700,10 @@ impl TestCodexBuilder {
) -> anyhow::Result<TestCodex> {
let auth = self.auth.clone();
let state_db = codex_core::init_state_db(&config).await;
let thread_store = thread_store_from_config(&config, state_db.clone());
let thread_store = self
.thread_store
.clone()
.unwrap_or_else(|| thread_store_from_config(&config, state_db.clone()));
let installation_id = resolve_installation_id(&config.codex_home).await?;
let user_instructions_provider =
self.user_instructions_provider.clone().unwrap_or_else(|| {
@@ -1387,6 +1396,7 @@ pub fn test_codex() -> TestCodexBuilder {
code_mode_host_program: None,
history_mode: None,
models_manager: None,
thread_store: None,
}
}