From 0038bc76cdab6793e3bfcdd61cc3a08a372d28b6 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Fri, 24 Jul 2026 17:53:58 +1000 Subject: [PATCH] fix(acp): preserve read lines and reload tool output (#10662) --- crates/goose/src/acp/fs.rs | 2 +- crates/goose/src/acp/server.rs | 2 +- crates/goose/src/acp/server/load_session.rs | 1 + .../src/acp/server/tool_calls/conversion.rs | 27 ++++++++++++++----- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/crates/goose/src/acp/fs.rs b/crates/goose/src/acp/fs.rs index e63849f97..7f1801395 100644 --- a/crates/goose/src/acp/fs.rs +++ b/crates/goose/src/acp/fs.rs @@ -143,7 +143,7 @@ impl AcpTools { ctx, ToolCallUpdateFields::new() .kind(ToolKind::Read) - .locations(vec![ToolCallLocation::new(&path)]), + .locations(vec![ToolCallLocation::new(&path).line(params.line)]), ); match acp_read_text_file(&self.cx, &self.session_id, &path, params.line, params.limit).await { diff --git a/crates/goose/src/acp/server.rs b/crates/goose/src/acp/server.rs index 34eaa0794..f350db862 100644 --- a/crates/goose/src/acp/server.rs +++ b/crates/goose/src/acp/server.rs @@ -1186,7 +1186,7 @@ impl GooseAcpAgent { session_id: &SessionId, cx: &ConnectionTo, ) -> Result<(), agent_client_protocol::Error> { - let fields = tool_call_update_fields_from_response(tool_response, tool_request); + let fields = tool_call_update_fields_from_response(tool_response, tool_request, false); let update = ToolCallUpdate::new(ToolCallId::new(tool_response.id.clone()), fields) .meta(trusted_update_meta(tool_response)); diff --git a/crates/goose/src/acp/server/load_session.rs b/crates/goose/src/acp/server/load_session.rs index bc99f3ceb..c6d1fa7be 100644 --- a/crates/goose/src/acp/server/load_session.rs +++ b/crates/goose/src/acp/server/load_session.rs @@ -157,6 +157,7 @@ fn replay_conversation_to_client( let fields = tool_call_update_fields_from_response( tool_response, replay_tool_requests.get(&tool_response.id), + true, ); let update = diff --git a/crates/goose/src/acp/server/tool_calls/conversion.rs b/crates/goose/src/acp/server/tool_calls/conversion.rs index ef3e0614b..e2f80b1b4 100644 --- a/crates/goose/src/acp/server/tool_calls/conversion.rs +++ b/crates/goose/src/acp/server/tool_calls/conversion.rs @@ -266,6 +266,7 @@ fn extract_tool_raw_output(tool_result: &ToolResult) -> Option, + include_content_for_acp_aware_tools: bool, ) -> ToolCallUpdateFields { let is_failed = match &tool_response.tool_result { Ok(result) => result.is_error == Some(true), @@ -285,7 +286,7 @@ pub(crate) fn tool_call_update_fields_from_response( .tool_result .as_ref() .is_ok_and(|result| result.is_acp_aware()); - let include_content = is_failed || !is_acp_aware; + let include_content = include_content_for_acp_aware_tools || is_failed || !is_acp_aware; let include_locations = !is_acp_aware; if include_content { @@ -719,7 +720,7 @@ mod tests { let response = response_from_tool_result(Ok(result)); let request = write_request("/tmp/request.txt"); - let fields = tool_call_update_fields_from_response(&response, Some(&request)); + let fields = tool_call_update_fields_from_response(&response, Some(&request), false); assert_eq!(fields.status, Some(ToolCallStatus::Completed)); assert_eq!(fields.raw_output, Some(raw_output)); @@ -737,7 +738,7 @@ mod tests { "write failed", )]))); - let fields = tool_call_update_fields_from_response(&response, None); + let fields = tool_call_update_fields_from_response(&response, None, false); assert_eq!(fields.status, Some(ToolCallStatus::Failed)); assert_eq!(first_tool_call_text(&fields), Some("write failed")); @@ -752,7 +753,7 @@ mod tests { let response = response_from_tool_result(Ok(result.with_acp_aware_meta())); let request = write_request("/tmp/request.txt"); - let fields = tool_call_update_fields_from_response(&response, Some(&request)); + let fields = tool_call_update_fields_from_response(&response, Some(&request), false); assert_eq!(fields.status, Some(ToolCallStatus::Completed)); assert_eq!(fields.raw_output, Some(raw_output)); @@ -760,6 +761,18 @@ mod tests { assert!(fields.locations.is_none()); } + #[test] + fn includes_acp_aware_success_content_when_requested() { + let result = CallToolResult::success(vec![RmcpContent::text("write completed")]) + .with_acp_aware_meta(); + let response = response_from_tool_result(Ok(result)); + + let fields = tool_call_update_fields_from_response(&response, None, true); + + assert_eq!(fields.status, Some(ToolCallStatus::Completed)); + assert_eq!(first_tool_call_text(&fields), Some("write completed")); + } + #[test] fn prefers_explicit_location() { let response = response_with_meta(Some(serde_json::json!({ @@ -767,7 +780,7 @@ mod tests { }))); let request = write_request("/tmp/request.txt"); - let fields = tool_call_update_fields_from_response(&response, Some(&request)); + let fields = tool_call_update_fields_from_response(&response, Some(&request), false); let locations = fields.locations.as_deref().expect("expected location"); assert_eq!(locations.len(), 1); @@ -782,7 +795,7 @@ mod tests { let response = response_from_tool_result(Ok(result)); let request = write_request("/tmp/request.txt"); - let fields = tool_call_update_fields_from_response(&response, Some(&request)); + let fields = tool_call_update_fields_from_response(&response, Some(&request), false); assert_eq!(fields.status, Some(ToolCallStatus::Failed)); assert_eq!(first_tool_call_text(&fields), Some("write failed")); @@ -797,7 +810,7 @@ mod tests { None, ))); - let fields = tool_call_update_fields_from_response(&response, None); + let fields = tool_call_update_fields_from_response(&response, None, false); assert_eq!(fields.status, Some(ToolCallStatus::Failed)); assert_eq!(first_tool_call_text(&fields), Some("transport failed"));