fix(agent): preserve native tool-call fallbacks and history fidelity
This commit is contained in:
parent
f322360248
commit
f75f73a50d
2 changed files with 112 additions and 66 deletions
|
|
@ -489,7 +489,8 @@ pub(crate) async fn run_tool_call_loop(
|
||||||
let llm_started_at = Instant::now();
|
let llm_started_at = Instant::now();
|
||||||
|
|
||||||
// Choose between native tool-call API and prompt-based tool use.
|
// Choose between native tool-call API and prompt-based tool use.
|
||||||
let (response_text, parsed_text, tool_calls, assistant_history_content) = if use_native_tools {
|
let (response_text, parsed_text, tool_calls, assistant_history_content) =
|
||||||
|
if use_native_tools {
|
||||||
match provider
|
match provider
|
||||||
.chat_with_tools(history, &tool_definitions, model, temperature)
|
.chat_with_tools(history, &tool_definitions, model, temperature)
|
||||||
.await
|
.await
|
||||||
|
|
@ -517,7 +518,10 @@ pub(crate) async fn run_tool_call_loop(
|
||||||
let assistant_history_content = if resp.tool_calls.is_empty() {
|
let assistant_history_content = if resp.tool_calls.is_empty() {
|
||||||
response_text.clone()
|
response_text.clone()
|
||||||
} else {
|
} else {
|
||||||
build_assistant_history_with_tool_calls(&response_text, &resp.tool_calls)
|
build_assistant_history_with_tool_calls(
|
||||||
|
&response_text,
|
||||||
|
&resp.tool_calls,
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
(response_text, parsed_text, calls, assistant_history_content)
|
(response_text, parsed_text, calls, assistant_history_content)
|
||||||
|
|
@ -528,13 +532,18 @@ pub(crate) async fn run_tool_call_loop(
|
||||||
model: model.to_string(),
|
model: model.to_string(),
|
||||||
duration: llm_started_at.elapsed(),
|
duration: llm_started_at.elapsed(),
|
||||||
success: false,
|
success: false,
|
||||||
error_message: Some(crate::providers::sanitize_api_error(&e.to_string())),
|
error_message: Some(crate::providers::sanitize_api_error(
|
||||||
|
&e.to_string(),
|
||||||
|
)),
|
||||||
});
|
});
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match provider.chat_with_history(history, model, temperature).await {
|
match provider
|
||||||
|
.chat_with_history(history, model, temperature)
|
||||||
|
.await
|
||||||
|
{
|
||||||
Ok(resp) => {
|
Ok(resp) => {
|
||||||
observer.record_event(&ObserverEvent::LlmResponse {
|
observer.record_event(&ObserverEvent::LlmResponse {
|
||||||
provider: provider_name.to_string(),
|
provider: provider_name.to_string(),
|
||||||
|
|
@ -554,7 +563,9 @@ pub(crate) async fn run_tool_call_loop(
|
||||||
model: model.to_string(),
|
model: model.to_string(),
|
||||||
duration: llm_started_at.elapsed(),
|
duration: llm_started_at.elapsed(),
|
||||||
success: false,
|
success: false,
|
||||||
error_message: Some(crate::providers::sanitize_api_error(&e.to_string())),
|
error_message: Some(crate::providers::sanitize_api_error(
|
||||||
|
&e.to_string(),
|
||||||
|
)),
|
||||||
});
|
});
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -712,4 +712,39 @@ mod tests {
|
||||||
assert_eq!(response.tool_calls[0].id, "call_789");
|
assert_eq!(response.tool_calls[0].id, "call_789");
|
||||||
assert_eq!(response.tool_calls[0].name, "file_read");
|
assert_eq!(response.tool_calls[0].name, "file_read");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn convert_messages_parses_assistant_tool_call_payload() {
|
||||||
|
let messages = vec![ChatMessage {
|
||||||
|
role: "assistant".into(),
|
||||||
|
content: r#"{"content":"Using tool","tool_calls":[{"id":"call_abc","name":"shell","arguments":"{\"command\":\"pwd\"}"}]}"#
|
||||||
|
.into(),
|
||||||
|
}];
|
||||||
|
|
||||||
|
let converted = OpenRouterProvider::convert_messages(&messages);
|
||||||
|
assert_eq!(converted.len(), 1);
|
||||||
|
assert_eq!(converted[0].role, "assistant");
|
||||||
|
assert_eq!(converted[0].content.as_deref(), Some("Using tool"));
|
||||||
|
|
||||||
|
let tool_calls = converted[0].tool_calls.as_ref().unwrap();
|
||||||
|
assert_eq!(tool_calls.len(), 1);
|
||||||
|
assert_eq!(tool_calls[0].id.as_deref(), Some("call_abc"));
|
||||||
|
assert_eq!(tool_calls[0].function.name, "shell");
|
||||||
|
assert_eq!(tool_calls[0].function.arguments, r#"{"command":"pwd"}"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn convert_messages_parses_tool_result_payload() {
|
||||||
|
let messages = vec![ChatMessage {
|
||||||
|
role: "tool".into(),
|
||||||
|
content: r#"{"tool_call_id":"call_xyz","content":"done"}"#.into(),
|
||||||
|
}];
|
||||||
|
|
||||||
|
let converted = OpenRouterProvider::convert_messages(&messages);
|
||||||
|
assert_eq!(converted.len(), 1);
|
||||||
|
assert_eq!(converted[0].role, "tool");
|
||||||
|
assert_eq!(converted[0].tool_call_id.as_deref(), Some("call_xyz"));
|
||||||
|
assert_eq!(converted[0].content.as_deref(), Some("done"));
|
||||||
|
assert!(converted[0].tool_calls.is_none());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue