From 0270dd3a1aa0d82abd00273c2ed7dae14fea5b41 Mon Sep 17 00:00:00 2001 From: Douwe Osinga Date: Wed, 28 Jan 2026 12:55:46 -0500 Subject: [PATCH] Fix/GitHub copilot error handling 5845 (#6771) Signed-off-by: albina-popova <97168987+albina-popova@users.noreply.github.com> Co-authored-by: albina-popova <97168987+albina-popova@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 Co-authored-by: Douwe Osinga --- crates/goose/src/providers/formats/openai.rs | 43 ++++++++++++++++---- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/crates/goose/src/providers/formats/openai.rs b/crates/goose/src/providers/formats/openai.rs index b00a2f89..bae0a380 100644 --- a/crates/goose/src/providers/formats/openai.rs +++ b/crates/goose/src/providers/formats/openai.rs @@ -72,10 +72,14 @@ pub fn format_messages(messages: &[Message], image_format: &ImageFormat) -> Vec< match content { MessageContent::Text(text) => { if !text.text.is_empty() { - if let Some(image_path) = detect_image_path(&text.text) { - if let Ok(image) = load_image_file(image_path) { - content_array.push(json!({"type": "text", "text": text.text})); - content_array.push(convert_image(&image, image_format)); + if message.role == Role::User { + if let Some(image_path) = detect_image_path(&text.text) { + if let Ok(image) = load_image_file(image_path) { + content_array.push(json!({"type": "text", "text": text.text})); + content_array.push(convert_image(&image, image_format)); + } else { + text_array.push(text.text.clone()); + } } else { text_array.push(text.text.clone()); } @@ -204,7 +208,14 @@ pub fn format_messages(messages: &[Message], image_format: &ImageFormat) -> Vec< MessageContent::ToolConfirmationRequest(_) => {} MessageContent::ActionRequired(_) => {} MessageContent::Image(image) => { - content_array.push(convert_image(image, image_format)); + if message.role == Role::User { + content_array.push(convert_image(image, image_format)); + } else { + content_array.push(json!({ + "type": "text", + "text": "[Image content removed - not supported in assistant messages]" + })); + } } MessageContent::FrontendToolRequest(request) => match &request.tool_call { Ok(tool_call) => { @@ -1031,9 +1042,9 @@ mod tests { std::fs::write(&png_path, png_data)?; let png_path_str = png_path.to_str().unwrap(); - // Create message with image path - let message = Message::user().with_text(format!("Here is an image: {}", png_path_str)); - let spec = format_messages(&[message], &ImageFormat::OpenAi); + // Create user message with image path - should load the image + let user_message = Message::user().with_text(format!("Here is an image: {}", png_path_str)); + let spec = format_messages(&[user_message], &ImageFormat::OpenAi); assert_eq!(spec.len(), 1); assert_eq!(spec[0]["role"], "user"); @@ -1049,6 +1060,22 @@ mod tests { .unwrap() .starts_with("data:image/png;base64,")); + // Create assistant message with same text - should NOT load the image + let assistant_message = + Message::assistant().with_text(format!("I saved the output to {}", png_path_str)); + let spec = format_messages(&[assistant_message], &ImageFormat::OpenAi); + + assert_eq!(spec.len(), 1); + assert_eq!(spec[0]["role"], "assistant"); + + // Content should be plain text, NOT an array with image + let content = spec[0]["content"].as_str(); + assert!( + content.is_some(), + "Assistant message content should be a string, not an array with image" + ); + assert!(content.unwrap().contains(png_path_str)); + Ok(()) }