mirror of
https://github.com/block/goose.git
synced 2026-07-17 12:56:20 +02:00
perf(google): avoid accumulating thoughtSignatures across conversation history (#6462)
Signed-off-by: rabi <ramishra@redhat.com>
This commit is contained in:
@@ -31,7 +31,7 @@ pub fn get_thought_signature(metadata: &Option<ProviderMetadata>) -> Option<&str
|
||||
|
||||
/// Convert internal Message format to Google's API message specification
|
||||
pub fn format_messages(messages: &[Message]) -> Vec<Value> {
|
||||
messages
|
||||
let filtered: Vec<_> = messages
|
||||
.iter()
|
||||
.filter(|m| m.is_agent_visible())
|
||||
.filter(|message| {
|
||||
@@ -42,12 +42,28 @@ pub fn format_messages(messages: &[Message]) -> Vec<Value> {
|
||||
)
|
||||
})
|
||||
})
|
||||
.map(|message| {
|
||||
.collect();
|
||||
|
||||
let last_assistant_idx = filtered
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, m)| m.role != Role::User)
|
||||
.map(|(i, _)| i)
|
||||
.next_back();
|
||||
|
||||
filtered
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, message)| {
|
||||
let role = if message.role == Role::User {
|
||||
"user"
|
||||
} else {
|
||||
"model"
|
||||
};
|
||||
let include_signature = match last_assistant_idx {
|
||||
Some(last_idx) => idx >= last_idx,
|
||||
None => false,
|
||||
};
|
||||
let mut parts = Vec::new();
|
||||
for message_content in message.content.iter() {
|
||||
match message_content {
|
||||
@@ -74,8 +90,13 @@ pub fn format_messages(messages: &[Message]) -> Vec<Value> {
|
||||
let mut part = Map::new();
|
||||
part.insert("functionCall".to_string(), json!(function_call_part));
|
||||
|
||||
if let Some(signature) = get_thought_signature(&request.metadata) {
|
||||
part.insert(THOUGHT_SIGNATURE_KEY.to_string(), json!(signature));
|
||||
if include_signature {
|
||||
if let Some(signature) = get_thought_signature(&request.metadata) {
|
||||
part.insert(
|
||||
THOUGHT_SIGNATURE_KEY.to_string(),
|
||||
json!(signature),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
parts.push(json!(part));
|
||||
@@ -144,11 +165,15 @@ pub fn format_messages(messages: &[Message]) -> Vec<Value> {
|
||||
"functionResponse".to_string(),
|
||||
json!(function_response),
|
||||
);
|
||||
if let Some(signature) = get_thought_signature(&response.metadata) {
|
||||
part.insert(
|
||||
THOUGHT_SIGNATURE_KEY.to_string(),
|
||||
json!(signature),
|
||||
);
|
||||
if include_signature {
|
||||
if let Some(signature) =
|
||||
get_thought_signature(&response.metadata)
|
||||
{
|
||||
part.insert(
|
||||
THOUGHT_SIGNATURE_KEY.to_string(),
|
||||
json!(signature),
|
||||
);
|
||||
}
|
||||
}
|
||||
parts.push(json!(part));
|
||||
}
|
||||
@@ -164,11 +189,15 @@ pub fn format_messages(messages: &[Message]) -> Vec<Value> {
|
||||
"functionResponse".to_string(),
|
||||
json!(function_response),
|
||||
);
|
||||
if let Some(signature) = get_thought_signature(&response.metadata) {
|
||||
part.insert(
|
||||
THOUGHT_SIGNATURE_KEY.to_string(),
|
||||
json!(signature),
|
||||
);
|
||||
if include_signature {
|
||||
if let Some(signature) =
|
||||
get_thought_signature(&response.metadata)
|
||||
{
|
||||
part.insert(
|
||||
THOUGHT_SIGNATURE_KEY.to_string(),
|
||||
json!(signature),
|
||||
);
|
||||
}
|
||||
}
|
||||
parts.push(json!(part));
|
||||
}
|
||||
@@ -177,7 +206,9 @@ pub fn format_messages(messages: &[Message]) -> Vec<Value> {
|
||||
MessageContent::Thinking(thinking) => {
|
||||
let mut part = Map::new();
|
||||
part.insert("text".to_string(), json!(thinking.thinking));
|
||||
part.insert("thoughtSignature".to_string(), json!(thinking.signature));
|
||||
if include_signature {
|
||||
part.insert("thoughtSignature".to_string(), json!(thinking.signature));
|
||||
}
|
||||
parts.push(json!(part));
|
||||
}
|
||||
|
||||
@@ -1230,10 +1261,21 @@ mod tests {
|
||||
Ok(tool_result("output")),
|
||||
req1.metadata.as_ref(),
|
||||
);
|
||||
let google_out = format_messages(&[native, tool_response]);
|
||||
let google_out = format_messages(&[native.clone(), tool_response.clone()]);
|
||||
assert_eq!(google_out[0]["parts"][0]["thoughtSignature"], SIG);
|
||||
assert_eq!(google_out[1]["parts"][0]["thoughtSignature"], SIG);
|
||||
|
||||
let second_assistant =
|
||||
Message::assistant().with_thinking("More thinking".to_string(), "sig_456".to_string());
|
||||
let google_multi = format_messages(&[native, tool_response, second_assistant]);
|
||||
assert!(google_multi[0]["parts"][0]
|
||||
.get("thoughtSignature")
|
||||
.is_none());
|
||||
assert!(google_multi[1]["parts"][0]
|
||||
.get("thoughtSignature")
|
||||
.is_none());
|
||||
assert_eq!(google_multi[2]["parts"][0]["thoughtSignature"], "sig_456");
|
||||
|
||||
// Text-only response WITH signature but WITHOUT function calls should be regular text
|
||||
// (per original behavior: thinking is only when reasoning before tool calls)
|
||||
let final_response_with_sig =
|
||||
|
||||
Reference in New Issue
Block a user