Reuse current model context across paginated resume config loading (#56224)

## Why

Resuming a paginated thread rechecks stored history after loading configuration. Unchanged model context can be reused instead of loading it again.

## What changed

Retain the prepared model context across configuration loading and reuse it when the thread ID, rollout path, and history revision still match. Add `ThreadStore::is_model_context_current` to validate revisions, with a fresh read when validation fails or is unavailable.

## Testing

Add coverage for revision invalidation after history is appended or removed. Extend resume tests to cover paginated history, concurrent metadata and lifecycle changes, workspace-root changes, and preservation of saved user messages in model requests.

GitOrigin-RevId: bad2ca0caddb63523264ac530ffb801db3961f2b
This commit is contained in:
Charlie Marsh
2026-10-22 17:15:06 +00:00
committed by copyberry
parent 9cb547349e
commit ffda54f5b8
5 changed files with 207 additions and 21 deletions
+19
View File
@@ -616,6 +616,25 @@ impl ThreadStore for LocalThreadStore {
Box::pin(async move { model_context::load_latest_model_context(self, params).await })
}
fn is_model_context_current(
&self,
params: LoadThreadHistoryParams,
revision: String,
) -> ThreadStoreFuture<'_, bool> {
Box::pin(async move {
let resolved = if params.include_archived {
thread_rollout_resolver::resolve_current_including_archived(self, params.thread_id)
.await?
} else {
thread_rollout_resolver::resolve_current(self, params.thread_id).await?
};
let Some(resolved) = resolved else {
return Ok(false);
};
Ok(history_revision::read(&resolved.path).await.as_ref() == Some(&revision))
})
}
fn prepare_fork(&self, params: PrepareForkParams) -> ThreadStoreFuture<'_, PreparedFork> {
Box::pin(async move { paginated_fork::prepare(self, params).await })
}