This commit is contained in:
jif-oai
2026-01-09 19:23:33 +00:00
parent 48502af5a2
commit 4c1703dfad
2 changed files with 44 additions and 44 deletions

View File

@@ -156,7 +156,6 @@ use codex_async_utils::OrCancelExt;
use codex_otel::OtelManager;
use codex_protocol::config_types::ReasoningSummary as ReasoningSummaryConfig;
use codex_protocol::models::ContentItem;
use codex_protocol::models::FunctionCallOutputContentItem;
use codex_protocol::models::ResponseInputItem;
use codex_protocol::models::ResponseItem;
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
@@ -1552,39 +1551,6 @@ impl Session {
}
}
pub(crate) async fn current_turn_images_tool_only(&self) -> bool {
let history = self.state.lock().await.clone_history();
let mut saw_user = false;
let mut saw_tool = false;
for item in history.raw_items().iter().rev() {
match item {
ResponseItem::Message { role, content, .. } => {
if role == "assistant" {
break;
}
if role == "user"
&& content
.iter()
.any(|item| matches!(item, ContentItem::InputImage { .. }))
{
saw_user = true;
}
}
ResponseItem::FunctionCallOutput { output, .. } => {
if let Some(items) = &output.content_items
&& items.iter().any(|item| {
matches!(item, FunctionCallOutputContentItem::InputImage { .. })
})
{
saw_tool = true;
}
}
_ => {}
}
}
saw_tool && !saw_user
}
pub async fn list_resources(
&self,
server: &str,
@@ -2483,19 +2449,25 @@ pub(crate) async fn run_turn(
break;
}
Err(CodexErr::InvalidImageRequest()) => {
if sess.current_turn_images_tool_only().await {
let tool_only = {
let mut state = sess.state.lock().await;
error_or_panic(
"Invalid image detected, replacing it in the last turn to prevent poisoning",
);
let tool_only = state.history.current_turn_images_tool_only();
error_or_panic(if tool_only {
"Invalid image detected, replacing it in the last turn to prevent poisoning"
} else {
"Invalid user image detected; replacing it in the last turn to prevent poisoning"
});
state.history.replace_last_turn_images("Invalid image");
} else {
let err = CodexErr::InvalidImageRequest();
info!("Turn error: {err:#}");
let event = EventMsg::Error(err.to_error_event(None));
sess.send_event(&turn_context, event).await;
break;
tool_only
};
if tool_only {
continue;
}
let err = CodexErr::InvalidImageRequest();
info!("Turn error: {err:#}");
let event = EventMsg::Error(err.to_error_event(None));
sess.send_event(&turn_context, event).await;
break;
}
Err(e) => {
info!("Turn error: {e:#}");

View File

@@ -155,6 +155,34 @@ impl ContextManager {
}
}
pub(crate) fn current_turn_images_tool_only(&self) -> bool {
let mut saw_tool = false;
for item in self.items.iter().rev() {
match item {
ResponseItem::Message { role, .. } if role == "assistant" => break,
ResponseItem::Message { role, content, .. } if role == "user" => {
if content
.iter()
.any(|item| matches!(item, ContentItem::InputImage { .. }))
{
return false;
}
}
ResponseItem::FunctionCallOutput { output, .. } => {
if output.content_items.as_ref().map_or(false, |items| {
items.iter().any(|item| {
matches!(item, FunctionCallOutputContentItem::InputImage { .. })
})
}) {
saw_tool = true;
}
}
_ => {}
}
}
saw_tool
}
/// Drop the last `num_turns` user turns from this history.
///
/// "User turns" are identified as `ResponseItem::Message` entries whose role is `"user"`.