Paginate transcript history in the TUI (#36948)

## Why

Paginated threads should not require the TUI to load and render their entire
history when a session is resumed.

## What changed

- Hydrate a bounded initial history page for paginated resumes and forks,
  respecting the configured terminal reflow row budget.
- Load older transcript items in the background as users navigate upward, while
  preserving the viewport, live output, and backtrack selection.
- Reconcile review-mode prompts across page boundaries and keep restored token
  usage hidden until it can be attributed to a persisted turn.

## Testing

- Added coverage for paginated resume and fork hydration, older-page merging,
  transcript prepending, backtrack behavior, review prompt filtering, and token
  usage restoration.

GitOrigin-RevId: 42160b943a9f6a1ba0cfe4b195c24ddf410b747d
This commit is contained in:
Felipe Coury authored and copyberry committed 2026-08-04 18:59:32 +00:00
1 parent 989a0b053e
commit 8bfa49e350
26 files changed
+1360 -90

No files matched your search

+7
View File
@@ -564,6 +564,7 @@ pub(crate) struct ChatWidget {
runtime_model_provider_base_url: Option<String>,
pub(crate) remote_connection: Option<RemoteConnectionStatus>,
token_info: Option<TokenUsageInfo>,
token_usage_pending: bool,
rate_limit_snapshots_by_limit_id: BTreeMap<String, RateLimitSnapshotDisplay>,
refreshing_status_outputs: Vec<(u64, StatusHistoryHandle)>,
next_status_refresh_request_id: u64,
@@ -1144,6 +1145,9 @@ impl ChatWidget {
match info {
Some(info) => self.apply_token_info(info),
None => {
self.token_usage_pending = true;
self.bottom_pane
.set_context_window_pending(/*pending*/ true);
self.bottom_pane
.set_context_window(/*percent*/ None, /*used_tokens*/ None);
self.token_info = None;
@@ -1152,6 +1156,9 @@ impl ChatWidget {
}
fn apply_token_info(&mut self, info: TokenUsageInfo) {
self.token_usage_pending = false;
self.bottom_pane
.set_context_window_pending(/*pending*/ false);
let percent = self.context_remaining_percent(&info);
let used_tokens = self.context_used_tokens(&info, percent.is_some());
self.bottom_pane.set_context_window(percent, used_tokens);