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
19 changes: 15 additions & 4 deletions codex-rs/core/src/codex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4010,7 +4010,11 @@ pub(crate) async fn run_turn(
}

// Construct the input that we will send to the model.
let sampling_request_input: Vec<ResponseItem> = { sess.clone_history().await.for_prompt() };
let sampling_request_input: Vec<ResponseItem> = {
sess.clone_history()
.await
.for_prompt(&turn_context.model_info.input_modalities)
};

let sampling_request_input_messages = sampling_request_input
.iter()
Expand Down Expand Up @@ -6923,7 +6927,9 @@ mod tests {
rollout_items.push(RolloutItem::ResponseItem(assistant1.clone()));

let summary1 = "summary one";
let snapshot1 = live_history.clone().for_prompt();
let snapshot1 = live_history
.clone()
.for_prompt(&reconstruction_turn.model_info.input_modalities);
let user_messages1 = collect_user_messages(&snapshot1);
let rebuilt1 =
compact::build_compacted_history(initial_context.clone(), &user_messages1, summary1);
Expand Down Expand Up @@ -6964,7 +6970,9 @@ mod tests {
rollout_items.push(RolloutItem::ResponseItem(assistant2.clone()));

let summary2 = "summary two";
let snapshot2 = live_history.clone().for_prompt();
let snapshot2 = live_history
.clone()
.for_prompt(&reconstruction_turn.model_info.input_modalities);
let user_messages2 = collect_user_messages(&snapshot2);
let rebuilt2 =
compact::build_compacted_history(initial_context.clone(), &user_messages2, summary2);
Expand Down Expand Up @@ -7004,7 +7012,10 @@ mod tests {
);
rollout_items.push(RolloutItem::ResponseItem(assistant3));

(rollout_items, live_history.for_prompt())
(
rollout_items,
live_history.for_prompt(&reconstruction_turn.model_info.input_modalities),
)
}

#[tokio::test]
Expand Down
4 changes: 3 additions & 1 deletion codex-rs/core/src/compact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@ async fn run_compact_task_inner(

loop {
// Clone is required because of the loop
let turn_input = history.clone().for_prompt();
let turn_input = history
.clone()
.for_prompt(&turn_context.model_info.input_modalities);
let turn_input_len = turn_input.len();
let prompt = Prompt {
input: turn_input,
Expand Down
2 changes: 1 addition & 1 deletion codex-rs/core/src/compact_remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ async fn run_remote_compact_task_inner_impl(
.collect();

let prompt = Prompt {
input: history.for_prompt(),
input: history.for_prompt(&turn_context.model_info.input_modalities),
tools: vec![],
parallel_tool_calls: false,
base_instructions,
Expand Down
15 changes: 11 additions & 4 deletions codex-rs/core/src/context_manager/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use codex_protocol::models::FunctionCallOutputBody;
use codex_protocol::models::FunctionCallOutputContentItem;
use codex_protocol::models::FunctionCallOutputPayload;
use codex_protocol::models::ResponseItem;
use codex_protocol::openai_models::InputModality;
use codex_protocol::protocol::TokenUsage;
use codex_protocol::protocol::TokenUsageInfo;
use std::ops::Deref;
Expand Down Expand Up @@ -79,9 +80,11 @@ impl ContextManager {
}

/// Returns the history prepared for sending to the model. This applies a proper
/// normalization and drop un-suited items.
pub(crate) fn for_prompt(mut self) -> Vec<ResponseItem> {
self.normalize_history();
/// normalization and drops un-suited items. When `input_modalities` does not
/// include `InputModality::Image`, images are stripped from messages and tool
/// outputs.
pub(crate) fn for_prompt(mut self, input_modalities: &[InputModality]) -> Vec<ResponseItem> {
self.normalize_history(input_modalities);
self.items
.retain(|item| !matches!(item, ResponseItem::GhostSnapshot { .. }));
self.items
Expand Down Expand Up @@ -309,12 +312,16 @@ impl ContextManager {
/// This function enforces a couple of invariants on the in-memory history:
/// 1. every call (function/custom) has a corresponding output entry
/// 2. every output has a corresponding call entry
fn normalize_history(&mut self) {
/// 3. when images are unsupported, image content is stripped from messages and tool outputs
fn normalize_history(&mut self, input_modalities: &[InputModality]) {
// all function/tool calls must have a corresponding output
normalize::ensure_call_outputs_present(&mut self.items);

// all outputs must have a corresponding function/tool call
normalize::remove_orphan_outputs(&mut self.items);

// strip images when model does not support them
normalize::strip_images_when_unsupported(input_modalities, &mut self.items);
}

fn process_item(&self, item: &ResponseItem, policy: TruncationPolicy) -> ResponseItem {
Expand Down
Loading
Loading