Fix/filter audience 6703 local (#6773)

Signed-off-by: rabi <ramishra@redhat.com>
Co-authored-by: rabi <ramishra@redhat.com>
Co-authored-by: Douwe Osinga <douwe@squareup.com>
This commit is contained in:
Douwe Osinga
2026-01-28 15:49:52 -05:00
committed by GitHub
parent 14b3cd00e7
commit 2bc368948b
10 changed files with 40 additions and 43 deletions
+2 -4
View File
@@ -285,10 +285,8 @@ impl MessageContent {
.cloned() .cloned()
.collect(); .collect();
if filtered_content.is_empty() { // Preserve ToolResponse even when content is empty - some providers
return None; // (like Google) need to handle empty tool responses specially
}
Some(MessageContent::ToolResponse(ToolResponse { Some(MessageContent::ToolResponse(ToolResponse {
id: res.id.clone(), id: res.id.clone(),
tool_result: Ok(CallToolResult { tool_result: Ok(CallToolResult {
+3 -2
View File
@@ -79,7 +79,8 @@ fn build_input_items(messages: &[Message]) -> Result<Vec<Value>> {
let mut items = Vec::new(); let mut items = Vec::new();
for message in messages.iter().filter(|m| m.is_agent_visible()) { for message in messages.iter().filter(|m| m.is_agent_visible()) {
let role = match message.role { let filtered = message.agent_visible_content();
let role = match filtered.role {
Role::User => Some("user"), Role::User => Some("user"),
Role::Assistant => Some("assistant"), Role::Assistant => Some("assistant"),
}; };
@@ -95,7 +96,7 @@ fn build_input_items(messages: &[Message]) -> Result<Vec<Value>> {
} }
}; };
for content in &message.content { for content in &filtered.content {
match content { match content {
MessageContent::Text(text) => { MessageContent::Text(text) => {
if !text.text.is_empty() { if !text.text.is_empty() {
+3 -2
View File
@@ -65,13 +65,14 @@ impl CursorAgentProvider {
// Add conversation history // Add conversation history
for message in messages.iter().filter(|m| m.is_agent_visible()) { for message in messages.iter().filter(|m| m.is_agent_visible()) {
let role_prefix = match message.role { let filtered = message.agent_visible_content();
let role_prefix = match filtered.role {
Role::User => "Human: ", Role::User => "Human: ",
Role::Assistant => "Assistant: ", Role::Assistant => "Assistant: ",
}; };
full_prompt.push_str(role_prefix); full_prompt.push_str(role_prefix);
for content in &message.content { for content in &filtered.content {
match content { match content {
MessageContent::Text(text_content) => { MessageContent::Text(text_content) => {
full_prompt.push_str(&text_content.text); full_prompt.push_str(&text_content.text);
@@ -34,7 +34,13 @@ const DATA_FIELD: &str = "data";
pub fn format_messages(messages: &[Message]) -> Vec<Value> { pub fn format_messages(messages: &[Message]) -> Vec<Value> {
let mut anthropic_messages = Vec::new(); let mut anthropic_messages = Vec::new();
for message in messages.iter().filter(|m| m.is_agent_visible()) { let filtered_messages: Vec<Message> = messages
.iter()
.filter(|m| m.is_agent_visible())
.map(|m| m.agent_visible_content())
.collect();
for message in &filtered_messages {
let role = match message.role { let role = match message.role {
Role::User => USER_ROLE, Role::User => USER_ROLE,
Role::Assistant => ASSISTANT_ROLE, Role::Assistant => ASSISTANT_ROLE,
@@ -18,10 +18,12 @@ use super::super::base::Usage;
use crate::conversation::message::{Message, MessageContent}; use crate::conversation::message::{Message, MessageContent};
pub fn to_bedrock_message(message: &Message) -> Result<bedrock::Message> { pub fn to_bedrock_message(message: &Message) -> Result<bedrock::Message> {
let filtered = message.agent_visible_content();
bedrock::Message::builder() bedrock::Message::builder()
.role(to_bedrock_role(&message.role)) .role(to_bedrock_role(&filtered.role))
.set_content(Some( .set_content(Some(
message filtered
.content .content
.iter() .iter()
.map(to_bedrock_message_content) .map(to_bedrock_message_content)
@@ -90,11 +92,6 @@ pub fn to_bedrock_message_content(content: &MessageContent) -> Result<bedrock::C
result result
.content .content
.iter() .iter()
// Filter out content items that have User in their audience
.filter(|c| {
c.audience()
.is_none_or(|audience| !audience.contains(&Role::User))
})
.map(|c| to_bedrock_tool_result_content_block(&tool_res.id, c.clone())) .map(|c| to_bedrock_tool_result_content_block(&tool_res.id, c.clone()))
.collect::<Result<_>>()?, .collect::<Result<_>>()?,
), ),
@@ -44,12 +44,7 @@ fn format_tool_response(
match &response.tool_result { match &response.tool_result {
Ok(call_result) => { Ok(call_result) => {
let abridged: Vec<_> = call_result let abridged: Vec<_> = call_result.content.iter().map(|c| c.raw.clone()).collect();
.content
.iter()
.filter(|c| c.audience().is_none_or(|a| a.contains(&Role::Assistant)))
.map(|c| c.raw.clone())
.collect();
let mut tool_content = Vec::new(); let mut tool_content = Vec::new();
let mut image_messages = Vec::new(); let mut image_messages = Vec::new();
@@ -112,9 +107,10 @@ fn format_tool_response(
fn format_messages(messages: &[Message], image_format: &ImageFormat) -> Vec<DatabricksMessage> { fn format_messages(messages: &[Message], image_format: &ImageFormat) -> Vec<DatabricksMessage> {
let mut result = Vec::new(); let mut result = Vec::new();
for message in messages.iter().filter(|m| m.is_agent_visible()) { for message in messages.iter().filter(|m| m.is_agent_visible()) {
let filtered = message.agent_visible_content();
let mut converted = DatabricksMessage { let mut converted = DatabricksMessage {
content: Value::Null, content: Value::Null,
role: match message.role { role: match filtered.role {
Role::User => "user".to_string(), Role::User => "user".to_string(),
Role::Assistant => "assistant".to_string(), Role::Assistant => "assistant".to_string(),
}, },
@@ -126,7 +122,7 @@ fn format_messages(messages: &[Message], image_format: &ImageFormat) -> Vec<Data
let mut has_tool_calls = false; let mut has_tool_calls = false;
let mut has_multiple_content = false; let mut has_multiple_content = false;
for content in &message.content { for content in &filtered.content {
match content { match content {
MessageContent::Text(text) => { MessageContent::Text(text) => {
if !text.text.is_empty() { if !text.text.is_empty() {
+4 -13
View File
@@ -60,15 +60,16 @@ struct StreamingChunk {
pub fn format_messages(messages: &[Message], image_format: &ImageFormat) -> Vec<Value> { pub fn format_messages(messages: &[Message], image_format: &ImageFormat) -> Vec<Value> {
let mut messages_spec = Vec::new(); let mut messages_spec = Vec::new();
for message in messages.iter().filter(|m| m.is_agent_visible()) { for message in messages.iter().filter(|m| m.is_agent_visible()) {
let filtered = message.agent_visible_content();
let mut converted = json!({ let mut converted = json!({
"role": message.role "role": filtered.role
}); });
let mut output = Vec::new(); let mut output = Vec::new();
let mut content_array = Vec::new(); let mut content_array = Vec::new();
let mut text_array = Vec::new(); let mut text_array = Vec::new();
for content in &message.content { for content in &filtered.content {
match content { match content {
MessageContent::Text(text) => { MessageContent::Text(text) => {
if !text.text.is_empty() { if !text.text.is_empty() {
@@ -135,17 +136,7 @@ pub fn format_messages(messages: &[Message], image_format: &ImageFormat) -> Vec<
MessageContent::ToolResponse(response) => { MessageContent::ToolResponse(response) => {
match &response.tool_result { match &response.tool_result {
Ok(result) => { Ok(result) => {
// Send only contents with no audience or with Assistant in the audience let abridged: Vec<_> = result.content.to_vec();
let abridged: Vec<_> = result
.content
.iter()
.filter(|content| {
content
.audience()
.is_none_or(|audience| audience.contains(&Role::Assistant))
})
.cloned()
.collect();
// Process all content, replacing images with placeholder text // Process all content, replacing images with placeholder text
let mut tool_content = Vec::new(); let mut tool_content = Vec::new();
@@ -307,7 +307,8 @@ fn add_function_calls(input_items: &mut Vec<Value>, messages: &[Message]) {
fn add_function_call_outputs(input_items: &mut Vec<Value>, messages: &[Message]) { fn add_function_call_outputs(input_items: &mut Vec<Value>, messages: &[Message]) {
for message in messages.iter().filter(|m| m.is_agent_visible()) { for message in messages.iter().filter(|m| m.is_agent_visible()) {
for content in &message.content { let filtered = message.agent_visible_content();
for content in &filtered.content {
if let MessageContent::ToolResponse(response) = content { if let MessageContent::ToolResponse(response) = content {
match &response.tool_result { match &response.tool_result {
Ok(contents) => { Ok(contents) => {
@@ -12,8 +12,13 @@ use std::collections::HashSet;
pub fn format_messages(messages: &[Message]) -> Vec<Value> { pub fn format_messages(messages: &[Message]) -> Vec<Value> {
let mut snowflake_messages = Vec::new(); let mut snowflake_messages = Vec::new();
// Convert messages to Snowflake format let filtered_messages: Vec<Message> = messages
for message in messages.iter().filter(|m| m.is_agent_visible()) { .iter()
.filter(|m| m.is_agent_visible())
.map(|m| m.agent_visible_content())
.collect();
for message in &filtered_messages {
let role = match message.role { let role = match message.role {
Role::User => "user", Role::User => "user",
Role::Assistant => "assistant", Role::Assistant => "assistant",
+4 -3
View File
@@ -321,10 +321,11 @@ pub fn convert_tool_messages_to_text(messages: &[Message]) -> Conversation {
let converted_messages: Vec<Message> = messages let converted_messages: Vec<Message> = messages
.iter() .iter()
.map(|message| { .map(|message| {
let filtered = message.agent_visible_content();
let mut new_content = Vec::new(); let mut new_content = Vec::new();
let mut has_tool_content = false; let mut has_tool_content = false;
for content in &message.content { for content in &filtered.content {
match content { match content {
MessageContent::ToolRequest(req) => { MessageContent::ToolRequest(req) => {
has_tool_content = true; has_tool_content = true;
@@ -369,9 +370,9 @@ pub fn convert_tool_messages_to_text(messages: &[Message]) -> Conversation {
} }
if has_tool_content { if has_tool_content {
Message::new(message.role.clone(), message.created, new_content) Message::new(filtered.role.clone(), filtered.created, new_content)
} else { } else {
message.clone() filtered
} }
}) })
.collect(); .collect();