diff --git a/server/src/http/mcp/shell_tools.rs b/server/src/http/mcp/shell_tools.rs index 315a8d4d..99bafb86 100644 --- a/server/src/http/mcp/shell_tools.rs +++ b/server/src/http/mcp/shell_tools.rs @@ -399,12 +399,14 @@ pub(super) async fn tool_run_tests(args: &Value, ctx: &AppContext) -> Result Result Result { - // Done — collect results. - let result = collect_child_result(child, status); + // Done — join drain threads and collect output. + jobs.remove(&working_dir); + let stdout = stdout_handle + .take() + .and_then(|h| h.join().ok()) + .unwrap_or_default(); + let stderr = stderr_handle + .take() + .and_then(|h| h.join().ok()) + .unwrap_or_default(); + let combined = format!("{stdout}{stderr}"); + let (tests_passed, tests_failed) = parse_test_counts(&combined); + let truncated = truncate_output(&combined, MAX_OUTPUT_LINES); + let passed = status.success(); + let exit_code = status.code().unwrap_or(-1); crate::slog!( "[run_tests] Test job for {} finished (pid {}, passed={})", working_dir.display(), pid, - result.passed + passed ); - jobs.remove(&working_dir); - return format_test_result(&result); + return serde_json::to_string_pretty(&json!({ + "passed": passed, + "exit_code": exit_code, + "timed_out": false, + "tests_passed": tests_passed, + "tests_failed": tests_failed, + "output": truncated, + })) + .map_err(|e| format!("Serialization error: {e}")); } Ok(None) => { // Still running — check timeout.