use crate::{
providers::ToolCall,
tools::{ToolCapability, ToolResult, contract::metadata_key as meta},
};
pub(super) fn failed_search_diagnostic_output(
call: &ToolCall,
result: &ToolResult,
) -> Option<String> {
if result.success
|| !result.content.trim().is_empty()
|| ToolCapability::from_dispatch_name(&call.name) != Some(ToolCapability::Grep)
{
return None;
}
[meta::STDERR, meta::STDOUT]
.into_iter()
.filter_map(|key| result.metadata.get(key).and_then(serde_json::Value::as_str))
.find(|text| !text.trim().is_empty())
.map(str::to_string)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::tools::ToolResultDisplay;
use serde_json::json;
#[test]
fn failed_search_uses_stderr_then_stdout_without_changing_raw_content() {
let diagnostic = "regex parse error:\n [unterminated character class\n";
for name in ["grep", "ffgrep"] {
let call = ToolCall {
id: "call_1".to_string(),
name: name.to_string(),
arguments: json!({"patterns": ["["], "path": "."}),
};
for metadata in [
json!({"stderr": diagnostic, "stdout": "other output"}),
json!({"stderr": " \n", "stdout": diagnostic}),
json!({"stdout": diagnostic}),
] {
let result = ToolResult {
tool_name: name.to_string(),
success: false,
content: String::new(),
metadata: metadata.clone(),
display: ToolResultDisplay::default(),
};
assert_eq!(
failed_search_diagnostic_output(&call, &result).as_deref(),
Some(diagnostic),
"{name}: {metadata}"
);
assert_eq!(result.content, "");
assert_eq!(result.metadata, metadata);
}
}
}
#[test]
fn diagnostic_fallback_does_not_replace_content_or_successful_searches() {
for (name, success, content, metadata) in [
(
"grep",
false,
"existing diagnostic",
json!({"stderr": "other"}),
),
("grep", true, "", json!({"stderr": "other"})),
("bash", false, "", json!({"stderr": "other"})),
("grep", false, "", json!({"stderr": " \n", "stdout": ""})),
("grep", false, "", json!({"stderr": 42})),
] {
let call = ToolCall {
id: "call_1".to_string(),
name: name.to_string(),
arguments: json!({}),
};
let result = ToolResult {
tool_name: name.to_string(),
success,
content: content.to_string(),
metadata,
display: ToolResultDisplay::default(),
};
assert_eq!(failed_search_diagnostic_output(&call, &result), None);
}
}
}