mirror of
https://github.com/openai/codex.git
synced 2026-06-01 19:02:59 +00:00
feat: retroactive image placeholder to prevent poisoning (#6774)
If an image can't be read by the API, it will poison the entire history, preventing any new turn on the conversation. This detect such cases and replace the image by a placeholder
This commit is contained in:
@@ -5,6 +5,8 @@ use crate::truncate::approx_token_count;
|
||||
use crate::truncate::approx_tokens_from_byte_count;
|
||||
use crate::truncate::truncate_function_output_items_with_policy;
|
||||
use crate::truncate::truncate_text;
|
||||
use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::FunctionCallOutputContentItem;
|
||||
use codex_protocol::models::FunctionCallOutputPayload;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::protocol::TokenUsage;
|
||||
@@ -118,6 +120,37 @@ impl ContextManager {
|
||||
self.items = items;
|
||||
}
|
||||
|
||||
pub(crate) fn replace_last_turn_images(&mut self, placeholder: &str) {
|
||||
let Some(last_item) = self.items.last_mut() else {
|
||||
return;
|
||||
};
|
||||
|
||||
match last_item {
|
||||
ResponseItem::Message { role, content, .. } if role == "user" => {
|
||||
for item in content.iter_mut() {
|
||||
if matches!(item, ContentItem::InputImage { .. }) {
|
||||
*item = ContentItem::InputText {
|
||||
text: placeholder.to_string(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
ResponseItem::FunctionCallOutput { output, .. } => {
|
||||
let Some(content_items) = output.content_items.as_mut() else {
|
||||
return;
|
||||
};
|
||||
for item in content_items.iter_mut() {
|
||||
if matches!(item, FunctionCallOutputContentItem::InputImage { .. }) {
|
||||
*item = FunctionCallOutputContentItem::InputText {
|
||||
text: placeholder.to_string(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn update_token_info(
|
||||
&mut self,
|
||||
usage: &TokenUsage,
|
||||
|
||||
Reference in New Issue
Block a user