feat: 添加normalize_tool_arguments函数以解析字符串化的JSON参数,优化工具调用的参数处理
This commit is contained in:
parent
9e17cd35da
commit
fc8a0aa6ae
@ -125,6 +125,15 @@ fn parse_pending_tool_output(output: &str) -> Option<String> {
|
|||||||
output.strip_prefix(PENDING_USER_ACTION_MARKER).map(|rest| rest.trim().to_string())
|
output.strip_prefix(PENDING_USER_ACTION_MARKER).map(|rest| rest.trim().to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn normalize_tool_arguments(arguments: &serde_json::Value) -> serde_json::Value {
|
||||||
|
match arguments {
|
||||||
|
serde_json::Value::String(raw) => {
|
||||||
|
serde_json::from_str(raw).unwrap_or_else(|_| arguments.clone())
|
||||||
|
}
|
||||||
|
_ => arguments.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn is_recoverable_llm_error(error: &str) -> bool {
|
fn is_recoverable_llm_error(error: &str) -> bool {
|
||||||
let normalized = error.to_ascii_lowercase();
|
let normalized = error.to_ascii_lowercase();
|
||||||
normalized.contains("504")
|
normalized.contains("504")
|
||||||
@ -720,8 +729,10 @@ impl AgentLoop {
|
|||||||
|
|
||||||
/// Internal tool execution without event tracking.
|
/// Internal tool execution without event tracking.
|
||||||
async fn execute_tool_internal(&self, tool_call: &ToolCall) -> ToolExecutionOutcome {
|
async fn execute_tool_internal(&self, tool_call: &ToolCall) -> ToolExecutionOutcome {
|
||||||
|
let normalized_arguments = normalize_tool_arguments(&tool_call.arguments);
|
||||||
|
|
||||||
if tool_call.name == "skill_activate" {
|
if tool_call.name == "skill_activate" {
|
||||||
let skill_name = match tool_call.arguments.get("name").and_then(|v| v.as_str()) {
|
let skill_name = match normalized_arguments.get("name").and_then(|v| v.as_str()) {
|
||||||
Some(name) if !name.trim().is_empty() => name,
|
Some(name) if !name.trim().is_empty() => name,
|
||||||
_ => {
|
_ => {
|
||||||
self.record_skill_event(
|
self.record_skill_event(
|
||||||
@ -729,7 +740,7 @@ impl AgentLoop {
|
|||||||
None,
|
None,
|
||||||
serde_json::json!({
|
serde_json::json!({
|
||||||
"reason": "missing_name",
|
"reason": "missing_name",
|
||||||
"arguments": tool_call.arguments,
|
"arguments": normalized_arguments,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
return ToolExecutionOutcome::failure(
|
return ToolExecutionOutcome::failure(
|
||||||
@ -752,7 +763,7 @@ impl AgentLoop {
|
|||||||
Some(skill_name),
|
Some(skill_name),
|
||||||
serde_json::json!({
|
serde_json::json!({
|
||||||
"reason": err,
|
"reason": err,
|
||||||
"arguments": tool_call.arguments,
|
"arguments": normalized_arguments,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
ToolExecutionOutcome::failure(
|
ToolExecutionOutcome::failure(
|
||||||
@ -774,7 +785,7 @@ impl AgentLoop {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match tool.execute_with_context(&self.tool_context, tool_call.arguments.clone()).await {
|
match tool.execute_with_context(&self.tool_context, normalized_arguments).await {
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
if result.success {
|
if result.success {
|
||||||
if let Some(pending_output) = parse_pending_tool_output(&result.output) {
|
if let Some(pending_output) = parse_pending_tool_output(&result.output) {
|
||||||
@ -940,6 +951,22 @@ mod tests {
|
|||||||
assert!(parse_pending_tool_output("normal output").is_none());
|
assert!(parse_pending_tool_output("normal output").is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_normalize_tool_arguments_parses_stringified_json() {
|
||||||
|
let normalized = normalize_tool_arguments(&serde_json::Value::String(
|
||||||
|
"{\"command\":\"ls -la\"}".to_string(),
|
||||||
|
));
|
||||||
|
|
||||||
|
assert_eq!(normalized, serde_json::json!({ "command": "ls -la" }));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_normalize_tool_arguments_keeps_plain_string() {
|
||||||
|
let normalized = normalize_tool_arguments(&serde_json::Value::String("plain text".to_string()));
|
||||||
|
|
||||||
|
assert_eq!(normalized, serde_json::Value::String("plain text".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build_content_blocks_skips_non_image_media_refs() {
|
fn test_build_content_blocks_skips_non_image_media_refs() {
|
||||||
let temp_dir = tempdir().unwrap();
|
let temp_dir = tempdir().unwrap();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user