Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions codex-rs/app-server-protocol/src/protocol/thread_history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3341,6 +3341,8 @@ mod tests {
message: String::new(),
replacement_history: None,
window_number: None,
first_window_id: None,
previous_window_id: None,
window_id: None,
}),
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
Expand Down
2 changes: 2 additions & 0 deletions codex-rs/core/src/agent/control_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,8 @@ async fn spawn_agent_fork_strips_parent_usage_hints_from_compacted_history() {
message: String::new(),
replacement_history: Some(replacement_history),
window_number: None,
first_window_id: None,
previous_window_id: None,
window_id: None,
}),
RolloutItem::TurnContext(turn_context.to_turn_context_item()),
Expand Down
6 changes: 4 additions & 2 deletions codex-rs/core/src/compact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ async fn run_compact_task_inner_impl(
let user_messages = collect_user_messages(history_items);

let mut new_history = build_compacted_history(Vec::new(), &user_messages, &summary_text);
let (window_number, window_id) = sess.advance_auto_compact_window().await;
let (window_number, window_ids) = sess.advance_auto_compact_window().await;

if matches!(
initial_context_injection,
Expand All @@ -320,7 +320,9 @@ async fn run_compact_task_inner_impl(
message: summary_text.clone(),
replacement_history: Some(new_history.clone()),
window_number: Some(window_number),
window_id: Some(window_id),
first_window_id: Some(window_ids.first_window_id.to_string()),
previous_window_id: window_ids.previous_window_id.map(|id| id.to_string()),
window_id: Some(window_ids.window_id.to_string()),
};
sess.replace_compacted_history(
turn_context.as_ref(),
Expand Down
6 changes: 4 additions & 2 deletions codex-rs/core/src/compact_remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ async fn run_remote_compact_task_inner_impl(
&responses_metadata,
)
.await?;
let (new_window_number, new_window_id) = sess.advance_auto_compact_window().await;
let (new_window_number, new_window_ids) = sess.advance_auto_compact_window().await;
new_history = process_compacted_history(
sess.as_ref(),
turn_context.as_ref(),
Expand All @@ -275,7 +275,9 @@ async fn run_remote_compact_task_inner_impl(
message: String::new(),
replacement_history: Some(new_history.clone()),
window_number: Some(new_window_number),
window_id: Some(new_window_id),
first_window_id: Some(new_window_ids.first_window_id.to_string()),
previous_window_id: new_window_ids.previous_window_id.map(|id| id.to_string()),
window_id: Some(new_window_ids.window_id.to_string()),
};
// Install is the semantic boundary where the compact endpoint's output becomes live
// thread history. Keep it distinct from the later inference request so the reducer can
Expand Down
6 changes: 4 additions & 2 deletions codex-rs/core/src/compact_remote_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ async fn run_remote_compact_task_inner_impl(
let (compacted_history, retained_images) =
build_v2_compacted_history(&prompt_input, compaction_output);
analytics_details.retained_image_count = Some(retained_images);
let (new_window_number, new_window_id) = sess.advance_auto_compact_window().await;
let (new_window_number, new_window_ids) = sess.advance_auto_compact_window().await;
let new_history = process_compacted_history(
sess.as_ref(),
turn_context.as_ref(),
Expand All @@ -309,7 +309,9 @@ async fn run_remote_compact_task_inner_impl(
message: String::new(),
replacement_history: Some(new_history.clone()),
window_number: Some(new_window_number),
window_id: Some(new_window_id),
first_window_id: Some(new_window_ids.first_window_id.to_string()),
previous_window_id: new_window_ids.previous_window_id.map(|id| id.to_string()),
window_id: Some(new_window_ids.window_id.to_string()),
};
compaction_trace.record_installed(&CompactionCheckpointTracePayload {
input_history: &trace_input_history,
Expand Down
18 changes: 16 additions & 2 deletions codex-rs/core/src/context/token_budget_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,24 @@ use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct TokenBudgetContext {
thread_id: ThreadId,
first_window_id: Uuid,
previous_window_id: Option<Uuid>,
window_id: Uuid,
tokens_left: i64,
}

impl TokenBudgetContext {
pub(crate) fn new(thread_id: ThreadId, window_id: Uuid, tokens_left: i64) -> Self {
pub(crate) fn new(
thread_id: ThreadId,
first_window_id: Uuid,
previous_window_id: Option<Uuid>,
window_id: Uuid,
tokens_left: i64,
) -> Self {
Self {
thread_id,
first_window_id,
previous_window_id,
window_id,
tokens_left,
}
Expand All @@ -34,10 +44,14 @@ impl ContextualUserFragment for TokenBudgetContext {

fn body(&self) -> String {
let thread_id = self.thread_id;
let first_window_id = self.first_window_id;
let previous_window_id = self
.previous_window_id
.map_or_else(|| "none".to_string(), |window_id| window_id.to_string());
let window_id = self.window_id;
let tokens_left = self.tokens_left;
format!(
"Thread id {thread_id}.\nCurrent context window id {window_id}.\nYou have {tokens_left} tokens left in this context window."
"Thread id {thread_id}.\nFirst context window id {first_window_id}.\nPrevious context window id {previous_window_id}.\nCurrent context window id {window_id}.\nYou have {tokens_left} tokens left in this context window."
)
}
}
Expand Down
34 changes: 24 additions & 10 deletions codex-rs/core/src/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ use crate::session_startup_prewarm::SessionStartupPrewarmHandle;
use crate::shell;
#[cfg(test)]
use crate::skills::SkillLoadOutcome;
use crate::state::AutoCompactWindowIds;
use crate::state::AutoCompactWindowSnapshot;
use crate::state::PendingRequestPermissions;
use crate::state::SessionServices;
Expand Down Expand Up @@ -1364,6 +1365,8 @@ impl Session {
previous_turn_settings,
reference_context_item,
window_number,
first_window_id,
previous_window_id,
window_id,
} = self
.reconstruct_history_from_rollout(turn_context, rollout_items)
Expand All @@ -1382,8 +1385,16 @@ impl Session {
{
let mut state = self.state.lock().await;
state.replace_history(history, reference_context_item);
let window_id = window_id.unwrap_or_else(|| state.auto_compact_window_id());
state.restore_auto_compact_window(window_number, window_id);
let fallback_ids = state.auto_compact_window_ids();
let window_id = window_id.unwrap_or(fallback_ids.window_id);
state.restore_auto_compact_window(
window_number,
AutoCompactWindowIds {
first_window_id: first_window_id.unwrap_or(window_id),
Comment thread
pakrym-oai marked this conversation as resolved.
previous_window_id,
window_id,
},
);
state.set_previous_turn_settings(previous_turn_settings.clone());
}
let prefix_tokens = if matches!(
Expand Down Expand Up @@ -3011,7 +3022,7 @@ impl Session {
collaboration_mode,
base_instructions,
session_source,
auto_compact_window_id,
auto_compact_window_ids,
) = {
let state = self.state.lock().await;
(
Expand All @@ -3020,7 +3031,7 @@ impl Session {
state.session_configuration.collaboration_mode.clone(),
state.session_configuration.base_instructions.clone(),
state.session_configuration.session_source.clone(),
state.auto_compact_window_id(),
state.auto_compact_window_ids(),
)
};
if let Some(model_switch_message) =
Expand Down Expand Up @@ -3210,7 +3221,9 @@ impl Session {
developer_sections.push(
crate::context::TokenBudgetContext::new(
self.thread_id(),
auto_compact_window_id,
auto_compact_window_ids.first_window_id,
auto_compact_window_ids.previous_window_id,
auto_compact_window_ids.window_id,
model_context_window,
)
.render(),
Expand Down Expand Up @@ -3309,10 +3322,9 @@ impl Session {
format!("{thread_id}:{window_number}")
}

pub(crate) async fn advance_auto_compact_window(&self) -> (u64, String) {
pub(crate) async fn advance_auto_compact_window(&self) -> (u64, AutoCompactWindowIds) {
let mut state = self.state.lock().await;
let (window_number, window_id) = state.advance_auto_compact_window();
(window_number, window_id.to_string())
state.advance_auto_compact_window()
}

pub(crate) async fn request_new_context_window(&self) {
Expand All @@ -3328,7 +3340,7 @@ impl Session {
let mut state = self.state.lock().await;
state.start_new_context_window_if_requested()
};
let (window_number, window_id) = window?;
let (window_number, window_ids) = window?;
let context_items = self.build_initial_context(turn_context).await;
let turn_context_item = turn_context.to_turn_context_item();
let replacement_history = context_items;
Expand All @@ -3341,7 +3353,9 @@ impl Session {
message: String::new(),
replacement_history: Some(replacement_history),
window_number: Some(window_number),
window_id: Some(window_id.to_string()),
first_window_id: Some(window_ids.first_window_id.to_string()),
previous_window_id: window_ids.previous_window_id.map(|id| id.to_string()),
window_id: Some(window_ids.window_id.to_string()),
}),
RolloutItem::TurnContext(turn_context_item),
])
Expand Down
13 changes: 13 additions & 0 deletions codex-rs/core/src/session/rollout_reconstruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@ pub(super) struct RolloutReconstruction {
pub(super) previous_turn_settings: Option<PreviousTurnSettings>,
pub(super) reference_context_item: Option<TurnContextItem>,
pub(super) window_number: u64,
pub(super) first_window_id: Option<Uuid>,
pub(super) previous_window_id: Option<Uuid>,
pub(super) window_id: Option<Uuid>,
}

#[derive(Debug, Clone, Copy)]
struct ReconstructedWindow {
number: u64,
first_id: Option<Uuid>,
previous_id: Option<Uuid>,
id: Option<Uuid>,
}

Expand Down Expand Up @@ -133,6 +137,11 @@ impl Session {
{
active_segment.window = Some(ReconstructedWindow {
number: window_number,
first_id: compacted.first_window_id.as_deref().and_then(parse_uuid_v7),
previous_id: compacted
.previous_window_id
.as_deref()
.and_then(parse_uuid_v7),
id: compacted.window_id.as_deref().and_then(parse_uuid_v7),
});
}
Expand Down Expand Up @@ -341,13 +350,17 @@ impl Session {

let window = window.unwrap_or(ReconstructedWindow {
number: fallback_window_number,
first_id: None,
previous_id: None,
id: None,
});
RolloutReconstruction {
history: history.raw_items().to_vec(),
previous_turn_settings,
reference_context_item,
window_number: window.number,
first_window_id: window.first_id,
previous_window_id: window.previous_id,
window_id: window.id,
}
}
Expand Down
16 changes: 16 additions & 0 deletions codex-rs/core/src/session/rollout_reconstruction_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,8 @@ async fn record_initial_history_resumed_rollback_drops_incomplete_user_turn_comp
message: String::new(),
replacement_history: Some(Vec::new()),
window_number: None,
first_window_id: None,
previous_window_id: None,
window_id: None,
}),
RolloutItem::EventMsg(EventMsg::ThreadRolledBack(
Expand Down Expand Up @@ -887,6 +889,8 @@ async fn record_initial_history_resumed_does_not_seed_reference_context_item_aft
message: String::new(),
replacement_history: Some(Vec::new()),
window_number: None,
first_window_id: None,
previous_window_id: None,
window_id: None,
}),
];
Expand Down Expand Up @@ -914,6 +918,8 @@ async fn reconstruct_history_legacy_compaction_without_replacement_history_does_
message: "legacy summary".to_string(),
replacement_history: None,
window_number: None,
first_window_id: None,
previous_window_id: None,
window_id: None,
}),
];
Expand Down Expand Up @@ -947,6 +953,8 @@ async fn reconstruct_history_legacy_compaction_without_replacement_history_clear
message: "legacy summary".to_string(),
replacement_history: None,
window_number: None,
first_window_id: None,
previous_window_id: None,
window_id: None,
}),
RolloutItem::EventMsg(EventMsg::TurnStarted(
Expand Down Expand Up @@ -1043,6 +1051,8 @@ async fn record_initial_history_resumed_turn_context_after_compaction_reestablis
message: String::new(),
replacement_history: Some(Vec::new()),
window_number: None,
first_window_id: None,
previous_window_id: None,
window_id: None,
}),
RolloutItem::TurnContext(previous_context_item),
Expand Down Expand Up @@ -1196,6 +1206,8 @@ async fn record_initial_history_resumed_aborted_turn_without_id_clears_active_tu
message: String::new(),
replacement_history: Some(Vec::new()),
window_number: None,
first_window_id: None,
previous_window_id: None,
window_id: None,
}),
];
Expand Down Expand Up @@ -1433,6 +1445,8 @@ async fn record_initial_history_resumed_trailing_incomplete_turn_compaction_clea
message: String::new(),
replacement_history: Some(Vec::new()),
window_number: None,
first_window_id: None,
previous_window_id: None,
window_id: None,
}),
];
Expand Down Expand Up @@ -1599,6 +1613,8 @@ async fn record_initial_history_resumed_replaced_incomplete_compacted_turn_clear
message: String::new(),
replacement_history: Some(Vec::new()),
window_number: None,
first_window_id: None,
previous_window_id: None,
window_id: None,
}),
// A newer TurnStarted replaces the incomplete compacted turn without a matching
Expand Down
Loading
Loading