fix bug
This commit is contained in:
parent
ef1697d8a8
commit
9939e3191f
|
|
@ -106,11 +106,15 @@ pub async fn run_agent_loop(
|
|||
|
||||
let accumulated_text = accumulated_text.lock().await.clone();
|
||||
|
||||
// Add assistant message to conversation
|
||||
// Add assistant message to conversation (including tool_use blocks)
|
||||
conversation_messages.push(AiMessage {
|
||||
role: "assistant".to_string(),
|
||||
content: accumulated_text.clone(),
|
||||
tool_call_id: None,
|
||||
tool_calls: collected_tool_calls
|
||||
.iter()
|
||||
.map(|tc| ai::ToolCallRef { id: tc.id.clone(), name: tc.name.clone(), arguments: tc.arguments.clone() })
|
||||
.collect(),
|
||||
});
|
||||
|
||||
if collected_tool_calls.is_empty() {
|
||||
|
|
@ -150,6 +154,7 @@ pub async fn run_agent_loop(
|
|||
role: "tool".to_string(),
|
||||
content: result.content.clone(),
|
||||
tool_call_id: Some(tc.id.clone()),
|
||||
tool_calls: Vec::new(),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -264,6 +269,22 @@ async fn call_openai_with_tools(
|
|||
if let Some(ref tc_id) = m.tool_call_id {
|
||||
msg["tool_call_id"] = json!(tc_id);
|
||||
}
|
||||
} else if m.role == "assistant" && !m.tool_calls.is_empty() {
|
||||
let calls: Vec<serde_json::Value> = m
|
||||
.tool_calls
|
||||
.iter()
|
||||
.map(|tc| {
|
||||
json!({
|
||||
"id": tc.id,
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": tc.name,
|
||||
"arguments": tc.arguments.to_string()
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
msg["tool_calls"] = json!(calls);
|
||||
}
|
||||
msg
|
||||
}));
|
||||
|
|
@ -336,6 +357,27 @@ async fn call_claude_with_tools(
|
|||
"content": m.content
|
||||
}]
|
||||
}));
|
||||
} else if m.role == "assistant" && !m.tool_calls.is_empty() {
|
||||
// Reconstruct assistant message with tool_use content blocks
|
||||
let mut content_blocks: Vec<serde_json::Value> = Vec::new();
|
||||
if !m.content.is_empty() {
|
||||
content_blocks.push(json!({
|
||||
"type": "text",
|
||||
"text": m.content
|
||||
}));
|
||||
}
|
||||
for tc in &m.tool_calls {
|
||||
content_blocks.push(json!({
|
||||
"type": "tool_use",
|
||||
"id": tc.id,
|
||||
"name": tc.name,
|
||||
"input": tc.arguments
|
||||
}));
|
||||
}
|
||||
messages.push(json!({
|
||||
"role": "assistant",
|
||||
"content": content_blocks
|
||||
}));
|
||||
} else {
|
||||
messages.push(json!({ "role": m.role, "content": m.content }));
|
||||
}
|
||||
|
|
@ -417,6 +459,23 @@ async fn call_gemini_with_tools(
|
|||
}
|
||||
}]
|
||||
}));
|
||||
} else if m.role == "assistant" && !m.tool_calls.is_empty() {
|
||||
let mut parts: Vec<serde_json::Value> = Vec::new();
|
||||
if !m.content.is_empty() {
|
||||
parts.push(json!({ "text": m.content }));
|
||||
}
|
||||
for tc in &m.tool_calls {
|
||||
parts.push(json!({
|
||||
"functionCall": {
|
||||
"name": tc.name,
|
||||
"args": tc.arguments
|
||||
}
|
||||
}));
|
||||
}
|
||||
contents.push(json!({
|
||||
"role": "model",
|
||||
"parts": parts
|
||||
}));
|
||||
} else {
|
||||
let role = if m.role == "assistant" { "model" } else { "user" };
|
||||
contents.push(json!({
|
||||
|
|
|
|||
|
|
@ -103,6 +103,22 @@ pub struct AiMessage {
|
|||
/// a tool result with its originating tool call in multi-turn loops.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub tool_call_id: Option<String>,
|
||||
/// Tool calls made by the assistant (role="assistant"). Used to
|
||||
/// reconstruct tool_use content blocks for providers like Anthropic
|
||||
/// that require them in the conversation history.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub tool_calls: Vec<ToolCallRef>,
|
||||
}
|
||||
|
||||
/// A lightweight reference to a tool call within an assistant message.
|
||||
/// Stores the id, name, and arguments needed to reconstruct provider-specific
|
||||
/// tool_use content blocks (e.g. Anthropic's `{"type":"tool_use", ...}`).
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ToolCallRef {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub arguments: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
|
@ -684,7 +700,12 @@ pub async fn test_connection_core(config: &AiConfig) -> Result<String, String> {
|
|||
let request = AiCompletionRequest {
|
||||
config: config.clone(),
|
||||
system_prompt: String::new(),
|
||||
messages: vec![AiMessage { role: "user".into(), content: "hi".into(), tool_call_id: None }],
|
||||
messages: vec![AiMessage {
|
||||
role: "user".into(),
|
||||
content: "hi".into(),
|
||||
tool_call_id: None,
|
||||
tool_calls: Vec::new(),
|
||||
}],
|
||||
max_tokens: Some(16),
|
||||
temperature: Some(0.0),
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue