agent: Account for tool use messages without any corresponding text (#27917)

This PR makes it so if we receive a tool use from the model without any
corresponding text, we'll insert some placeholder text to keep the
conversation in a well-structured format.

This aims to fix an error that Antonio was seeing:


![image](https://github.com/user-attachments/assets/eeba95ef-9b67-41d7-bce3-afe84bcdc7b1)

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2025-04-02 08:56:50 -04:00 committed by GitHub
parent 5dcd0d37a6
commit 2846c55cde
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -124,6 +124,15 @@ pub enum MessageSegment {
Thinking(String), Thinking(String),
} }
impl MessageSegment {
pub fn text_mut(&mut self) -> &mut String {
match self {
Self::Text(text) => text,
Self::Thinking(text) => text,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProjectSnapshot { pub struct ProjectSnapshot {
pub worktree_snapshots: Vec<WorktreeSnapshot>, pub worktree_snapshots: Vec<WorktreeSnapshot>,
@ -1076,18 +1085,32 @@ impl Thread {
} }
} }
LanguageModelCompletionEvent::ToolUse(tool_use) => { LanguageModelCompletionEvent::ToolUse(tool_use) => {
let last_assistant_message_id = thread let last_assistant_message = thread
.messages .messages
.iter() .iter_mut()
.rfind(|message| message.role == Role::Assistant) .rfind(|message| message.role == Role::Assistant);
.map(|message| message.id)
.unwrap_or_else(|| { let last_assistant_message_id =
if let Some(message) = last_assistant_message {
if let Some(segment) = message.segments.first_mut() {
let text = segment.text_mut();
if text.is_empty() {
text.push_str("Using tool...");
}
} else {
message.segments.push(MessageSegment::Text(
"Using tool...".to_string(),
));
}
message.id
} else {
thread.insert_message( thread.insert_message(
Role::Assistant, Role::Assistant,
vec![MessageSegment::Text("Using tool...".to_string())], vec![MessageSegment::Text("Using tool...".to_string())],
cx, cx,
) )
}); };
thread.tool_use.request_tool_use( thread.tool_use.request_tool_use(
last_assistant_message_id, last_assistant_message_id,
tool_use, tool_use,