fix(runtime): add 30s timeout to tool execution in AgentLoop
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Tool execution (ShellExec, WebFetch, etc.) had no timeout, causing the entire streaming response to hang indefinitely when a tool fails or stalls. Now wraps execute_tool calls in tokio::time::timeout(30s) with a graceful error message on timeout.
This commit is contained in:
@@ -429,10 +429,17 @@ impl AgentLoop {
|
||||
continue;
|
||||
}
|
||||
middleware::ToolCallDecision::ReplaceInput(new_input) => {
|
||||
// Execute with replaced input
|
||||
let tool_result = match self.execute_tool(&name, new_input, &tool_context).await {
|
||||
Ok(result) => result,
|
||||
Err(e) => serde_json::json!({ "error": e.to_string() }),
|
||||
// Execute with replaced input (with timeout)
|
||||
let tool_result = match tokio::time::timeout(
|
||||
std::time::Duration::from_secs(30),
|
||||
self.execute_tool(&name, new_input, &tool_context),
|
||||
).await {
|
||||
Ok(Ok(result)) => result,
|
||||
Ok(Err(e)) => serde_json::json!({ "error": e.to_string() }),
|
||||
Err(_) => {
|
||||
tracing::warn!("[AgentLoop] Tool '{}' (replaced input) timed out after 30s", name);
|
||||
serde_json::json!({ "error": format!("工具 '{}' 执行超时(30秒),请重试", name) })
|
||||
}
|
||||
};
|
||||
messages.push(Message::tool_result(id, zclaw_types::ToolId::new(&name), tool_result, false));
|
||||
continue;
|
||||
@@ -471,9 +478,16 @@ impl AgentLoop {
|
||||
}
|
||||
}
|
||||
|
||||
let tool_result = match self.execute_tool(&name, input, &tool_context).await {
|
||||
Ok(result) => result,
|
||||
Err(e) => serde_json::json!({ "error": e.to_string() }),
|
||||
let tool_result = match tokio::time::timeout(
|
||||
std::time::Duration::from_secs(30),
|
||||
self.execute_tool(&name, input, &tool_context),
|
||||
).await {
|
||||
Ok(Ok(result)) => result,
|
||||
Ok(Err(e)) => serde_json::json!({ "error": e.to_string() }),
|
||||
Err(_) => {
|
||||
tracing::warn!("[AgentLoop] Tool '{}' timed out after 30s", name);
|
||||
serde_json::json!({ "error": format!("工具 '{}' 执行超时(30秒),请重试", name) })
|
||||
}
|
||||
};
|
||||
|
||||
// Check if this is a clarification response — terminate loop immediately
|
||||
|
||||
Reference in New Issue
Block a user