From b1a439e38f5deacaf72742eba299d40dd7a15a7c Mon Sep 17 00:00:00 2001 From: yiliang114 <1204183885@qq.com> Date: Fri, 5 Dec 2025 12:42:58 +0800 Subject: [PATCH] feat(vscode-ide-companion/read): implement diff auto-open functionality Add diff viewing capabilities to Read tool calls with automatic opening of VS Code diff tabs when diff content is detected. Includes: - Import necessary React hooks and VS Code context - Memoize content grouping for performance - Auto-open diff in VS Code with useEffect - Handle diff messages with useCallback - Display compact UI when diff content is present --- .../toolcalls/Read/ReadToolCall.tsx | 69 ++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/packages/vscode-ide-companion/src/webview/components/toolcalls/Read/ReadToolCall.tsx b/packages/vscode-ide-companion/src/webview/components/toolcalls/Read/ReadToolCall.tsx index b848f380..27bcc409 100644 --- a/packages/vscode-ide-companion/src/webview/components/toolcalls/Read/ReadToolCall.tsx +++ b/packages/vscode-ide-companion/src/webview/components/toolcalls/Read/ReadToolCall.tsx @@ -7,6 +7,7 @@ */ import type React from 'react'; +import { useCallback, useEffect, useMemo } from 'react'; import type { BaseToolCallProps } from '../shared/types.js'; import { ToolCallContainer } from '../shared/LayoutComponents.js'; import { @@ -14,6 +15,7 @@ import { mapToolStatusToContainerStatus, } from '../shared/utils.js'; import { FileLink } from '../../ui/FileLink.js'; +import { useVSCode } from '../../../hooks/useVSCode.js'; /** * Specialized component for Read tool calls @@ -22,9 +24,48 @@ import { FileLink } from '../../ui/FileLink.js'; */ export const ReadToolCall: React.FC = ({ toolCall }) => { const { content, locations, toolCallId } = toolCall; + const vscode = useVSCode(); - // Group content by type - const { errors } = groupContent(content); + // Group content by type; memoize to avoid new array identities on every render + const { errors, diffs } = useMemo(() => groupContent(content), [content]); + + // Post a message to the extension host to open a VS Code diff tab + const handleOpenDiff = useCallback( + ( + path: string | undefined, + oldText: string | null | undefined, + newText: string | undefined, + ) => { + if (path) { + vscode.postMessage({ + type: 'openDiff', + data: { path, oldText: oldText || '', newText: newText || '' }, + }); + } + }, + [vscode], + ); + + // Auto-open diff (Claude-style) when a read call returns diff content. + // Only trigger once per toolCallId so we don't spam as in-progress updates stream in. + useEffect(() => { + if (diffs.length > 0) { + const firstDiff = diffs[0]; + const path = firstDiff.path || (locations && locations[0]?.path) || ''; + + if ( + path && + firstDiff.oldText !== undefined && + firstDiff.newText !== undefined + ) { + const timer = setTimeout(() => { + handleOpenDiff(path, firstDiff.oldText, firstDiff.newText); + }, 100); + return () => timer && clearTimeout(timer); + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [toolCallId]); // Compute container status based on toolCall.status (pending/in_progress -> loading) const containerStatus: @@ -58,6 +99,30 @@ export const ReadToolCall: React.FC = ({ toolCall }) => { ); } + // Success case with diff: keep UI compact; VS Code diff is auto-opened above + if (diffs.length > 0) { + const path = diffs[0]?.path || locations?.[0]?.path || ''; + return ( + + ) : undefined + } + > + {null} + + ); + } + // Success case: show which file was read with filename in label if (locations && locations.length > 0) { const path = locations[0].path;