From c7234c1174b27d9c55199fba0d546dc27d1b0415 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Wed, 21 Oct 2026 02:34:07 +0000 Subject: [PATCH] Box session metadata and compaction payloads in `RolloutItem` (#55733) ## What changed Store `RolloutItem::SessionMeta` and `RolloutItem::Compacted` payloads in `Box` values and update their producers, consumers, and test fixtures. Preserve the existing serialized rollout format. GitOrigin-RevId: 59fcc4beb47d23160872dcb6e95ace9b142d3d11 --- .../src/protocol/thread_history.rs | 4 +- .../thread_history_projection_tests.rs | 4 +- .../request_processors/feedback_processor.rs | 4 +- .../thread_processor_tests.rs | 12 +-- .../app-server/tests/suite/v2/thread_fork.rs | 6 +- .../app-server/tests/suite/v2/thread_list.rs | 10 ++- .../tests/suite/v2/thread_resume.rs | 13 +-- codex-rs/cli/src/doctor/thread_inventory.rs | 28 ++++--- codex-rs/core/src/agent/control_tests.rs | 16 ++-- .../core/src/session/guardian_checkpoint.rs | 4 +- codex-rs/core/src/session/mod.rs | 2 +- .../session/rollout_reconstruction_tests.rs | 80 +++++++++---------- codex-rs/core/src/session/tests.rs | 34 ++++---- codex-rs/core/src/thread_manager_tests.rs | 8 +- .../mcp_attribution_tests.rs | 6 +- .../request_metadata_tests.rs | 4 +- codex-rs/core/tests/suite/client.rs | 12 +-- codex-rs/core/tests/suite/fork_thread.rs | 2 +- .../tests/suite/guardian_authorization.rs | 14 ++-- .../suite/guardian_authorization_refresh.rs | 14 ++-- .../core/tests/suite/guardian_root_handoff.rs | 2 +- .../suite/guardian_subagent_authorization.rs | 4 +- .../suite/mcp_storage_telemetry_tests.rs | 4 +- .../remote_env_capability_roots_tests.rs | 4 +- codex-rs/core/tests/suite/sqlite_state.rs | 2 +- codex-rs/history/src/lib.rs | 4 +- codex-rs/history/src/rollout_payload.rs | 8 +- codex-rs/history/src/tests.rs | 15 ++-- codex-rs/rollout/src/compression_tests.rs | 2 +- codex-rs/rollout/src/list.rs | 2 +- codex-rs/rollout/src/metadata_tests.rs | 22 ++--- codex-rs/rollout/src/recorder.rs | 2 +- codex-rs/rollout/src/recorder_tests.rs | 6 +- codex-rs/rollout/src/session_index_tests.rs | 4 +- codex-rs/rollout/src/state_db_tests.rs | 4 +- codex-rs/rollout/src/tests.rs | 4 +- codex-rs/state/src/extract.rs | 12 +-- codex-rs/state/src/runtime/threads.rs | 8 +- codex-rs/thread-store/src/in_memory.rs | 4 +- .../src/local/compression_writer_tests.rs | 4 +- .../thread-store/src/local/model_context.rs | 4 +- .../src/local/model_context_tests.rs | 18 ++--- .../src/local/read_thread_tests.rs | 4 +- .../src/local/rollout_lineage_tests.rs | 4 +- .../local/rollout_migration/rollback_plan.rs | 4 +- .../local/rollout_migration/startup_tests.rs | 4 +- .../src/local/rollout_migration_tests.rs | 20 ++--- .../src/local/thread_history/read_tests.rs | 4 +- .../src/local/update_thread_metadata.rs | 4 +- .../thread-store/src/thread_metadata_sync.rs | 10 +-- codex-rs/thread-store/src/types.rs | 4 +- .../resume_picker_transcript_preview_tests.rs | 12 +-- 52 files changed, 254 insertions(+), 232 deletions(-) diff --git a/codex-rs/app-server-protocol/src/protocol/thread_history.rs b/codex-rs/app-server-protocol/src/protocol/thread_history.rs index 8fb3a38f5d..418a9fb1bb 100644 --- a/codex-rs/app-server-protocol/src/protocol/thread_history.rs +++ b/codex-rs/app-server-protocol/src/protocol/thread_history.rs @@ -4602,7 +4602,7 @@ mod tests { model_context_window: None, collaboration_mode_kind: Default::default(), })), - RolloutItem::Compacted(CompactedItem { + RolloutItem::Compacted(Box::new(CompactedItem { message: String::new(), replacement_history: None, retained_context: None, @@ -4615,7 +4615,7 @@ mod tests { compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }), + })), RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent { root_turn_id: None, turn_id: "turn-compact".into(), diff --git a/codex-rs/app-server-protocol/src/protocol/thread_history_projection_tests.rs b/codex-rs/app-server-protocol/src/protocol/thread_history_projection_tests.rs index 6afb4411ee..a2ca09c6b7 100644 --- a/codex-rs/app-server-protocol/src/protocol/thread_history_projection_tests.rs +++ b/codex-rs/app-server-protocol/src/protocol/thread_history_projection_tests.rs @@ -210,7 +210,7 @@ fn ignores_legacy_abort_without_turn_id_and_context_only_records() { duration_ms: None, }, ))); - let compacted = project(RolloutItem::Compacted(CompactedItem { + let compacted = project(RolloutItem::Compacted(Box::new(CompactedItem { message: String::new(), replacement_history: None, retained_context: None, @@ -223,7 +223,7 @@ fn ignores_legacy_abort_without_turn_id_and_context_only_records() { compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - })); + }))); let security_risk = project(RolloutItem::SecurityRiskScore(SecurityRiskScore { scores: BTreeMap::from([("action_risk".to_string(), 0.92)]), call_id: None, diff --git a/codex-rs/app-server/src/request_processors/feedback_processor.rs b/codex-rs/app-server/src/request_processors/feedback_processor.rs index f3f2071973..1cc789a18c 100644 --- a/codex-rs/app-server/src/request_processors/feedback_processor.rs +++ b/codex-rs/app-server/src/request_processors/feedback_processor.rs @@ -742,7 +742,7 @@ mod tests { let mut lines = vec![RolloutLine { timestamp: "2026-07-24T00:00:00Z".to_string(), ordinal: None, - item: RolloutItem::SessionMeta(SessionMetaLine { + item: RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: codex_protocol::protocol::SessionMeta { cwd: tempdir.path().to_path_buf(), base_instructions: Some(codex_protocol::models::BaseInstructions { @@ -752,7 +752,7 @@ mod tests { ..Default::default() }, git: None, - }), + })), }]; lines.extend(turns.iter().map(|(turn_id, model, effort)| { RolloutLine { diff --git a/codex-rs/app-server/src/request_processors/thread_processor_tests.rs b/codex-rs/app-server/src/request_processors/thread_processor_tests.rs index a42e06dc9d..166142ffdf 100644 --- a/codex-rs/app-server/src/request_processors/thread_processor_tests.rs +++ b/codex-rs/app-server/src/request_processors/thread_processor_tests.rs @@ -989,10 +989,10 @@ mod thread_processor_behavior_tests { let line = RolloutLine { timestamp: timestamp.clone(), ordinal: None, - item: RolloutItem::SessionMeta(SessionMetaLine { + item: RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: session_meta.clone(), git: None, - }), + })), }; fs::write(&path, format!("{}\n", serde_json::to_string(&line)?))?; @@ -1057,10 +1057,10 @@ mod thread_processor_behavior_tests { let line = RolloutLine { timestamp, ordinal: None, - item: RolloutItem::SessionMeta(SessionMetaLine { + item: RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: session_meta, git: None, - }), + })), }; fs::write(&path, format!("{}\n", serde_json::to_string(&line)?))?; @@ -1100,10 +1100,10 @@ mod thread_processor_behavior_tests { let line = RolloutLine { timestamp, ordinal: None, - item: RolloutItem::SessionMeta(SessionMetaLine { + item: RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: session_meta, git: None, - }), + })), }; fs::write(&path, format!("{}\n", serde_json::to_string(&line)?))?; diff --git a/codex-rs/app-server/tests/suite/v2/thread_fork.rs b/codex-rs/app-server/tests/suite/v2/thread_fork.rs index 046111e8c7..980e8d1f70 100644 --- a/codex-rs/app-server/tests/suite/v2/thread_fork.rs +++ b/codex-rs/app-server/tests/suite/v2/thread_fork.rs @@ -173,7 +173,11 @@ async fn thread_fork_creates_new_thread_and_emits_started() -> Result<()> { ); let mut session_meta = read_session_meta_line(&original_path).await?; session_meta.meta.multi_agent_version = Some(MultiAgentVersion::V1); - append_rollout_item_to_path(&original_path, &RolloutItem::SessionMeta(session_meta)).await?; + append_rollout_item_to_path( + &original_path, + &RolloutItem::SessionMeta(Box::new(session_meta)), + ) + .await?; let original_contents = std::fs::read_to_string(&original_path)?; let mut mcp = TestAppServer::builder() diff --git a/codex-rs/app-server/tests/suite/v2/thread_list.rs b/codex-rs/app-server/tests/suite/v2/thread_list.rs index f697f9e141..0a4ad00dab 100644 --- a/codex-rs/app-server/tests/suite/v2/thread_list.rs +++ b/codex-rs/app-server/tests/suite/v2/thread_list.rs @@ -1678,8 +1678,11 @@ async fn thread_list_reports_loaded_subagent_direct_input_capability() -> Result let parent_rollout_path = rollout_path(codex_home.path(), "2025-02-01T09-00-00", &cli_id); let mut parent_meta = read_session_meta_line(&parent_rollout_path).await?; parent_meta.meta.multi_agent_version = Some(MultiAgentVersion::V2); - append_rollout_item_to_path(&parent_rollout_path, &RolloutItem::SessionMeta(parent_meta)) - .await?; + append_rollout_item_to_path( + &parent_rollout_path, + &RolloutItem::SessionMeta(Box::new(parent_meta)), + ) + .await?; // Legacy children resume before the root restores the V2 registry from persisted spawn edges. let mut expected = vec![(cli_id.clone(), None, false)]; let mut threads_to_resume = vec![(cli_id.clone(), SessionSource::Cli, Some(true))]; @@ -1736,7 +1739,8 @@ async fn thread_list_reports_loaded_subagent_direct_input_capability() -> Result let source = SessionSource::from(session_meta.meta.source.clone()); if let Some(version) = version { session_meta.meta.multi_agent_version = Some(version); - append_rollout_item_to_path(&path, &RolloutItem::SessionMeta(session_meta)).await?; + append_rollout_item_to_path(&path, &RolloutItem::SessionMeta(Box::new(session_meta))) + .await?; } if should_resume { let resume = (thread_id.clone(), source, capability); diff --git a/codex-rs/app-server/tests/suite/v2/thread_resume.rs b/codex-rs/app-server/tests/suite/v2/thread_resume.rs index c34a453e6c..e183b147fb 100644 --- a/codex-rs/app-server/tests/suite/v2/thread_resume.rs +++ b/codex-rs/app-server/tests/suite/v2/thread_resume.rs @@ -195,7 +195,7 @@ async fn thread_resume_paginated_model_context_preserves_original_metadata() -> }))?; append_rollout_item_to_path( &path, - &RolloutItem::Compacted(CompactedItem { + &RolloutItem::Compacted(Box::new(CompactedItem { message: "compacted history".to_string(), replacement_history: Some(Vec::new()), retained_context: None, @@ -208,7 +208,7 @@ async fn thread_resume_paginated_model_context_preserves_original_metadata() -> compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }), + })), ) .await?; append_rollout_item_to_path( @@ -2158,7 +2158,7 @@ async fn unloaded_thread_goal_mutations_respect_parent_ownership() -> Result<()> // must take precedence, just as it does when the thread resumes. let mut meta = read_session_meta_line(&path).await?; meta.meta.multi_agent_version = version; - append_rollout_item_to_path(&path, &RolloutItem::SessionMeta(meta)).await?; + append_rollout_item_to_path(&path, &RolloutItem::SessionMeta(Box::new(meta))).await?; for (method, params) in [ ( @@ -6487,8 +6487,11 @@ async fn setup_rollout_fixture(codex_home: &Path, server_uri: &str) -> Result vec![ RolloutItem::WorldState(WorldStateItem::full(object!({}))), - RolloutItem::Compacted(CompactedItem { + RolloutItem::Compacted(Box::new(CompactedItem { message: String::new(), replacement_history: Some(Vec::new()), retained_context: None, @@ -1384,7 +1384,7 @@ async fn record_initial_history_requires_surviving_full_snapshot_without_user_tu compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }), + })), ], }; rollout_items.push(RolloutItem::TurnContext( @@ -1409,7 +1409,7 @@ async fn record_initial_history_resumed_does_not_seed_reference_context_item_aft let previous_context_item = turn_context.to_turn_context_item(); let rollout_items = vec![ RolloutItem::TurnContext(previous_context_item), - RolloutItem::Compacted(CompactedItem { + RolloutItem::Compacted(Box::new(CompactedItem { message: String::new(), replacement_history: Some(Vec::new()), retained_context: None, @@ -1422,7 +1422,7 @@ async fn record_initial_history_resumed_does_not_seed_reference_context_item_aft compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }), + })), ]; session @@ -1443,7 +1443,7 @@ async fn reconstruct_history_restores_initial_window_from_session_meta() { let (session, turn_context) = make_session_and_context().await; let thread_id = ThreadId::default(); let initial_window_id = Uuid::now_v7(); - let rollout_items = vec![RolloutItem::SessionMeta(SessionMetaLine { + let rollout_items = vec![RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { session_id: thread_id.into(), id: thread_id, @@ -1453,7 +1453,7 @@ async fn reconstruct_history_restores_initial_window_from_session_meta() { ..SessionMeta::default() }, git: None, - })]; + }))]; let reconstructed = session .reconstruct_history_from_rollout(&turn_context, &rollout_items) @@ -1474,7 +1474,7 @@ async fn reconstruct_history_prefers_compacted_window_over_session_meta() { let compacted_previous_window_id = Uuid::now_v7(); let compacted_window_id = Uuid::now_v7(); let rollout_items = vec![ - RolloutItem::SessionMeta(SessionMetaLine { + RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { session_id: thread_id.into(), id: thread_id, @@ -1484,8 +1484,8 @@ async fn reconstruct_history_prefers_compacted_window_over_session_meta() { ..SessionMeta::default() }, git: None, - }), - RolloutItem::Compacted(CompactedItem { + })), + RolloutItem::Compacted(Box::new(CompactedItem { message: String::new(), replacement_history: Some(Vec::new()), retained_context: None, @@ -1498,7 +1498,7 @@ async fn reconstruct_history_prefers_compacted_window_over_session_meta() { compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }), + })), ]; let reconstructed = session @@ -1526,7 +1526,7 @@ async fn reconstruct_history_replays_world_state_from_latest_compaction_window() RolloutItem::WorldState(WorldStateItem::full(object!({ "environment": {"status": "old"} }))), - RolloutItem::Compacted(CompactedItem { + RolloutItem::Compacted(Box::new(CompactedItem { message: String::new(), replacement_history: Some(Vec::new()), retained_context: None, @@ -1539,7 +1539,7 @@ async fn reconstruct_history_replays_world_state_from_latest_compaction_window() compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }), + })), RolloutItem::WorldState(WorldStateItem::full(object!({ "environment": {"status": "starting", "cwd": "/workspace"} }))), @@ -1584,7 +1584,7 @@ async fn bounded_replay_matches_full_replay_after_empty_turn_compactions( git: None, }; let initial_context = turn_context.to_turn_context_item(); - let mut rollout_items = vec![RolloutItem::SessionMeta(session_meta.clone())]; + let mut rollout_items = vec![RolloutItem::SessionMeta(Box::new(session_meta.clone()))]; rollout_items.extend(completed_user_turn_rollout( initial_context.clone(), vec![RolloutItem::ResponseItem( @@ -1603,7 +1603,7 @@ async fn bounded_replay_matches_full_replay_after_empty_turn_compactions( let mut wake_items = completed_user_turn_rollout( context.clone(), vec![ - RolloutItem::Compacted(CompactedItem { + RolloutItem::Compacted(Box::new(CompactedItem { message: String::new(), replacement_history: Some(annotated(vec![object!({ "type": "compaction", @@ -1632,7 +1632,7 @@ async fn bounded_replay_matches_full_replay_after_empty_turn_compactions( realtime_active: Some(false), }), }), - }), + })), RolloutItem::WorldState(WorldStateItem::full(object!({ "environment": {"window": window_number, "status": "starting"} }))), @@ -1679,7 +1679,7 @@ async fn bounded_replay_matches_full_replay_after_empty_turn_compactions( }); assert_eq!(cutoff, Some(latest_compaction_index)); let mut bounded_items = scan.finish(); - bounded_items.insert(0, RolloutItem::SessionMeta(session_meta)); + bounded_items.insert(0, RolloutItem::SessionMeta(Box::new(session_meta))); let full = session .reconstruct_history_from_rollout(&turn_context, &rollout_items) .await; @@ -1723,7 +1723,7 @@ async fn paginated_compaction_does_not_restore_missing_companions_from_older_his let rollout_items = vec![ RolloutItem::TurnContext(turn_context.to_turn_context_item()), RolloutItem::WorldState(WorldStateItem::full(object!({"older": true}))), - RolloutItem::Compacted(compacted), + RolloutItem::Compacted(Box::new(compacted)), ]; let reconstructed = session @@ -1819,7 +1819,7 @@ async fn reconstruct_attribution_ignores_previous_terminal_after_checkpoint( .pop() .expect("previous turn completion"); let mut rollout = vec![ - RolloutItem::Compacted(object!({ + RolloutItem::Compacted(Box::new(object!({ "message": "summary", "replacement_history": [user_message("original work")], "window_number": 1, @@ -1828,7 +1828,7 @@ async fn reconstruct_attribution_ignores_previous_terminal_after_checkpoint( "turn_attribution": expected, "previous_turn_settings": settings } - })), + }))), RolloutItem::ResponseItem(user_message("continued work").into()), RolloutItem::TurnContext(context.clone()), late_terminal, @@ -1880,7 +1880,7 @@ async fn completed_turn_suffix_after_compaction_overrides_resume_metadata( realtime_active: newer_context.realtime_active, }; let mut rollout_items = vec![ - RolloutItem::Compacted(object!({ + RolloutItem::Compacted(Box::new(object!({ "message": "summary", "replacement_history": [user_message("seed"), assistant_message("summary")], "window_number": 1, @@ -1892,7 +1892,7 @@ async fn completed_turn_suffix_after_compaction_overrides_resume_metadata( "comp_hash": "metadata-hash" } } - })), + }))), RolloutItem::WorldState(WorldStateItem::full(object!({}))), ]; // The bounded suffix starts at the compaction, so the turn start and user input are already in @@ -1959,7 +1959,7 @@ async fn reconstruct_history_preserves_legacy_compaction_count_with_session_meta let thread_id = ThreadId::default(); let initial_window_id = Uuid::now_v7(); let rollout_items = vec![ - RolloutItem::SessionMeta(SessionMetaLine { + RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { session_id: thread_id.into(), id: thread_id, @@ -1969,8 +1969,8 @@ async fn reconstruct_history_preserves_legacy_compaction_count_with_session_meta ..SessionMeta::default() }, git: None, - }), - RolloutItem::Compacted(CompactedItem { + })), + RolloutItem::Compacted(Box::new(CompactedItem { message: "legacy summary".to_string(), replacement_history: None, retained_context: None, @@ -1983,7 +1983,7 @@ async fn reconstruct_history_preserves_legacy_compaction_count_with_session_meta compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }), + })), ]; let reconstructed = session @@ -2028,7 +2028,7 @@ async fn reconstruct_history_legacy_compaction_without_replacement_history_does_ RolloutItem::ResponseItem(user_message("before compact").into()), RolloutItem::ResponseItem(assistant_message("assistant reply").into()), RolloutItem::RetainedContext(answer), - RolloutItem::Compacted(CompactedItem { + RolloutItem::Compacted(Box::new(CompactedItem { message: "legacy summary".to_string(), replacement_history: None, retained_context: None, @@ -2041,7 +2041,7 @@ async fn reconstruct_history_legacy_compaction_without_replacement_history_does_ compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }), + })), ]; let reconstructed = session @@ -2070,7 +2070,7 @@ async fn reconstruct_history_legacy_compaction_without_replacement_history_clear .expect("turn context should have turn_id"); let rollout_items = vec![ RolloutItem::ResponseItem(user_message("before compact").into()), - RolloutItem::Compacted(CompactedItem { + RolloutItem::Compacted(Box::new(CompactedItem { message: "legacy summary".to_string(), replacement_history: None, retained_context: None, @@ -2083,7 +2083,7 @@ async fn reconstruct_history_legacy_compaction_without_replacement_history_clear compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }), + })), RolloutItem::EventMsg(EventMsg::TurnStarted( codex_protocol::protocol::TurnStartedEvent { turn_attribution: None, @@ -2180,7 +2180,7 @@ async fn record_initial_history_resumed_turn_context_after_compaction_reestablis }, )), // Compaction clears baseline until a later TurnContextItem re-establishes it. - RolloutItem::Compacted(CompactedItem { + RolloutItem::Compacted(Box::new(CompactedItem { message: String::new(), replacement_history: Some(Vec::new()), retained_context: None, @@ -2193,7 +2193,7 @@ async fn record_initial_history_resumed_turn_context_after_compaction_reestablis compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }), + })), RolloutItem::TurnContext(previous_context_item), RolloutItem::EventMsg(EventMsg::TurnComplete( codex_protocol::protocol::TurnCompleteEvent { @@ -2354,7 +2354,7 @@ async fn record_initial_history_resumed_aborted_turn_without_id_clears_active_tu duration_ms: None, }, )), - RolloutItem::Compacted(CompactedItem { + RolloutItem::Compacted(Box::new(CompactedItem { message: String::new(), replacement_history: Some(Vec::new()), retained_context: None, @@ -2367,7 +2367,7 @@ async fn record_initial_history_resumed_aborted_turn_without_id_clears_active_tu compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }), + })), ]; session @@ -2621,7 +2621,7 @@ async fn record_initial_history_resumed_trailing_incomplete_turn_compaction_clea ..Default::default() }, )), - RolloutItem::Compacted(CompactedItem { + RolloutItem::Compacted(Box::new(CompactedItem { message: String::new(), replacement_history: Some(Vec::new()), retained_context: None, @@ -2634,7 +2634,7 @@ async fn record_initial_history_resumed_trailing_incomplete_turn_compaction_clea compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }), + })), ]; session @@ -2807,7 +2807,7 @@ async fn record_initial_history_resumed_replaced_incomplete_compacted_turn_clear ..Default::default() }, )), - RolloutItem::Compacted(CompactedItem { + RolloutItem::Compacted(Box::new(CompactedItem { message: String::new(), replacement_history: Some(Vec::new()), retained_context: None, @@ -2820,7 +2820,7 @@ async fn record_initial_history_resumed_replaced_incomplete_compacted_turn_clear compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }), + })), // A newer TurnStarted replaces the incomplete compacted turn without a matching // completion/abort for the old one. RolloutItem::EventMsg(EventMsg::TurnStarted( diff --git a/codex-rs/core/src/session/tests.rs b/codex-rs/core/src/session/tests.rs index 30a7216428..8446df3831 100644 --- a/codex-rs/core/src/session/tests.rs +++ b/codex-rs/core/src/session/tests.rs @@ -2469,7 +2469,7 @@ async fn reconstruct_history_uses_replacement_history_verbatim() { let first_window_id = Uuid::now_v7(); let previous_window_id = Uuid::now_v7(); let window_id = Uuid::now_v7(); - let rollout_items = vec![RolloutItem::Compacted(CompactedItem { + let rollout_items = vec![RolloutItem::Compacted(Box::new(CompactedItem { message: String::new(), replacement_history: Some(replacement_history.clone()), retained_context: None, @@ -2482,7 +2482,7 @@ async fn reconstruct_history_uses_replacement_history_verbatim() { compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - })]; + }))]; let reconstructed = session .reconstruct_history_from_rollout(&turn_context, &rollout_items) @@ -2749,7 +2749,7 @@ async fn inter_agent_communication_waits_for_confirmed_delivery_persistence() { compacted.retained_context = Some(live.retained_context().clone()); let mut history = resumed.history.as_ref().clone(); history.extend([ - RolloutItem::Compacted(compacted), + RolloutItem::Compacted(Box::new(compacted)), RolloutItem::EventMsg(EventMsg::ThreadRolledBack( codex_protocol::protocol::ThreadRolledBackEvent { num_turns: 1 }, )), @@ -3280,7 +3280,7 @@ fn session_meta_item( thread_id: ThreadId, multi_agent_version: Option, ) -> RolloutItem { - RolloutItem::SessionMeta(SessionMetaLine { + RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { session_id: thread_id.into(), id: thread_id, @@ -3288,7 +3288,7 @@ fn session_meta_item( ..SessionMeta::default() }, git: None, - }) + })) } #[tokio::test] @@ -3435,7 +3435,7 @@ fn latest_token_usage_record_stops_at_compaction_checkpoint() { thread_token_usage: TokenUsage::default(), }; let checkpoint = |latest_token_usage_record| { - RolloutItem::Compacted(CompactedItem { + RolloutItem::Compacted(Box::new(CompactedItem { message: String::new(), replacement_history: None, retained_context: None, @@ -3448,7 +3448,7 @@ fn latest_token_usage_record_stops_at_compaction_checkpoint() { compaction_response_id: None, latest_token_usage_record, resume_metadata: None, - }) + })) }; assert_eq!( @@ -7409,7 +7409,7 @@ async fn resumed_subagent_session_restores_persisted_session_id() { InitialHistory::Resumed(ResumedHistory { history_revision: None, conversation_id: thread_id, - history: Arc::new(vec![RolloutItem::SessionMeta(SessionMetaLine { + history: Arc::new(vec![RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { session_id: parent_session_id, id: thread_id, @@ -7417,7 +7417,7 @@ async fn resumed_subagent_session_restores_persisted_session_id() { ..SessionMeta::default() }, git: None, - })]), + }))]), rollout_path: None, }), session_source, @@ -7443,7 +7443,7 @@ async fn resumed_copied_fork_ignores_source_history_base() { let parent_thread_id = ThreadId::new(); let thread_id = ThreadId::new(); let history = vec![ - RolloutItem::SessionMeta(SessionMetaLine { + RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { id: thread_id, session_id: SessionId::from(thread_id), @@ -7451,8 +7451,8 @@ async fn resumed_copied_fork_ignores_source_history_base() { ..SessionMeta::default() }, git: None, - }), - RolloutItem::SessionMeta(SessionMetaLine { + })), + RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { id: parent_thread_id, session_id: SessionId::from(parent_thread_id), @@ -7465,7 +7465,7 @@ async fn resumed_copied_fork_ignores_source_history_base() { ..SessionMeta::default() }, git: None, - }), + })), ]; let (session, _rx_event) = make_session_with_history_source_and_agent_control_and_rx( InitialHistory::Resumed(ResumedHistory { @@ -13279,7 +13279,7 @@ async fn sample_rollout( let rebuilt1 = compact::build_compacted_history(Vec::new(), &user_messages1, summary1); live_history.replace_annotated(rebuilt1); let (window_number, window_ids) = session.advance_auto_compact_window().await; - rollout_items.push(RolloutItem::Compacted(CompactedItem { + rollout_items.push(RolloutItem::Compacted(Box::new(CompactedItem { message: summary1.to_string(), replacement_history: None, retained_context: None, @@ -13292,7 +13292,7 @@ async fn sample_rollout( compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - })); + }))); let user2 = user_message("second user"); live_history.record_items( @@ -13314,7 +13314,7 @@ async fn sample_rollout( let rebuilt2 = compact::build_compacted_history(Vec::new(), &user_messages2, summary2); live_history.replace_annotated(rebuilt2); let (window_number, window_ids) = session.advance_auto_compact_window().await; - rollout_items.push(RolloutItem::Compacted(CompactedItem { + rollout_items.push(RolloutItem::Compacted(Box::new(CompactedItem { message: summary2.to_string(), replacement_history: None, retained_context: None, @@ -13327,7 +13327,7 @@ async fn sample_rollout( compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - })); + }))); let user3 = user_message("third user"); live_history.record_items( diff --git a/codex-rs/core/src/thread_manager_tests.rs b/codex-rs/core/src/thread_manager_tests.rs index e740707349..9578c92459 100644 --- a/codex-rs/core/src/thread_manager_tests.rs +++ b/codex-rs/core/src/thread_manager_tests.rs @@ -2022,7 +2022,7 @@ async fn selected_capability_roots_round_trip_through_fork() { }]; let inherited = manager .start_thread(StartThreadOptions { - initial_history: InitialHistory::Forked(vec![RolloutItem::SessionMeta( + initial_history: InitialHistory::Forked(vec![RolloutItem::SessionMeta(Box::new( SessionMetaLine { meta: SessionMeta { selected_capability_roots: selected_roots.clone(), @@ -2030,7 +2030,7 @@ async fn selected_capability_roots_round_trip_through_fork() { }, git: None, }, - )]), + ))]), environments: Some(Vec::new()), ..StartThreadOptions::new(config) }) @@ -2117,7 +2117,7 @@ async fn selected_capability_roots_respect_startup_precedence_and_isolation() { } let child = manager .start_thread(StartThreadOptions { - initial_history: InitialHistory::Forked(vec![RolloutItem::SessionMeta( + initial_history: InitialHistory::Forked(vec![RolloutItem::SessionMeta(Box::new( SessionMetaLine { meta: SessionMeta { selected_capability_roots: vec![root("saved")], @@ -2125,7 +2125,7 @@ async fn selected_capability_roots_respect_startup_precedence_and_isolation() { }, git: None, }, - )]), + ))]), inherited_environments: Some(parent_environments.clone()), thread_extension_init, ..StartThreadOptions::new(config.clone()) diff --git a/codex-rs/core/src/tools/executed_tool_calls/mcp_attribution_tests.rs b/codex-rs/core/src/tools/executed_tool_calls/mcp_attribution_tests.rs index 9085d18a43..054f05385f 100644 --- a/codex-rs/core/src/tools/executed_tool_calls/mcp_attribution_tests.rs +++ b/codex-rs/core/src/tools/executed_tool_calls/mcp_attribution_tests.rs @@ -66,7 +66,7 @@ fn restores_cumulative_item_and_compaction_checkpoints() { }; let history = InitialHistory::Forked(vec![ RolloutItem::ResponseItem(envelope(Some(initial))), - RolloutItem::Compacted(CompactedItem { + RolloutItem::Compacted(Box::new(CompactedItem { message: "summary".to_string(), replacement_history: Some(vec![envelope(Some(cumulative.clone()))]), guardian_history: None, @@ -79,7 +79,7 @@ fn restores_cumulative_item_and_compaction_checkpoints() { compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }), + })), ]); assert_eq!(McpAttributionRecorder::new(&history).snapshot(), cumulative); @@ -135,7 +135,7 @@ fn first_error_reason_survives_checkpoints_and_later_sources() { compacted.replacement_history = Some(vec![checkpoint.clone()]); for item in [ RolloutItem::ResponseItem(checkpoint), - RolloutItem::Compacted(compacted), + RolloutItem::Compacted(Box::new(compacted)), ] { let restored = McpAttributionRecorder::new(&InitialHistory::Forked(vec![item])); restored.record(source("", "turn_3")); diff --git a/codex-rs/core/src/tools/executed_tool_calls/request_metadata_tests.rs b/codex-rs/core/src/tools/executed_tool_calls/request_metadata_tests.rs index 1c504bf872..db927b9c82 100644 --- a/codex-rs/core/src/tools/executed_tool_calls/request_metadata_tests.rs +++ b/codex-rs/core/src/tools/executed_tool_calls/request_metadata_tests.rs @@ -967,13 +967,13 @@ fn tool_call_completeness_survives_waits_without_changing_deltas() { fn paginated_history_allows_fresh_origins_but_rejects_known_ids() { for origin in ["fresh-exec", "old-exec"] { let history = InitialHistory::Forked(vec![ - RolloutItem::SessionMeta(SessionMetaLine { + RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { history_mode: ThreadHistoryMode::Paginated, ..SessionMeta::default() }, git: None, - }), + })), RolloutItem::ResponseItem(exec_input("old-exec").into()), RolloutItem::ResponseItem(exec_output("old-exec").into()), ]); diff --git a/codex-rs/core/tests/suite/client.rs b/codex-rs/core/tests/suite/client.rs index d443977137..7e24379417 100644 --- a/codex-rs/core/tests/suite/client.rs +++ b/codex-rs/core/tests/suite/client.rs @@ -673,7 +673,7 @@ async fn synthetic_call_output_id_is_stable_across_resumes() -> anyhow::Result<( RolloutLine { timestamp: "2024-01-01T00:00:00.000Z".to_string(), ordinal: None, - item: RolloutItem::SessionMeta(SessionMetaLine { + item: RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { session_id: thread_id.into(), id: thread_id, @@ -686,7 +686,7 @@ async fn synthetic_call_output_id_is_stable_across_resumes() -> anyhow::Result<( ..Default::default() }, git: None, - }), + })), }, RolloutLine { timestamp: "2024-01-01T00:00:01.000Z".to_string(), @@ -1187,7 +1187,7 @@ async fn resume_replays_legacy_js_repl_image_rollout_shapes() { RolloutLine { timestamp: "2024-01-01T00:00:00.000Z".to_string(), ordinal: None, - item: RolloutItem::SessionMeta(SessionMetaLine { + item: RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { session_id: thread_id.into(), id: thread_id, @@ -1200,7 +1200,7 @@ async fn resume_replays_legacy_js_repl_image_rollout_shapes() { ..Default::default() }, git: None, - }), + })), }, RolloutLine { timestamp: "2024-01-01T00:00:01.000Z".to_string(), @@ -1331,7 +1331,7 @@ async fn resume_replays_image_tool_outputs_with_detail() { RolloutLine { timestamp: "2024-01-01T00:00:00.000Z".to_string(), ordinal: None, - item: RolloutItem::SessionMeta(SessionMetaLine { + item: RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { session_id: thread_id.into(), id: thread_id, @@ -1344,7 +1344,7 @@ async fn resume_replays_image_tool_outputs_with_detail() { ..Default::default() }, git: None, - }), + })), }, RolloutLine { timestamp: "2024-01-01T00:00:01.000Z".to_string(), diff --git a/codex-rs/core/tests/suite/fork_thread.rs b/codex-rs/core/tests/suite/fork_thread.rs index c90fb92246..044cacd9a2 100644 --- a/codex-rs/core/tests/suite/fork_thread.rs +++ b/codex-rs/core/tests/suite/fork_thread.rs @@ -324,7 +324,7 @@ async fn assert_copied_fork_persists_inherited_history(history_mode: ThreadHisto let source_meta = codex_rollout::read_session_meta_line(source_path.as_path()) .await .expect("read source session metadata"); - let mut supplied_history = vec![RolloutItem::SessionMeta(source_meta)]; + let mut supplied_history = vec![RolloutItem::SessionMeta(Box::new(source_meta))]; supplied_history.extend(source_items.iter().cloned()); let NewThread { thread: forked_thread, diff --git a/codex-rs/core/tests/suite/guardian_authorization.rs b/codex-rs/core/tests/suite/guardian_authorization.rs index 1c2940e5d3..91f93d838c 100644 --- a/codex-rs/core/tests/suite/guardian_authorization.rs +++ b/codex-rs/core/tests/suite/guardian_authorization.rs @@ -179,12 +179,14 @@ async fn guardian_revalidates_owning_session_before_allow( test.codex = super::guardian_checkpoint_migration::resume( &test, &test.codex, - vec![RolloutItem::Compacted(serde_json::from_value(json!({ - "message": "old checkpoint", - "replacement_history": [{ - "type": "compaction", "id": "old", "encrypted_content": "unknown producer" - }] - }))?)], + vec![RolloutItem::Compacted(Box::new(serde_json::from_value( + json!({ + "message": "old checkpoint", + "replacement_history": [{ + "type": "compaction", "id": "old", "encrypted_content": "unknown producer" + }] + }), + )?))], ) .await?; } diff --git a/codex-rs/core/tests/suite/guardian_authorization_refresh.rs b/codex-rs/core/tests/suite/guardian_authorization_refresh.rs index cd0cda4b76..6279fba110 100644 --- a/codex-rs/core/tests/suite/guardian_authorization_refresh.rs +++ b/codex-rs/core/tests/suite/guardian_authorization_refresh.rs @@ -156,12 +156,14 @@ async fn guardian_refreshes_subagent_authorization(change: Change) -> Result<()> test.codex = super::guardian_checkpoint_migration::resume( &test, &test.codex, - vec![RolloutItem::Compacted(serde_json::from_value(json!({ - "message": "old checkpoint", - "replacement_history": [{ - "type": "compaction", "id": "old", "encrypted_content": "unknown producer" - }] - }))?)], + vec![RolloutItem::Compacted(Box::new(serde_json::from_value( + json!({ + "message": "old checkpoint", + "replacement_history": [{ + "type": "compaction", "id": "old", "encrypted_content": "unknown producer" + }] + }), + )?))], ) .await?; } diff --git a/codex-rs/core/tests/suite/guardian_root_handoff.rs b/codex-rs/core/tests/suite/guardian_root_handoff.rs index 5aca6a2fcc..4aa0b0df75 100644 --- a/codex-rs/core/tests/suite/guardian_root_handoff.rs +++ b/codex-rs/core/tests/suite/guardian_root_handoff.rs @@ -274,7 +274,7 @@ pub(crate) async fn handoff_scenario() -> Result> { "message":"Root checkpoint.", "replacement_history":[], "retained_context":history.retained_context(), }))?; test.codex - .append_rollout_items(&[RolloutItem::Compacted(checkpoint)]) + .append_rollout_items(&[RolloutItem::Compacted(Box::new(checkpoint))]) .await?; test.codex.flush_rollout().await?; let rollout = test diff --git a/codex-rs/core/tests/suite/guardian_subagent_authorization.rs b/codex-rs/core/tests/suite/guardian_subagent_authorization.rs index 96beaeff19..a11d977bfd 100644 --- a/codex-rs/core/tests/suite/guardian_subagent_authorization.rs +++ b/codex-rs/core/tests/suite/guardian_subagent_authorization.rs @@ -801,7 +801,7 @@ async fn run_guardian_subagent_review( test.codex = super::guardian_checkpoint_migration::resume( &test, &test.codex, - vec![RolloutItem::Compacted(checkpoint)], + vec![RolloutItem::Compacted(Box::new(checkpoint))], ) .await?; assert_eq!( @@ -1678,7 +1678,7 @@ async fn run_guardian_subagent_review( )); } checkpoint.replacement_history = Some(replacement_history); - root.append_rollout_items(&[RolloutItem::Compacted(checkpoint)]) + root.append_rollout_items(&[RolloutItem::Compacted(Box::new(checkpoint))]) .await?; root.shutdown_and_wait().await?; test.thread_manager.remove_thread(&root_thread_id).await; diff --git a/codex-rs/core/tests/suite/mcp_storage_telemetry_tests.rs b/codex-rs/core/tests/suite/mcp_storage_telemetry_tests.rs index ff71ae8405..0358aa88c7 100644 --- a/codex-rs/core/tests/suite/mcp_storage_telemetry_tests.rs +++ b/codex-rs/core/tests/suite/mcp_storage_telemetry_tests.rs @@ -111,7 +111,7 @@ async fn recovery_without_a_snapshot_keeps_each_threads_originator() -> Result<( let thread = fixture .thread_manager .start_thread(StartThreadOptions { - initial_history: InitialHistory::Forked(vec![RolloutItem::SessionMeta( + initial_history: InitialHistory::Forked(vec![RolloutItem::SessionMeta(Box::new( SessionMetaLine { meta: SessionMeta { originator: originator.into(), @@ -119,7 +119,7 @@ async fn recovery_without_a_snapshot_keeps_each_threads_originator() -> Result<( }, git: None, }, - )]), + ))]), environments: Some( fixture .codex diff --git a/codex-rs/core/tests/suite/remote_env_capability_roots_tests.rs b/codex-rs/core/tests/suite/remote_env_capability_roots_tests.rs index f6ff5889e6..334ccef433 100644 --- a/codex-rs/core/tests/suite/remote_env_capability_roots_tests.rs +++ b/codex-rs/core/tests/suite/remote_env_capability_roots_tests.rs @@ -48,13 +48,13 @@ async fn selected_capability_roots_survive_environment_reselection( }]; let mut thread_extension_init = ExtensionDataInit::new(); let initial_history = if from_history { - InitialHistory::Forked(vec![RolloutItem::SessionMeta(SessionMetaLine { + InitialHistory::Forked(vec![RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { selected_capability_roots: roots.clone(), ..SessionMeta::default() }, git: None, - })]) + }))]) } else { thread_extension_init.insert(roots.clone()); InitialHistory::New diff --git a/codex-rs/core/tests/suite/sqlite_state.rs b/codex-rs/core/tests/suite/sqlite_state.rs index af772f8d9a..f863f9e3d8 100644 --- a/codex-rs/core/tests/suite/sqlite_state.rs +++ b/codex-rs/core/tests/suite/sqlite_state.rs @@ -592,7 +592,7 @@ async fn backfill_scans_existing_rollouts() -> Result<()> { RolloutLine { timestamp: "2026-01-27T12:00:00Z".to_string(), ordinal: None, - item: RolloutItem::SessionMeta(session_meta_line), + item: RolloutItem::SessionMeta(Box::new(session_meta_line)), }, RolloutLine { timestamp: "2026-01-27T12:00:01Z".to_string(), diff --git a/codex-rs/history/src/lib.rs b/codex-rs/history/src/lib.rs index 826669cc33..7262a4b1b8 100644 --- a/codex-rs/history/src/lib.rs +++ b/codex-rs/history/src/lib.rs @@ -213,13 +213,13 @@ impl Borrow for ResponseItemEnvelope { /// Persisted rollout item used by core history and rollout storage. #[derive(Debug, Clone)] pub enum RolloutItem { - SessionMeta(SessionMetaLine), + SessionMeta(Box), ResponseItem(ResponseItemEnvelope), InterAgentCommunication(InterAgentCommunication), InterAgentCommunicationMetadata { trigger_turn: bool, }, - Compacted(CompactedItem), + Compacted(Box), TurnContext(TurnContextItem), TokenUsageRecord(TokenUsageRecord), WorldState(WorldStateItem), diff --git a/codex-rs/history/src/rollout_payload.rs b/codex-rs/history/src/rollout_payload.rs index 9ab89363df..370e8c8c82 100644 --- a/codex-rs/history/src/rollout_payload.rs +++ b/codex-rs/history/src/rollout_payload.rs @@ -166,7 +166,9 @@ impl<'a> From<&'a RolloutItem> for RolloutItemWire<'a> { impl From> for RolloutItem { fn from(item: RolloutItemWire<'_>) -> Self { match item { - RolloutItemWire::SessionMeta { payload } => Self::SessionMeta(payload.into_owned()), + RolloutItemWire::SessionMeta { payload } => { + Self::SessionMeta(Box::new(payload.into_owned())) + } RolloutItemWire::ResponseItem { payload, metadata } => { if let ( ResponseItem::Message { @@ -218,7 +220,9 @@ impl From> for RolloutItem { trigger_turn: payload.trigger_turn, } } - RolloutItemWire::Compacted { payload } => Self::Compacted(payload.into_owned()), + RolloutItemWire::Compacted { payload } => { + Self::Compacted(Box::new(payload.into_owned())) + } RolloutItemWire::TurnContext { payload } => Self::TurnContext(payload.into_owned()), RolloutItemWire::TokenUsageRecord { payload } => { Self::TokenUsageRecord(payload.into_owned()) diff --git a/codex-rs/history/src/tests.rs b/codex-rs/history/src/tests.rs index 32a6110d3b..2f6424b6b0 100644 --- a/codex-rs/history/src/tests.rs +++ b/codex-rs/history/src/tests.rs @@ -682,7 +682,7 @@ fn compacted_metadata_remains_compatible_with_legacy_response_item_readers() -> ])?)?, crate::GuardianHistoryCheckpoint(vec![response_item.clone().into()]), ); - let compacted_line = serde_json::to_value(RolloutItem::Compacted(CompactedItem { + let compacted_line = serde_json::to_value(RolloutItem::Compacted(Box::new(CompactedItem { message: "summary".to_string(), replacement_history: Some(vec![envelope]), retained_context: None, @@ -700,7 +700,7 @@ fn compacted_metadata_remains_compatible_with_legacy_response_item_readers() -> turn_attribution: None, previous_turn_settings: None, }), - }))?; + })))?; let restored: RolloutItem = serde_json::from_value(compacted_line.clone())?; let RolloutItem::Compacted(restored) = restored else { @@ -959,7 +959,7 @@ fn compacted_item_migrates_legacy_numeric_window_id() -> Result<()> { #[test] fn copied_history_uses_persisted_history_mode() -> Result<()> { let thread_id = ThreadId::from_string("00000000-0000-0000-0000-000000000001")?; - let session_meta = RolloutItem::SessionMeta(SessionMetaLine { + let session_meta = RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { session_id: thread_id.into(), id: thread_id, @@ -967,7 +967,7 @@ fn copied_history_uses_persisted_history_mode() -> Result<()> { ..SessionMeta::default() }, git: None, - }); + })); let history = InitialHistory::Resumed(ResumedHistory { history_revision: None, conversation_id: thread_id, @@ -1025,8 +1025,8 @@ fn multi_agent_version_uses_newest_present_session_meta_value() -> Result<()> { assert_eq!( multi_agent_version_from_items( &[ - RolloutItem::SessionMeta(older_meta), - RolloutItem::SessionMeta(newer_meta_without_version), + RolloutItem::SessionMeta(Box::new(older_meta)), + RolloutItem::SessionMeta(Box::new(newer_meta_without_version)), ], Some(thread_id), ), @@ -1045,7 +1045,8 @@ fn multi_agent_version_uses_compaction_metadata_without_turn_context() -> Result }))?; assert_eq!( - InitialHistory::Forked(vec![RolloutItem::Compacted(compacted)]).get_multi_agent_version(), + InitialHistory::Forked(vec![RolloutItem::Compacted(Box::new(compacted))]) + .get_multi_agent_version(), Some(MultiAgentVersion::V2) ); Ok(()) diff --git a/codex-rs/rollout/src/compression_tests.rs b/codex-rs/rollout/src/compression_tests.rs index 93b9e48c6a..806039d624 100644 --- a/codex-rs/rollout/src/compression_tests.rs +++ b/codex-rs/rollout/src/compression_tests.rs @@ -1155,7 +1155,7 @@ fn write_rollout(path: &std::path::Path, thread_id: ThreadId, message: &str) -> RolloutLine { timestamp: "2025-01-03T12:00:00Z".to_string(), ordinal: None, - item: RolloutItem::SessionMeta(session_meta_line), + item: RolloutItem::SessionMeta(Box::new(session_meta_line)), }, RolloutLine { timestamp: "2025-01-03T12:00:01Z".to_string(), diff --git a/codex-rs/rollout/src/list.rs b/codex-rs/rollout/src/list.rs index 10734a92b9..66607d92ba 100644 --- a/codex-rs/rollout/src/list.rs +++ b/codex-rs/rollout/src/list.rs @@ -1204,7 +1204,7 @@ pub async fn read_session_meta_line(path: &Path) -> io::Result continue; }; match rollout_line.item { - RolloutItem::SessionMeta(session_meta_line) => return Ok(session_meta_line), + RolloutItem::SessionMeta(session_meta_line) => return Ok(*session_meta_line), RolloutItem::ResponseItem(_) | RolloutItem::InterAgentCommunication(_) => { return Err(io::Error::other(MetadataReadError { reason: "response_before_metadata", diff --git a/codex-rs/rollout/src/metadata_tests.rs b/codex-rs/rollout/src/metadata_tests.rs index 79091b8dd0..770a4290e2 100644 --- a/codex-rs/rollout/src/metadata_tests.rs +++ b/codex-rs/rollout/src/metadata_tests.rs @@ -152,7 +152,7 @@ async fn extract_metadata_from_rollout_uses_session_meta() { let rollout_line = RolloutLine { timestamp: "2026-01-27T12:34:56Z".to_string(), ordinal: Some(0), - item: RolloutItem::SessionMeta(session_meta_line.clone()), + item: RolloutItem::SessionMeta(Box::new(session_meta_line.clone())), }; let json = serde_json::to_string(&rollout_line).expect("rollout json"); let mut file = File::create(&path).expect("create rollout"); @@ -164,7 +164,7 @@ async fn extract_metadata_from_rollout_uses_session_meta() { let parent_line = RolloutLine { timestamp: rollout_line.timestamp.clone(), ordinal: Some(1), - item: RolloutItem::SessionMeta(parent), + item: RolloutItem::SessionMeta(Box::new(parent)), }; writeln!( file, @@ -206,7 +206,7 @@ async fn extract_metadata_from_rollout_rejects_unknown_history_mode() { let mut rollout_line = serde_json::to_value(RolloutLine { timestamp: "2026-01-27T12:34:56Z".to_string(), ordinal: None, - item: RolloutItem::SessionMeta(SessionMetaLine { + item: RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { session_id: id.into(), id, @@ -217,7 +217,7 @@ async fn extract_metadata_from_rollout_rejects_unknown_history_mode() { ..SessionMeta::default() }, git: None, - }), + })), }) .expect("serialize rollout line"); rollout_line["payload"]["history_mode"] = serde_json::json!("future"); @@ -278,18 +278,18 @@ async fn extract_metadata_from_rollout_returns_latest_memory_mode() { RolloutLine { timestamp: "2026-01-27T12:34:56Z".to_string(), ordinal: None, - item: RolloutItem::SessionMeta(SessionMetaLine { + item: RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: session_meta, git: None, - }), + })), }, RolloutLine { timestamp: "2026-01-27T12:35:00Z".to_string(), ordinal: None, - item: RolloutItem::SessionMeta(SessionMetaLine { + item: RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: polluted_meta, git: None, - }), + })), }, ]; let mut file = File::create(&path).expect("create rollout"); @@ -316,7 +316,7 @@ fn builder_from_items_falls_back_to_filename() { let path = dir .path() .join(format!("rollout-2026-01-27T12-34-56-{uuid}.jsonl")); - let items = vec![RolloutItem::Compacted(CompactedItem { + let items = vec![RolloutItem::Compacted(Box::new(CompactedItem { message: "noop".to_string(), replacement_history: None, retained_context: None, @@ -329,7 +329,7 @@ fn builder_from_items_falls_back_to_filename() { compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - })]; + }))]; let builder = builder_from_items(items.as_slice(), path.as_path()).expect("builder"); let naive = NaiveDateTime::parse_from_str("2026-01-27T12-34-56", "%Y-%m-%dT%H-%M-%S") @@ -625,7 +625,7 @@ fn write_rollout_in_sessions_with_cwd( let rollout_line = RolloutLine { timestamp: event_ts.to_string(), ordinal: None, - item: RolloutItem::SessionMeta(session_meta_line), + item: RolloutItem::SessionMeta(Box::new(session_meta_line)), }; let json = serde_json::to_string(&rollout_line).expect("serialize rollout"); let mut file = File::create(&path).expect("create rollout"); diff --git a/codex-rs/rollout/src/recorder.rs b/codex-rs/rollout/src/recorder.rs index b02229a377..4be15ef1e2 100644 --- a/codex-rs/rollout/src/recorder.rs +++ b/codex-rs/rollout/src/recorder.rs @@ -2039,7 +2039,7 @@ async fn write_session_meta( git: git_info, }; - let rollout_item = RolloutItem::SessionMeta(session_meta_line); + let rollout_item = RolloutItem::SessionMeta(Box::new(session_meta_line)); if let Some(writer) = writer.as_mut() { let ordinal = ordinal_state.current()?; writer.write_rollout_item(&rollout_item, ordinal).await?; diff --git a/codex-rs/rollout/src/recorder_tests.rs b/codex-rs/rollout/src/recorder_tests.rs index 7e7767ec0f..d42a7c4ba7 100644 --- a/codex-rs/rollout/src/recorder_tests.rs +++ b/codex-rs/rollout/src/recorder_tests.rs @@ -48,7 +48,7 @@ fn test_config(codex_home: &Path) -> RolloutConfig { } fn paginated_session_meta_item(thread_id: ThreadId, cwd: &Path) -> RolloutItem { - RolloutItem::SessionMeta(SessionMetaLine { + RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { session_id: thread_id.into(), id: thread_id, @@ -61,7 +61,7 @@ fn paginated_session_meta_item(thread_id: ThreadId, cwd: &Path) -> RolloutItem { ..SessionMeta::default() }, git: None, - }) + })) } fn agent_message_item(message: &str) -> RolloutItem { @@ -248,7 +248,7 @@ async fn state_db_init_backfills_before_returning() -> anyhow::Result<()> { RolloutLine { timestamp: "2026-01-27T12:34:56Z".to_string(), ordinal: None, - item: RolloutItem::SessionMeta(session_meta_line), + item: RolloutItem::SessionMeta(Box::new(session_meta_line)), }, RolloutLine { timestamp: "2026-01-27T12:34:57Z".to_string(), diff --git a/codex-rs/rollout/src/session_index_tests.rs b/codex-rs/rollout/src/session_index_tests.rs index 1a4c7070d1..32eb6c1a07 100644 --- a/codex-rs/rollout/src/session_index_tests.rs +++ b/codex-rs/rollout/src/session_index_tests.rs @@ -33,7 +33,7 @@ fn write_rollout_with_source_and_provider( let line = RolloutLine { timestamp: timestamp.clone(), ordinal: None, - item: RolloutItem::SessionMeta(SessionMetaLine { + item: RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { creator_user_id: None, creator_account_id: None, @@ -64,7 +64,7 @@ fn write_rollout_with_source_and_provider( context_window: None, }, git: None, - }), + })), }; let body = serde_json::to_string(&line).map_err(std::io::Error::other)?; std::fs::write(path, format!("{body}\n")) diff --git a/codex-rs/rollout/src/state_db_tests.rs b/codex-rs/rollout/src/state_db_tests.rs index 22de3ccdb4..ebf5881870 100644 --- a/codex-rs/rollout/src/state_db_tests.rs +++ b/codex-rs/rollout/src/state_db_tests.rs @@ -323,7 +323,7 @@ fn write_rollout_with_user_message( RolloutLine { timestamp: "2026-06-01T14:26:25Z".to_string(), ordinal: None, - item: RolloutItem::SessionMeta(SessionMetaLine { + item: RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { creator_user_id: None, creator_account_id: None, @@ -354,7 +354,7 @@ fn write_rollout_with_user_message( context_window: None, }, git: None, - }), + })), }, RolloutLine { timestamp: "2026-06-01T14:26:26Z".to_string(), diff --git a/codex-rs/rollout/src/tests.rs b/codex-rs/rollout/src/tests.rs index 2c9f0fe4bc..b1484f1694 100644 --- a/codex-rs/rollout/src/tests.rs +++ b/codex-rs/rollout/src/tests.rs @@ -1591,7 +1591,7 @@ async fn test_updated_at_uses_file_mtime() -> Result<()> { let meta_line = RolloutLine { timestamp: ts.to_string(), ordinal: None, - item: RolloutItem::SessionMeta(SessionMetaLine { + item: RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { creator_user_id: None, creator_account_id: None, @@ -1622,7 +1622,7 @@ async fn test_updated_at_uses_file_mtime() -> Result<()> { context_window: None, }, git: None, - }), + })), }; writeln!(file, "{}", serde_json::to_string(&meta_line)?)?; diff --git a/codex-rs/state/src/extract.rs b/codex-rs/state/src/extract.rs index f079ebc4ee..18bcec64cd 100644 --- a/codex-rs/state/src/extract.rs +++ b/codex-rs/state/src/extract.rs @@ -365,7 +365,7 @@ mod tests { let mut metadata = ThreadMetadataBuilder::new(thread_id, PathBuf::new(), Utc::now(), source.clone()) .build("test-provider"); - let session_meta = RolloutItem::SessionMeta(SessionMetaLine { + let session_meta = RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { session_id: thread_id.into(), id: thread_id, @@ -373,7 +373,7 @@ mod tests { ..Default::default() }, git: None, - }); + })); apply_rollout_item(&mut metadata, &session_meta, "test-provider"); let mut expected = metadata.clone(); expected.title = super::GUARDIAN_THREAD_TITLE.to_string(); @@ -525,7 +525,7 @@ mod tests { apply_rollout_item( &mut metadata, - &RolloutItem::SessionMeta(SessionMetaLine { + &RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { creator_user_id: None, creator_account_id: None, @@ -558,7 +558,7 @@ mod tests { context_window: None, }, git: None, - }), + })), "test-provider", ); apply_rollout_item( @@ -775,7 +775,7 @@ mod tests { apply_rollout_item( &mut metadata, - &RolloutItem::SessionMeta(SessionMetaLine { + &RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { creator_user_id: None, creator_account_id: None, @@ -806,7 +806,7 @@ mod tests { context_window: None, }, git: None, - }), + })), "test-provider", ); diff --git a/codex-rs/state/src/runtime/threads.rs b/codex-rs/state/src/runtime/threads.rs index 96704dfa08..5a96d13c58 100644 --- a/codex-rs/state/src/runtime/threads.rs +++ b/codex-rs/state/src/runtime/threads.rs @@ -2806,7 +2806,7 @@ mod tests { metadata.created_at, SessionSource::Cli, ); - let items = vec![RolloutItem::SessionMeta(SessionMetaLine { + let items = vec![RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { creator_user_id: None, creator_account_id: None, @@ -2837,7 +2837,7 @@ mod tests { context_window: None, }, git: None, - })]; + }))]; runtime .apply_rollout_items( @@ -2880,7 +2880,7 @@ mod tests { metadata.created_at, SessionSource::Cli, ); - let items = vec![RolloutItem::SessionMeta(SessionMetaLine { + let items = vec![RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { creator_user_id: None, creator_account_id: None, @@ -2918,7 +2918,7 @@ mod tests { .expect("valid git remote URL"), ), }), - })]; + }))]; runtime .apply_rollout_items( diff --git a/codex-rs/thread-store/src/in_memory.rs b/codex-rs/thread-store/src/in_memory.rs index 568596f675..14a967e6e4 100644 --- a/codex-rs/thread-store/src/in_memory.rs +++ b/codex-rs/thread-store/src/in_memory.rs @@ -617,10 +617,10 @@ impl InMemoryThreadStore { .histories .entry(params.thread_id) .or_default() - .push(RolloutItem::SessionMeta(SessionMetaLine { + .push(RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: session_meta, git: None, - })); + }))); state.created_threads.insert(params.thread_id, params); Ok(()) } diff --git a/codex-rs/thread-store/src/local/compression_writer_tests.rs b/codex-rs/thread-store/src/local/compression_writer_tests.rs index 1ea0161bbd..34b976d0e0 100644 --- a/codex-rs/thread-store/src/local/compression_writer_tests.rs +++ b/codex-rs/thread-store/src/local/compression_writer_tests.rs @@ -185,7 +185,7 @@ async fn metadata_updates_share_ownership_and_resume_compressed_rollouts() -> Te expected.git = None; assert_eq!( json!(items.last()), - json!(Some(RolloutItem::SessionMeta(expected.clone()))) + json!(Some(RolloutItem::SessionMeta(Box::new(expected.clone())))) ); age(&path)?; @@ -214,7 +214,7 @@ async fn metadata_updates_share_ownership_and_resume_compressed_rollouts() -> Te let (items, _, _) = RolloutRecorder::load_rollout_items(&path).await?; assert_eq!( json!(items.last()), - json!(Some(RolloutItem::SessionMeta(expected))) + json!(Some(RolloutItem::SessionMeta(Box::new(expected)))) ); Ok(()) } diff --git a/codex-rs/thread-store/src/local/model_context.rs b/codex-rs/thread-store/src/local/model_context.rs index bcfd460b20..87fe92ae38 100644 --- a/codex-rs/thread-store/src/local/model_context.rs +++ b/codex-rs/thread-store/src/local/model_context.rs @@ -155,7 +155,7 @@ pub(super) async fn load_for_fork( let lineage = lineage.truncate_at(history_base).await?; scan_model_context_from_lineage(lineage, session_meta).await } - None => Ok(vec![RolloutItem::SessionMeta(session_meta)]), + None => Ok(vec![RolloutItem::SessionMeta(Box::new(session_meta))]), } } @@ -212,6 +212,6 @@ fn scan_model_context_from_lineage_blocking( } let mut items = scan.finish(); - items.insert(0, RolloutItem::SessionMeta(session_meta)); + items.insert(0, RolloutItem::SessionMeta(Box::new(session_meta))); Ok(items) } diff --git a/codex-rs/thread-store/src/local/model_context_tests.rs b/codex-rs/thread-store/src/local/model_context_tests.rs index acf0c28a33..683d66a9fb 100644 --- a/codex-rs/thread-store/src/local/model_context_tests.rs +++ b/codex-rs/thread-store/src/local/model_context_tests.rs @@ -69,7 +69,7 @@ async fn stops_at_newest_usable_compaction_and_keeps_companions() { assert_eq!( serde_json::to_value(context.items).expect("serialize context"), serde_json::to_value(vec![ - RolloutItem::SessionMeta(session_meta), + RolloutItem::SessionMeta(Box::new(session_meta)), compacted("latest compaction", Some(Vec::new())), world_state, turn_context, @@ -129,7 +129,7 @@ async fn loads_recent_context_after_many_empty_wake_turns() { }) .await .expect("load model context"); - expected_suffix.insert(0, RolloutItem::SessionMeta(session_meta)); + expected_suffix.insert(0, RolloutItem::SessionMeta(Box::new(session_meta))); assert_eq!( serde_json::to_value(context.items).expect("serialize context"), @@ -165,7 +165,7 @@ async fn fork_context_excludes_items_after_frozen_cutoff() { .expect("load frozen fork context"); let expected = vec![ - RolloutItem::SessionMeta(session_meta), + RolloutItem::SessionMeta(Box::new(session_meta)), turn_started("frozen-turn"), user_message("frozen message"), ]; @@ -201,7 +201,7 @@ async fn fork_version_stops_before_older_segments_once_resolved() { let head = RolloutLine { timestamp: "2025-01-03T13:02:01Z".to_string(), ordinal: Some(0), - item: RolloutItem::SessionMeta(source_meta.clone()), + item: RolloutItem::SessionMeta(Box::new(source_meta.clone())), }; std::fs::write( &child_path, @@ -243,7 +243,7 @@ async fn fork_version_stops_before_older_segments_once_resolved() { source_meta.meta.multi_agent_version = stored_version.or(Some(MultiAgentVersion::V2)); assert_eq!( serde_json::to_value(context).expect("serialize fork context"), - serde_json::to_value(vec![RolloutItem::SessionMeta(source_meta)]) + serde_json::to_value(vec![RolloutItem::SessionMeta(Box::new(source_meta))]) .expect("serialize expected context") ); } @@ -296,7 +296,7 @@ async fn fork_version_respects_inherited_segment_cutoffs() { source_meta.meta.multi_agent_version = Some(MultiAgentVersion::V2); assert_eq!( serde_json::to_value(context).expect("serialize fork context"), - serde_json::to_value(vec![RolloutItem::SessionMeta(source_meta)]) + serde_json::to_value(vec![RolloutItem::SessionMeta(Box::new(source_meta))]) .expect("serialize expected context") ); } @@ -444,7 +444,7 @@ async fn replays_nested_archived_lineage_from_frozen_prefix() { .await .expect("read child metadata"); let expected = vec![ - RolloutItem::SessionMeta(child_meta), + RolloutItem::SessionMeta(Box::new(child_meta)), compacted("root checkpoint", Some(Vec::new())), turn_started("middle-turn"), user_message("middle inherited"), @@ -703,7 +703,7 @@ fn turn_context(root: &Path, turn_id: &str) -> RolloutItem { } fn compacted(message: &str, replacement_history: Option>) -> RolloutItem { - RolloutItem::Compacted(CompactedItem { + RolloutItem::Compacted(Box::new(CompactedItem { message: message.to_string(), replacement_history: replacement_history .map(|items| items.into_iter().map(Into::into).collect()), @@ -717,5 +717,5 @@ fn compacted(message: &str, replacement_history: Option>) -> R compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }) + })) } diff --git a/codex-rs/thread-store/src/local/read_thread_tests.rs b/codex-rs/thread-store/src/local/read_thread_tests.rs index 065c47d63a..d0a54a827b 100644 --- a/codex-rs/thread-store/src/local/read_thread_tests.rs +++ b/codex-rs/thread-store/src/local/read_thread_tests.rs @@ -34,7 +34,7 @@ async fn empty_archived_reads_without_sqlite_preserve_source_and_file_time() let line = RolloutLine { timestamp: timestamp.to_string(), ordinal: None, - item: RolloutItem::SessionMeta(SessionMetaLine { + item: RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { id: thread_id, session_id: thread_id.into(), @@ -43,7 +43,7 @@ async fn empty_archived_reads_without_sqlite_preserve_source_and_file_time() ..SessionMeta::default() }, git: None, - }), + })), }; fs::write(&path, format!("{}\n", serde_json::to_string(&line)?))?; fs::OpenOptions::new() diff --git a/codex-rs/thread-store/src/local/rollout_lineage_tests.rs b/codex-rs/thread-store/src/local/rollout_lineage_tests.rs index be93f4a38c..e62140bdeb 100644 --- a/codex-rs/thread-store/src/local/rollout_lineage_tests.rs +++ b/codex-rs/thread-store/src/local/rollout_lineage_tests.rs @@ -277,7 +277,7 @@ fn write_rollout_under( let initial_ordinal = history_base.map_or(0, |base| base.end_ordinal_exclusive); let mut lines = vec![rollout_line( initial_ordinal, - RolloutItem::SessionMeta(SessionMetaLine { + RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { session_id: thread_id.into(), id: thread_id, @@ -286,7 +286,7 @@ fn write_rollout_under( ..SessionMeta::default() }, git: None, - }), + })), )]; for offset in 1..next_ordinal { let ordinal = initial_ordinal diff --git a/codex-rs/thread-store/src/local/rollout_migration/rollback_plan.rs b/codex-rs/thread-store/src/local/rollout_migration/rollback_plan.rs index 45081b4689..1a884e8350 100644 --- a/codex-rs/thread-store/src/local/rollout_migration/rollback_plan.rs +++ b/codex-rs/thread-store/src/local/rollout_migration/rollback_plan.rs @@ -86,7 +86,7 @@ impl RollbackPlan { // A rolled-back turn can still own the empty checkpoint that keeps cold resume from // replaying older history. if let Some(compacted) = self.compacted_items.get(&record_index) { - line.item = RolloutItem::Compacted(compacted.clone()); + line.item = RolloutItem::Compacted(Box::new(compacted.clone())); return Ok(Some(line)); } if boundary.is_some_and(|boundary| !self.boundary_alive[boundary]) { @@ -262,7 +262,7 @@ impl RollbackPlanner { record_index: index, boundary_depth: self.boundary_stack.len(), owner, - item: item.clone(), + item: item.as_ref().clone(), }); } RolloutItem::TurnContext(_) => { diff --git a/codex-rs/thread-store/src/local/rollout_migration/startup_tests.rs b/codex-rs/thread-store/src/local/rollout_migration/startup_tests.rs index a2b7d34f81..5594edab32 100644 --- a/codex-rs/thread-store/src/local/rollout_migration/startup_tests.rs +++ b/codex-rs/thread-store/src/local/rollout_migration/startup_tests.rs @@ -47,10 +47,10 @@ fn write_rollout(home: &Path, thread_id: ThreadId, history_mode: ThreadHistoryMo ..SessionMeta::default() }; for (ordinal, item) in [ - RolloutItem::SessionMeta(SessionMetaLine { + RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: metadata, git: None, - }), + })), RolloutItem::EventMsg(EventMsg::UserMessage(UserMessageEvent { message: "question".to_string(), ..UserMessageEvent::default() diff --git a/codex-rs/thread-store/src/local/rollout_migration_tests.rs b/codex-rs/thread-store/src/local/rollout_migration_tests.rs index f3ef5849f0..8179691899 100644 --- a/codex-rs/thread-store/src/local/rollout_migration_tests.rs +++ b/codex-rs/thread-store/src/local/rollout_migration_tests.rs @@ -119,10 +119,10 @@ fn write_rollout_with_fork( model_provider: Some("test-provider".to_string()), ..SessionMeta::default() }; - let items = std::iter::once(RolloutItem::SessionMeta(SessionMetaLine { + let items = std::iter::once(RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: metadata, git: None, - })) + }))) .chain(items); for item in items { let line = RolloutLine { @@ -245,7 +245,7 @@ fn started(turn_id: &str) -> RolloutItem { } fn compacted(replacement_history: Vec) -> RolloutItem { - RolloutItem::Compacted(CompactedItem { + RolloutItem::Compacted(Box::new(CompactedItem { message: "checkpoint".to_string(), replacement_history: Some(replacement_history.into_iter().map(Into::into).collect()), retained_context: None, @@ -258,7 +258,7 @@ fn compacted(replacement_history: Vec) -> RolloutItem { compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }) + })) } fn completed(turn_id: &str) -> RolloutItem { @@ -2077,10 +2077,10 @@ async fn migration_drops_copied_user_fork_metadata_without_creating_a_history_ba SessionSource::Cli, Some(parent_id), vec![ - RolloutItem::SessionMeta(SessionMetaLine { + RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: copied_metadata, git: None, - }), + })), copied_response, user_message("child question"), agent_message("child answer"), @@ -2142,7 +2142,7 @@ async fn migration_compacts_subagent_prefix_and_does_not_project_it() { thread_id, SessionSource::SubAgent(SubAgentSource::Other("test".to_string())), vec![ - RolloutItem::Compacted(CompactedItem { + RolloutItem::Compacted(Box::new(CompactedItem { message: "superseded checkpoint".repeat(1024), replacement_history: Some(Vec::new()), retained_context: None, @@ -2155,8 +2155,8 @@ async fn migration_compacts_subagent_prefix_and_does_not_project_it() { compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }), - RolloutItem::Compacted(CompactedItem { + })), + RolloutItem::Compacted(Box::new(CompactedItem { message: "latest checkpoint".to_string(), replacement_history: Some(vec![ ResponseItem::Message { @@ -2182,7 +2182,7 @@ async fn migration_compacts_subagent_prefix_and_does_not_project_it() { compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }), + })), started("child-turn"), RolloutItem::TurnContext(TurnContextItem { turn_id: Some("child-turn".to_string()), diff --git a/codex-rs/thread-store/src/local/thread_history/read_tests.rs b/codex-rs/thread-store/src/local/thread_history/read_tests.rs index 116b5866d6..b974327dc8 100644 --- a/codex-rs/thread-store/src/local/thread_history/read_tests.rs +++ b/codex-rs/thread-store/src/local/thread_history/read_tests.rs @@ -1569,7 +1569,7 @@ fn write_rollout_with_end( let mut lines = vec![RolloutLine { timestamp: "2026-07-16T00:00:00.000Z".to_string(), ordinal: Some(initial_ordinal), - item: RolloutItem::SessionMeta(SessionMetaLine { + item: RolloutItem::SessionMeta(Box::new(SessionMetaLine { meta: SessionMeta { session_id: thread_id.into(), id: thread_id, @@ -1578,7 +1578,7 @@ fn write_rollout_with_end( ..SessionMeta::default() }, git: None, - }), + })), }]; for offset in 1..next_ordinal { let ordinal = initial_ordinal diff --git a/codex-rs/thread-store/src/local/update_thread_metadata.rs b/codex-rs/thread-store/src/local/update_thread_metadata.rs index 9e72bcdf02..3e2729b021 100644 --- a/codex-rs/thread-store/src/local/update_thread_metadata.rs +++ b/codex-rs/thread-store/src/local/update_thread_metadata.rs @@ -921,7 +921,7 @@ async fn update_rollout_metadata( }; patch(&mut metadata); recorder - .record_canonical_items(&[RolloutItem::SessionMeta(metadata)]) + .record_canonical_items(&[RolloutItem::SessionMeta(Box::new(metadata))]) .await .map_err(io_error)?; recorder.flush().await.map_err(io_error)?; @@ -1314,7 +1314,7 @@ mod tests { let (mut expected, _, _) = RolloutRecorder::load_rollout_items(&path).await?; let mut metadata = read_session_meta_line(&path).await?; metadata.meta.memory_mode = Some("disabled".into()); - expected.push(RolloutItem::SessionMeta(metadata)); + expected.push(RolloutItem::SessionMeta(Box::new(metadata))); let mut shutdown = Box::pin(store.shutdown_thread(thread_id)); update_rollout_metadata(&store, thread_id, &path, &writer_lock, |meta| { diff --git a/codex-rs/thread-store/src/thread_metadata_sync.rs b/codex-rs/thread-store/src/thread_metadata_sync.rs index 0351105fc1..c58a3c49e4 100644 --- a/codex-rs/thread-store/src/thread_metadata_sync.rs +++ b/codex-rs/thread-store/src/thread_metadata_sync.rs @@ -563,7 +563,7 @@ mod tests { let mut sync = resume_sync( thread_id, vec![ - RolloutItem::SessionMeta(session_meta(thread_id)), + RolloutItem::SessionMeta(Box::new(session_meta(thread_id))), RolloutItem::EventMsg(EventMsg::UserMessage(user_message("hello metadata"))), ], ); @@ -672,7 +672,7 @@ mod tests { fn metadata_irrelevant_items_coalesce_updated_at_touches() { let thread_id = ThreadId::new(); let mut sync = resume_sync(thread_id, Vec::new()); - let item = RolloutItem::Compacted(CompactedItem { + let item = RolloutItem::Compacted(Box::new(CompactedItem { message: "compacted".to_string(), replacement_history: None, retained_context: None, @@ -685,7 +685,7 @@ mod tests { compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }); + })); let first = sync .observe_appended_items(std::slice::from_ref(&item)) @@ -804,7 +804,7 @@ mod tests { let mut sync = resume_sync( thread_id, vec![ - RolloutItem::SessionMeta(session_meta(thread_id)), + RolloutItem::SessionMeta(Box::new(session_meta(thread_id))), RolloutItem::EventMsg(EventMsg::UserMessage(user_message("hello metadata"))), ], ); @@ -836,7 +836,7 @@ mod tests { let sync = resume_sync( thread_id, vec![ - RolloutItem::SessionMeta(meta), + RolloutItem::SessionMeta(Box::new(meta)), RolloutItem::EventMsg(EventMsg::UserMessage(user_message("hello metadata"))), ], ); diff --git a/codex-rs/thread-store/src/types.rs b/codex-rs/thread-store/src/types.rs index 5b3dea3551..163833a7cf 100644 --- a/codex-rs/thread-store/src/types.rs +++ b/codex-rs/thread-store/src/types.rs @@ -1143,12 +1143,12 @@ mod tests { } fn session_meta(history_mode: ThreadHistoryMode) -> RolloutItem { - RolloutItem::SessionMeta(codex_protocol::protocol::SessionMetaLine { + RolloutItem::SessionMeta(Box::new(codex_protocol::protocol::SessionMetaLine { meta: codex_protocol::protocol::SessionMeta { history_mode, ..Default::default() }, git: None, - }) + })) } } diff --git a/codex-rs/tui/src/resume_picker_transcript_preview_tests.rs b/codex-rs/tui/src/resume_picker_transcript_preview_tests.rs index 0750e3eb76..cfbb9ee5e7 100644 --- a/codex-rs/tui/src/resume_picker_transcript_preview_tests.rs +++ b/codex-rs/tui/src/resume_picker_transcript_preview_tests.rs @@ -73,7 +73,7 @@ fn legacy_transcript_preview_scans_tail_across_compaction() { vec![ rollout_user_message("older user"), rollout_agent_message("older assistant"), - RolloutItem::Compacted(CompactedItem { + RolloutItem::Compacted(Box::new(CompactedItem { message: String::from("summary that is not transcript text"), replacement_history: None, retained_context: None, @@ -86,7 +86,7 @@ fn legacy_transcript_preview_scans_tail_across_compaction() { compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }), + })), rollout_user_message("recent user"), rollout_agent_message("commentary one\ncommentary two"), rollout_agent_message("final one\n\n final two "), @@ -209,7 +209,7 @@ fn legacy_transcript_preview_falls_back_for_oversized_hidden_record() { &path, vec![ rollout_user_message("older user"), - RolloutItem::Compacted(CompactedItem { + RolloutItem::Compacted(Box::new(CompactedItem { message: "x".repeat(MAX_LEGACY_TRANSCRIPT_PREVIEW_SCAN_BYTES), replacement_history: None, retained_context: None, @@ -222,7 +222,7 @@ fn legacy_transcript_preview_falls_back_for_oversized_hidden_record() { compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }), + })), rollout_agent_message("recent assistant"), ], ); @@ -241,7 +241,7 @@ fn legacy_transcript_preview_falls_back_for_oversized_hidden_record() { fn legacy_transcript_preview_falls_back_when_scan_budget_is_exhausted() { let temp_dir = tempdir().expect("tempdir"); let path = temp_dir.path().join("rollout.jsonl"); - let compacted = RolloutItem::Compacted(CompactedItem { + let compacted = RolloutItem::Compacted(Box::new(CompactedItem { message: "x".repeat(MAX_LEGACY_TRANSCRIPT_PREVIEW_SCAN_BYTES / 8), replacement_history: None, retained_context: None, @@ -254,7 +254,7 @@ fn legacy_transcript_preview_falls_back_when_scan_budget_is_exhausted() { compaction_response_id: None, latest_token_usage_record: None, resume_metadata: None, - }); + })); let mut items = vec![rollout_user_message("older user")]; items.extend(std::iter::repeat_n(compacted, 9)); items.push(rollout_agent_message("recent assistant"));