Skip to content

Commit 89985e5

Browse files
committed
fix(tui): bound history loaded on resume
1 parent 4462b9d commit 89985e5

1 file changed

Lines changed: 73 additions & 1 deletion

File tree

‎codex-rs/tui/src/app_server_session.rs‎

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ use codex_app_server_protocol::ReviewTarget;
5050
use codex_app_server_protocol::SessionSource;
5151
use codex_app_server_protocol::SkillsListParams;
5252
use codex_app_server_protocol::SkillsListResponse;
53+
use codex_app_server_protocol::SortDirection;
5354
use codex_app_server_protocol::Thread;
5455
use codex_app_server_protocol::ThreadApproveGuardianDeniedActionParams;
5556
use codex_app_server_protocol::ThreadApproveGuardianDeniedActionResponse;
@@ -84,6 +85,7 @@ use codex_app_server_protocol::ThreadMetadataUpdateParams;
8485
use codex_app_server_protocol::ThreadMetadataUpdateResponse;
8586
use codex_app_server_protocol::ThreadReadParams;
8687
use codex_app_server_protocol::ThreadReadResponse;
88+
use codex_app_server_protocol::ThreadResumeInitialTurnsPageParams;
8789
use codex_app_server_protocol::ThreadResumeParams;
8890
use codex_app_server_protocol::ThreadResumeResponse;
8991
use codex_app_server_protocol::ThreadSetNameParams;
@@ -103,6 +105,7 @@ use codex_app_server_protocol::ThreadUnsubscribeResponse;
103105
use codex_app_server_protocol::Turn;
104106
use codex_app_server_protocol::TurnInterruptParams;
105107
use codex_app_server_protocol::TurnInterruptResponse;
108+
use codex_app_server_protocol::TurnItemsView;
106109
use codex_app_server_protocol::TurnStartParams;
107110
use codex_app_server_protocol::TurnStartResponse;
108111
use codex_app_server_protocol::TurnSteerParams;
@@ -138,6 +141,7 @@ const JSONRPC_INVALID_REQUEST: i64 = -32600;
138141
const JSONRPC_METHOD_NOT_FOUND: i64 = -32601;
139142
pub(crate) const EXTERNAL_AGENT_CONFIG_IMPORT_IN_PROGRESS_MESSAGE: &str = "A previous external agent import is still running. Wait for it to finish before importing again.";
140143
const THREAD_SETTINGS_UPDATE_METHOD: &str = "thread/settings/update";
144+
const TUI_RESUME_INITIAL_TURN_LIMIT: u32 = 100;
141145

142146
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
143147
pub(crate) enum ForkGoalContinuation {
@@ -1586,6 +1590,12 @@ fn thread_resume_params_from_config(
15861590
developer_instructions: with_terminal_visualization_instructions(
15871591
&config, /*control_instructions*/ None,
15881592
),
1593+
exclude_turns: true,
1594+
initial_turns_page: Some(ThreadResumeInitialTurnsPageParams {
1595+
limit: Some(TUI_RESUME_INITIAL_TURN_LIMIT),
1596+
sort_direction: Some(SortDirection::Desc),
1597+
items_view: Some(TurnItemsView::Summary),
1598+
}),
15891599
..ThreadResumeParams::default()
15901600
}
15911601
}
@@ -1669,9 +1679,15 @@ async fn started_thread_from_resume_response(
16691679
thread_session_state_from_thread_resume_response(&response, config, thread_params_mode)
16701680
.await
16711681
.map_err(color_eyre::eyre::Report::msg)?;
1682+
let turns = response
1683+
.initial_turns_page
1684+
.map_or(response.thread.turns, |mut page| {
1685+
page.data.reverse();
1686+
page.data
1687+
});
16721688
Ok(AppServerStartedThread {
16731689
session,
1674-
turns: response.thread.turns,
1690+
turns,
16751691
blocks_direct_input,
16761692
})
16771693
}
@@ -2382,6 +2398,30 @@ mod tests {
23822398
assert_eq!(fork.config, Some(expected_config));
23832399
}
23842400

2401+
#[tokio::test]
2402+
async fn thread_resume_params_request_bounded_summary_history() {
2403+
let temp_dir = tempfile::tempdir().expect("tempdir");
2404+
let config = build_config(&temp_dir).await;
2405+
2406+
let params = thread_resume_params_from_config(
2407+
config,
2408+
ThreadId::new(),
2409+
ThreadParamsMode::Embedded,
2410+
/*remote_cwd_override*/ None,
2411+
ResumeModelSettings::RestoreFromThread,
2412+
);
2413+
2414+
assert!(params.exclude_turns);
2415+
assert_eq!(
2416+
params.initial_turns_page,
2417+
Some(ThreadResumeInitialTurnsPageParams {
2418+
limit: Some(TUI_RESUME_INITIAL_TURN_LIMIT),
2419+
sort_direction: Some(SortDirection::Desc),
2420+
items_view: Some(TurnItemsView::Summary),
2421+
})
2422+
);
2423+
}
2424+
23852425
#[tokio::test]
23862426
async fn thread_resume_params_can_restore_persisted_model_settings() {
23872427
let temp_dir = tempfile::tempdir().expect("tempdir");
@@ -2786,6 +2826,38 @@ mod tests {
27862826
.expect("embedded resume response should map");
27872827
assert_eq!(started.session.permission_profile, read_only_profile);
27882828

2829+
let initial_page_turn = Turn {
2830+
id: "turn-2".to_string(),
2831+
items_view: TurnItemsView::Summary,
2832+
items: vec![codex_app_server_protocol::ThreadItem::AgentMessage {
2833+
id: "assistant-2".to_string(),
2834+
text: "latest assistant reply".to_string(),
2835+
phase: None,
2836+
memory_citation: None,
2837+
}],
2838+
status: TurnStatus::Completed,
2839+
error: None,
2840+
started_at: None,
2841+
completed_at: None,
2842+
duration_ms: None,
2843+
};
2844+
let mut initial_page_older_turn = initial_page_turn.clone();
2845+
initial_page_older_turn.id = "turn-1".to_string();
2846+
let mut paged_response = response.clone();
2847+
paged_response.initial_turns_page = Some(codex_app_server_protocol::TurnsPage {
2848+
data: vec![initial_page_turn.clone(), initial_page_older_turn.clone()],
2849+
next_cursor: None,
2850+
backwards_cursor: Some("older-turns".to_string()),
2851+
});
2852+
let started =
2853+
started_thread_from_resume_response(paged_response, &config, ThreadParamsMode::Remote)
2854+
.await
2855+
.expect("paged resume response should map");
2856+
assert_eq!(
2857+
started.turns,
2858+
vec![initial_page_older_turn, initial_page_turn]
2859+
);
2860+
27892861
let mut empty_roots_response = response;
27902862
empty_roots_response.runtime_workspace_roots = Vec::new();
27912863
let started = started_thread_from_resume_response(

0 commit comments

Comments
 (0)