feat(acp): include path in ls tool results

Amolith created

Added Path to LSResponseMetadata and updated the ACP sink to include it
via WithUpdateLocations in tool call updates, enabling clients to show
which directory is being listed.

Assisted-by: Claude Sonnet 4 via Crush

Change summary

internal/acp/sink.go       | 19 ++++++++++++++++---
internal/agent/tools/ls.go |  6 ++++--
2 files changed, 20 insertions(+), 5 deletions(-)

Detailed changes

internal/acp/sink.go 🔗

@@ -341,6 +341,8 @@ func (s *Sink) translateToolResult(tr message.ToolResult) *acp.SessionUpdate {
 
 	// For edit tools with metadata, emit diff content.
 	content := []acp.ToolCallContent{acp.ToolContent(acp.TextBlock(tr.Content))}
+	var locations []acp.ToolCallLocation
+
 	if !tr.IsError && tr.Metadata != "" {
 		switch tr.Name {
 		case "edit", "multiedit", "write":
@@ -350,13 +352,24 @@ func (s *Sink) translateToolResult(tr message.ToolResult) *acp.SessionUpdate {
 					acp.ToolDiffContent(meta.FilePath, meta.NewContent, meta.OldContent),
 				}
 			}
+		case "ls":
+			var meta struct {
+				Path string `json:"path"`
+			}
+			if err := json.Unmarshal([]byte(tr.Metadata), &meta); err == nil && meta.Path != "" {
+				locations = []acp.ToolCallLocation{{Path: meta.Path}}
+			}
 		}
 	}
 
-	update := acp.UpdateToolCall(
-		acp.ToolCallId(tr.ToolCallID),
+	opts := []acp.ToolCallUpdateOpt{
 		acp.WithUpdateStatus(status),
 		acp.WithUpdateContent(content),
-	)
+	}
+	if len(locations) > 0 {
+		opts = append(opts, acp.WithUpdateLocations(locations))
+	}
+
+	update := acp.UpdateToolCall(acp.ToolCallId(tr.ToolCallID), opts...)
 	return &update
 }

internal/agent/tools/ls.go 🔗

@@ -36,8 +36,9 @@ type TreeNode struct {
 }
 
 type LSResponseMetadata struct {
-	NumberOfFiles int  `json:"number_of_files"`
-	Truncated     bool `json:"truncated"`
+	Path          string `json:"path"`
+	NumberOfFiles int    `json:"number_of_files"`
+	Truncated     bool   `json:"truncated"`
 }
 
 const (
@@ -126,6 +127,7 @@ func ListDirectoryTree(searchPath string, params LSParams, lsConfig config.ToolL
 	}
 
 	metadata := LSResponseMetadata{
+		Path:          searchPath,
 		NumberOfFiles: len(files),
 		Truncated:     truncated,
 	}