@@ -50,6 +50,7 @@ use codex_app_server_protocol::ReviewTarget;
5050use codex_app_server_protocol:: SessionSource ;
5151use codex_app_server_protocol:: SkillsListParams ;
5252use codex_app_server_protocol:: SkillsListResponse ;
53+ use codex_app_server_protocol:: SortDirection ;
5354use codex_app_server_protocol:: Thread ;
5455use codex_app_server_protocol:: ThreadApproveGuardianDeniedActionParams ;
5556use codex_app_server_protocol:: ThreadApproveGuardianDeniedActionResponse ;
@@ -84,6 +85,7 @@ use codex_app_server_protocol::ThreadMetadataUpdateParams;
8485use codex_app_server_protocol:: ThreadMetadataUpdateResponse ;
8586use codex_app_server_protocol:: ThreadReadParams ;
8687use codex_app_server_protocol:: ThreadReadResponse ;
88+ use codex_app_server_protocol:: ThreadResumeInitialTurnsPageParams ;
8789use codex_app_server_protocol:: ThreadResumeParams ;
8890use codex_app_server_protocol:: ThreadResumeResponse ;
8991use codex_app_server_protocol:: ThreadSetNameParams ;
@@ -103,6 +105,7 @@ use codex_app_server_protocol::ThreadUnsubscribeResponse;
103105use codex_app_server_protocol:: Turn ;
104106use codex_app_server_protocol:: TurnInterruptParams ;
105107use codex_app_server_protocol:: TurnInterruptResponse ;
108+ use codex_app_server_protocol:: TurnItemsView ;
106109use codex_app_server_protocol:: TurnStartParams ;
107110use codex_app_server_protocol:: TurnStartResponse ;
108111use codex_app_server_protocol:: TurnSteerParams ;
@@ -138,6 +141,7 @@ const JSONRPC_INVALID_REQUEST: i64 = -32600;
138141const JSONRPC_METHOD_NOT_FOUND : i64 = -32601 ;
139142pub ( 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." ;
140143const 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 ) ]
143147pub ( 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