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;
|
continue;
|
||||||
}
|
}
|
||||||
middleware::ToolCallDecision::ReplaceInput(new_input) => {
|
middleware::ToolCallDecision::ReplaceInput(new_input) => {
|
||||||
// Execute with replaced input
|
// Execute with replaced input (with timeout)
|
||||||
let tool_result = match self.execute_tool(&name, new_input, &tool_context).await {
|
let tool_result = match tokio::time::timeout(
|
||||||
Ok(result) => result,
|
std::time::Duration::from_secs(30),
|
||||||
Err(e) => serde_json::json!({ "error": e.to_string() }),
|
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));
|
messages.push(Message::tool_result(id, zclaw_types::ToolId::new(&name), tool_result, false));
|
||||||
continue;
|
continue;
|
||||||
@@ -471,9 +478,16 @@ impl AgentLoop {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let tool_result = match self.execute_tool(&name, input, &tool_context).await {
|
let tool_result = match tokio::time::timeout(
|
||||||
Ok(result) => result,
|
std::time::Duration::from_secs(30),
|
||||||
Err(e) => serde_json::json!({ "error": e.to_string() }),
|
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
|
// Check if this is a clarification response — terminate loop immediately
|
||||||
|
|||||||
Reference in New Issue
Block a user