From ef3d7b92d028fb22964fa15eff14ebe25b8e4139 Mon Sep 17 00:00:00 2001 From: yiliang114 <1204183885@qq.com> Date: Tue, 9 Dec 2025 00:15:30 +0800 Subject: [PATCH] feat(vscode-ide-companion): improve message handling and diff auto-opening - Ignore messages during checkpoint saves in WebViewProvider - Move diff auto-opening logic from useEffect to useWebViewMessages hook - Remove unused imports and variables in EditToolCall component - Enhance tool call handling for edit operations with diff content --- .../src/webview/WebViewProvider.ts | 14 +++++++ .../messages/toolcalls/Edit/EditToolCall.tsx | 39 +------------------ .../src/webview/hooks/useWebViewMessages.ts | 28 ++++++++++++- 3 files changed, 42 insertions(+), 39 deletions(-) diff --git a/packages/vscode-ide-companion/src/webview/WebViewProvider.ts b/packages/vscode-ide-companion/src/webview/WebViewProvider.ts index 8a0d205a..b61f9599 100644 --- a/packages/vscode-ide-companion/src/webview/WebViewProvider.ts +++ b/packages/vscode-ide-companion/src/webview/WebViewProvider.ts @@ -57,6 +57,20 @@ export class WebViewProvider { }); // Setup agent callbacks + this.agentManager.onMessage((message) => { + // Ignore history replay while background /chat save is running + if (this.messageHandler.getIsSavingCheckpoint()) { + console.log( + '[WebViewProvider] Ignoring message during checkpoint save', + ); + return; + } + this.sendMessageToWebView({ + type: 'message', + data: message, + }); + }); + this.agentManager.onStreamChunk((chunk: string) => { // Ignore stream chunks from background /chat save commands if (this.messageHandler.getIsSavingCheckpoint()) { diff --git a/packages/vscode-ide-companion/src/webview/components/messages/toolcalls/Edit/EditToolCall.tsx b/packages/vscode-ide-companion/src/webview/components/messages/toolcalls/Edit/EditToolCall.tsx index 4f668902..a8485316 100644 --- a/packages/vscode-ide-companion/src/webview/components/messages/toolcalls/Edit/EditToolCall.tsx +++ b/packages/vscode-ide-companion/src/webview/components/messages/toolcalls/Edit/EditToolCall.tsx @@ -6,7 +6,7 @@ * Edit tool call component - specialized for file editing operations */ -import { useEffect, useCallback, useMemo } from 'react'; +import { useMemo } from 'react'; import type { BaseToolCallProps } from '../shared/types.js'; import { groupContent, @@ -14,8 +14,6 @@ import { } from '../shared/utils.js'; import { FileLink } from '../../../layout/FileLink.js'; import type { ToolCallContainerProps } from '../shared/LayoutComponents.js'; -import { useVSCode } from '../../../../hooks/useVSCode.js'; -import { handleOpenDiff } from '../../../../utils/diffUtils.js'; export const ToolCallContainer: React.FC = ({ label, @@ -70,44 +68,9 @@ const getDiffSummary = ( */ export const EditToolCall: React.FC = ({ toolCall }) => { const { content, locations, toolCallId } = toolCall; - const vscode = useVSCode(); // Group content by type; memoize to avoid new array identities on every render const { errors, diffs } = useMemo(() => groupContent(content), [content]); - const handleOpenDiffInternal = useCallback( - ( - path: string | undefined, - oldText: string | null | undefined, - newText: string | undefined, - ) => { - handleOpenDiff(vscode, path, oldText, newText); - }, - [vscode], - ); - - // Automatically trigger openDiff when diff content is detected - // Only trigger once per tool call by checking toolCallId - useEffect(() => { - // Only auto-open if there are diffs and we have the required data - if (diffs.length > 0) { - const firstDiff = diffs[0]; - const path = firstDiff.path || (locations && locations[0]?.path) || ''; - - if ( - path && - firstDiff.oldText !== undefined && - firstDiff.newText !== undefined - ) { - // Add a small delay to ensure the component is fully rendered - const timer = setTimeout(() => { - handleOpenDiffInternal(path, firstDiff.oldText, firstDiff.newText); - }, 100); - // Proper cleanup function - return () => timer && clearTimeout(timer); - } - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [toolCallId]); // Failed case: show explicit failed message and render inline diffs if (toolCall.status === 'failed') { diff --git a/packages/vscode-ide-companion/src/webview/hooks/useWebViewMessages.ts b/packages/vscode-ide-companion/src/webview/hooks/useWebViewMessages.ts index 85ec4391..cd312361 100644 --- a/packages/vscode-ide-companion/src/webview/hooks/useWebViewMessages.ts +++ b/packages/vscode-ide-companion/src/webview/hooks/useWebViewMessages.ts @@ -386,7 +386,7 @@ export const useWebViewMessages = ({ if (permToolCall?.toolCallId) { // Infer kind more robustly for permission preview: - // - If content contains a diff entry, force 'edit' so the EditToolCall auto-opens VS Code diff + // - If content contains a diff entry, force 'edit' so the EditToolCall can handle it properly // - Else try title-based hints; fall back to provided kind or 'execute' let kind = permToolCall.kind || 'execute'; const contentArr = (permToolCall.content as unknown[]) || []; @@ -400,6 +400,32 @@ export const useWebViewMessages = ({ : false; if (hasDiff) { kind = 'edit'; + + // Auto-open diff view for edit operations with diff content + // This replaces the useEffect auto-trigger in EditToolCall component + const diffContent = contentArr.find( + (c: unknown) => + !!c && + typeof c === 'object' && + (c as { type?: string }).type === 'diff', + ) as + | { path?: string; oldText?: string; newText?: string } + | undefined; + + if ( + diffContent?.path && + diffContent?.oldText !== undefined && + diffContent?.newText !== undefined + ) { + vscode.postMessage({ + type: 'openDiff', + data: { + path: diffContent.path, + oldText: diffContent.oldText, + newText: diffContent.newText, + }, + }); + } } else if (permToolCall.title) { const title = permToolCall.title.toLowerCase(); if (title.includes('touch') || title.includes('echo')) {