generated from nhcarrigan/template
feat: stuffy feature bundle #159
@@ -875,6 +875,32 @@ fn parse_subagent_stop_hook(line: &str) -> Option<SubagentStopData> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Extract text content from a ToolResult's `content` field.
|
||||
/// The content may be a JSON string or an array of typed content blocks.
|
||||
fn extract_tool_result_text(content: &serde_json::Value) -> Option<String> {
|
||||
match content {
|
||||
serde_json::Value::String(s) if !s.is_empty() => Some(s.clone()),
|
||||
serde_json::Value::Array(blocks) => {
|
||||
let texts: Vec<String> = blocks
|
||||
.iter()
|
||||
.filter_map(|block| {
|
||||
if block.get("type")?.as_str()? == "text" {
|
||||
block.get("text")?.as_str().map(String::from)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
if texts.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(texts.join("\n"))
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn process_json_line(
|
||||
line: &str,
|
||||
app: &AppHandle,
|
||||
@@ -1176,8 +1202,8 @@ fn process_json_line(
|
||||
}
|
||||
ContentBlock::ToolResult {
|
||||
tool_use_id,
|
||||
content,
|
||||
is_error,
|
||||
..
|
||||
} => {
|
||||
// Emit agent-end for all tool results
|
||||
// The frontend will ignore IDs that don't match known agents
|
||||
@@ -1195,7 +1221,7 @@ fn process_json_line(
|
||||
conversation_id: conversation_id.clone(),
|
||||
duration_ms: None,
|
||||
num_turns: None,
|
||||
last_assistant_message: None,
|
||||
last_assistant_message: extract_tool_result_text(content),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -1613,8 +1639,8 @@ fn process_json_line(
|
||||
for block in &message.content {
|
||||
if let ContentBlock::ToolResult {
|
||||
tool_use_id,
|
||||
content,
|
||||
is_error,
|
||||
..
|
||||
} = block
|
||||
{
|
||||
let now = SystemTime::now()
|
||||
@@ -1631,7 +1657,7 @@ fn process_json_line(
|
||||
conversation_id: conversation_id.clone(),
|
||||
duration_ms: None,
|
||||
num_turns: None,
|
||||
last_assistant_message: None,
|
||||
last_assistant_message: extract_tool_result_text(content),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -2252,4 +2278,71 @@ mod tests {
|
||||
Some("Found 3 files, all passing.".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
// extract_tool_result_text tests
|
||||
#[test]
|
||||
fn test_extract_tool_result_text_plain_string() {
|
||||
let content = serde_json::json!("Hello from agent");
|
||||
assert_eq!(
|
||||
extract_tool_result_text(&content),
|
||||
Some("Hello from agent".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_tool_result_text_empty_string() {
|
||||
let content = serde_json::json!("");
|
||||
assert_eq!(extract_tool_result_text(&content), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_tool_result_text_array_single_text_block() {
|
||||
let content = serde_json::json!([{"type": "text", "text": "Agent completed the task."}]);
|
||||
assert_eq!(
|
||||
extract_tool_result_text(&content),
|
||||
Some("Agent completed the task.".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_tool_result_text_array_multiple_text_blocks() {
|
||||
let content = serde_json::json!([
|
||||
{"type": "text", "text": "First part."},
|
||||
{"type": "text", "text": "Second part."}
|
||||
]);
|
||||
assert_eq!(
|
||||
extract_tool_result_text(&content),
|
||||
Some("First part.\nSecond part.".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_tool_result_text_array_non_text_block() {
|
||||
let content = serde_json::json!([{"type": "image", "source": {"type": "base64"}}]);
|
||||
assert_eq!(extract_tool_result_text(&content), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_tool_result_text_array_mixed_blocks() {
|
||||
let content = serde_json::json!([
|
||||
{"type": "image", "source": {}},
|
||||
{"type": "text", "text": "Found results."}
|
||||
]);
|
||||
assert_eq!(
|
||||
extract_tool_result_text(&content),
|
||||
Some("Found results.".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_tool_result_text_null() {
|
||||
let content = serde_json::Value::Null;
|
||||
assert_eq!(extract_tool_result_text(&content), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_tool_result_text_empty_array() {
|
||||
let content = serde_json::json!([]);
|
||||
assert_eq!(extract_tool_result_text(&content), None);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user