diff --git a/src-tauri/src/acp/connection.rs b/src-tauri/src/acp/connection.rs index 1528c6a..1af295d 100644 --- a/src-tauri/src/acp/connection.rs +++ b/src-tauri/src/acp/connection.rs @@ -514,10 +514,11 @@ async fn run_connection( let conn_id = conn_id.clone(); let handle = handle.clone(); let perms = perms.clone(); + let perm_cwd = cwd_string.clone(); async move |req: RequestPermissionRequest, responder: Responder, _cx: ConnectionTo| { - handle_permission_request(&conn_id, &handle, &perms, req, responder).await; + handle_permission_request(&conn_id, &handle, &perms, &perm_cwd, req, responder).await; Ok(()) } }, @@ -861,6 +862,7 @@ async fn handle_permission_request( conn_id: &str, handle: &tauri::AppHandle, perms: &PendingPermissions, + cwd: &str, req: RequestPermissionRequest, responder: Responder, ) { @@ -882,7 +884,36 @@ async fn handle_permission_request( }) .collect(); - let tool_call_value = serde_json::to_value(&req.tool_call).unwrap_or_default(); + let mut tool_call_value = serde_json::to_value(&req.tool_call).unwrap_or_default(); + + // Resolve line numbers in rawInput for edit tool permission requests + if let Some(obj) = tool_call_value.as_object_mut() { + let raw_input_key = if obj.contains_key("rawInput") { + Some("rawInput") + } else if obj.contains_key("raw_input") { + Some("raw_input") + } else { + None + }; + if let Some(key) = raw_input_key { + if let Some(input_val) = obj.get(key).cloned() { + let input_text = match &input_val { + serde_json::Value::String(s) => Some(s.clone()), + v if !v.is_null() => Some(v.to_string()), + _ => None, + }; + if let Some(text) = input_text { + let resolved = resolve_live_tool_input(&text, Some(cwd)); + if resolved != text { + obj.insert( + key.to_string(), + serde_json::Value::String(resolved), + ); + } + } + } + } + } perms.lock().await.insert(request_id.clone(), responder); diff --git a/src/components/chat/permission-dialog.tsx b/src/components/chat/permission-dialog.tsx index 8dd3bdc..f204780 100644 --- a/src/components/chat/permission-dialog.tsx +++ b/src/components/chat/permission-dialog.tsx @@ -5,7 +5,6 @@ import { useTranslations } from "next-intl" import { ShieldAlert, Terminal, - FilePenLine, ListTodo, Compass, FileText, @@ -15,6 +14,7 @@ import { import { Button } from "@/components/ui/button" import { Badge } from "@/components/ui/badge" import { CodeBlock } from "@/components/ai-elements/code-block" +import { UnifiedDiffPreview } from "@/components/diff/unified-diff-preview" import { MessageResponse } from "@/components/ai-elements/message" import type { PendingPermission } from "@/contexts/acp-connections-context" import { parsePermissionToolCall } from "@/lib/permission-request" @@ -86,38 +86,8 @@ export function PermissionDialog({ )} - {hasFileChanges && ( -
-
- - - {t("filesSummary", { count: parsed.fileChanges.length })} - - {(parsed.additions > 0 || parsed.deletions > 0) && ( - - +{parsed.additions} / -{parsed.deletions} - - )} -
-
- {parsed.fileChanges.slice(0, 8).map((change, index) => ( -
- {change.path} -
- ))} - {parsed.fileChanges.length > 8 && ( -
- {t("moreFiles", { count: parsed.fileChanges.length - 8 })} -
- )} -
- {parsed.diffPreview && ( - - )} -
+ {hasFileChanges && parsed.diffPreview && ( + )} {hasPlan && ( diff --git a/src/lib/permission-request.ts b/src/lib/permission-request.ts index d98f055..bc302b0 100644 --- a/src/lib/permission-request.ts +++ b/src/lib/permission-request.ts @@ -145,7 +145,15 @@ function buildCompactDiffFromTexts( Math.min(oldLines.length, oldLines.length - suffix + contextLines) ) - const parts: string[] = [`--- ${path}`, `+++ ${path}`] + const oldStart = Math.max(1, prefix - before.length + 1) + const oldCount = before.length + removed.length + after.length + const newCount = before.length + added.length + after.length + + const parts: string[] = [ + `--- ${path}`, + `+++ ${path}`, + `@@ -${oldStart},${oldCount} +${oldStart},${newCount} @@`, + ] for (const line of before) parts.push(` ${line}`) for (const line of removed) parts.push(`-${line}`) for (const line of added) parts.push(`+${line}`)