From 0851ab572d589d52815659f1b6aa8a279d974af0 Mon Sep 17 00:00:00 2001 From: yiliang114 <1204183885@qq.com> Date: Fri, 5 Dec 2025 11:41:33 +0800 Subject: [PATCH] fix(vscode-ide-companion/acp): correct optionId mapping in acpMessageHandler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplify the optionId mapping logic to directly use the provided optionId rather than transforming 'reject_once' to 'cancel'. This ensures the original optionId value is preserved in the outcome. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../src/acp/acpMessageHandler.ts | 2 +- .../toolcalls/Edit/EditToolCall.tsx | 45 ++++++++++++++----- .../toolcalls/Write/WriteToolCall.tsx | 2 +- .../toolcalls/shared/LayoutComponents.tsx | 8 ++-- 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/packages/vscode-ide-companion/src/acp/acpMessageHandler.ts b/packages/vscode-ide-companion/src/acp/acpMessageHandler.ts index e1914237..a2937a38 100644 --- a/packages/vscode-ide-companion/src/acp/acpMessageHandler.ts +++ b/packages/vscode-ide-companion/src/acp/acpMessageHandler.ts @@ -218,7 +218,7 @@ export class AcpMessageHandler { outcome: { outcome, // optionId: optionId === 'cancel' ? 'reject_once' : optionId, - optionId: optionId === 'reject_once' ? 'cancel' : optionId, + optionId, }, }; } catch (_error) { diff --git a/packages/vscode-ide-companion/src/webview/components/toolcalls/Edit/EditToolCall.tsx b/packages/vscode-ide-companion/src/webview/components/toolcalls/Edit/EditToolCall.tsx index bc2365e6..cdbb8b18 100644 --- a/packages/vscode-ide-companion/src/webview/components/toolcalls/Edit/EditToolCall.tsx +++ b/packages/vscode-ide-companion/src/webview/components/toolcalls/Edit/EditToolCall.tsx @@ -6,7 +6,7 @@ * Edit tool call component - specialized for file editing operations */ -import { useEffect, useCallback } from 'react'; +import { useEffect, useCallback, useMemo } from 'react'; import type { BaseToolCallProps } from '../shared/types.js'; import { ToolCallContainer } from '../shared/LayoutComponents.js'; import { @@ -45,9 +45,16 @@ export const EditToolCall: React.FC = ({ toolCall }) => { const { content, locations, toolCallId } = toolCall; const vscode = useVSCode(); - // Group content by type - const { errors, diffs } = groupContent(content); - + // Group content by type; memoize to avoid new array identities on every render + const { errors, diffs } = useMemo(() => groupContent(content), [content]); + // TODO: + // console.log('EditToolCall', { + // content, + // locations, + // toolCallId, + // errors, + // diffs, + // }); const handleOpenDiff = useCallback( ( path: string | undefined, @@ -67,9 +74,24 @@ export const EditToolCall: React.FC = ({ toolCall }) => { // Extract filename from path const getFileName = (path: string): string => path.split('/').pop() || path; + // Keep a module-scoped set to ensure auto-open fires once per toolCallId across re-renders + // const autoOpenedToolCallIds = + // ( + // globalThis as unknown as { + // __qwenAutoOpenedDiffIds?: Set; + // } + // ).__qwenAutoOpenedDiffIds || new Set(); + // ( + // globalThis as unknown as { __qwenAutoOpenedDiffIds: Set } + // ).__qwenAutoOpenedDiffIds = autoOpenedToolCallIds; + // Automatically trigger openDiff when diff content is detected (Claude Code style) // Only trigger once per tool call by checking toolCallId useEffect(() => { + // Guard: already auto-opened for this toolCallId in this webview session + // if (autoOpenedToolCallIds.has(toolCallId)) { + // return; + // } // Only auto-open if there are diffs and we have the required data if (diffs.length > 0) { const firstDiff = diffs[0]; @@ -80,16 +102,17 @@ export const EditToolCall: React.FC = ({ toolCall }) => { firstDiff.oldText !== undefined && firstDiff.newText !== undefined ) { - // TODO: 暂时注释自动打开功能,避免频繁触发 // Add a small delay to ensure the component is fully rendered const timer = setTimeout(() => { handleOpenDiff(path, firstDiff.oldText, firstDiff.newText); + // autoOpenedToolCallIds.add(toolCallId); }, 100); // Proper cleanup function return () => timer && clearTimeout(timer); } } - }, [diffs, handleOpenDiff, locations]); // Add missing dependencies + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [toolCallId]); // Error case: show error if (errors.length > 0) { @@ -122,14 +145,14 @@ export const EditToolCall: React.FC = ({ toolCall }) => { // const fileName = path ? getFileName(path) : ''; const summary = getDiffSummary(firstDiff.oldText, firstDiff.newText); // No hooks here; define a simple click handler scoped to this block - const openFirstDiff = () => - handleOpenDiff(path, firstDiff.oldText, firstDiff.newText); + // const openFirstDiff = () => + // handleOpenDiff(path, firstDiff.oldText, firstDiff.newText); const containerStatus = mapToolStatusToContainerStatus(toolCall.status); return (
{/* IMPORTANT: Always include min-w-0/max-w-full on inner wrappers to prevent overflow. */} @@ -149,7 +172,7 @@ export const EditToolCall: React.FC = ({ toolCall }) => { )}
-
+
{summary}
@@ -175,7 +198,7 @@ export const EditToolCall: React.FC = ({ toolCall }) => { status={containerStatus} toolCallId={toolCallId} > -
+
= ({ toolCall }) => { ) : undefined } > -
+
{lineCount} lines
diff --git a/packages/vscode-ide-companion/src/webview/components/toolcalls/shared/LayoutComponents.tsx b/packages/vscode-ide-companion/src/webview/components/toolcalls/shared/LayoutComponents.tsx index b9ee02ed..bff26ffe 100644 --- a/packages/vscode-ide-companion/src/webview/components/toolcalls/shared/LayoutComponents.tsx +++ b/packages/vscode-ide-companion/src/webview/components/toolcalls/shared/LayoutComponents.tsx @@ -50,14 +50,16 @@ export const ToolCallContainer: React.FC = ({ > {/* Timeline connector line using ::after pseudo-element */}
-
+
{label} - {labelSuffix} + + {labelSuffix} +
{children && ( -
+
{children}
)}