From 795e7fa2c5b1b87d0ad1aaf23a9d14507f8ecdfa Mon Sep 17 00:00:00 2001 From: yiliang114 <1204183885@qq.com> Date: Mon, 24 Nov 2025 20:33:27 +0800 Subject: [PATCH] fix(vscode-ide-companion): improve type safety in webview components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复 webview 组件的类型安全问题: - App.tsx: 规范化工具调用状态为联合类型 - InProgressToolCall.tsx: 安全处理非字符串类型的 title 属性 - InputForm.tsx: 修正 RefObject 泛型类型声明 - ReadToolCall.tsx: 添加空 children 避免 ToolCallContainer 警告 --- packages/vscode-ide-companion/src/webview/App.tsx | 14 ++++++++++++-- .../src/webview/components/InProgressToolCall.tsx | 10 ++++++++-- .../src/webview/components/InputForm.tsx | 4 +++- .../webview/components/toolcalls/ReadToolCall.tsx | 4 +++- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/packages/vscode-ide-companion/src/webview/App.tsx b/packages/vscode-ide-companion/src/webview/App.tsx index 287fc962..5e5c55d3 100644 --- a/packages/vscode-ide-companion/src/webview/App.tsx +++ b/packages/vscode-ide-companion/src/webview/App.tsx @@ -24,7 +24,7 @@ import { import { useCompletionTrigger } from './hooks/useCompletionTrigger.js'; import { SaveSessionDialog } from './components/SaveSessionDialog.js'; import { InfoBanner } from './components/InfoBanner.js'; -import { ChatHeader } from './components/ui/ChatHeader.js'; +import { ChatHeader } from './components/layouts/ChatHeader.js'; import { UserMessage, AssistantMessage, @@ -830,12 +830,22 @@ export const App: React.FC = () => { } } + // Normalize status to our union type + const normalizedStatus = ( + permToolCall.status === 'pending' || + permToolCall.status === 'in_progress' || + permToolCall.status === 'completed' || + permToolCall.status === 'failed' + ? permToolCall.status + : 'pending' + ) as ToolCallUpdate['status']; + handleToolCallUpdate({ type: 'tool_call', toolCallId: permToolCall.toolCallId, kind, title: permToolCall.title, - status: permToolCall.status || 'pending', + status: normalizedStatus, content: permToolCall.content as Array<{ type: 'content' | 'diff'; content?: { diff --git a/packages/vscode-ide-companion/src/webview/components/InProgressToolCall.tsx b/packages/vscode-ide-companion/src/webview/components/InProgressToolCall.tsx index e8e48d9f..bb475a97 100644 --- a/packages/vscode-ide-companion/src/webview/components/InProgressToolCall.tsx +++ b/packages/vscode-ide-companion/src/webview/components/InProgressToolCall.tsx @@ -68,6 +68,12 @@ export const InProgressToolCall: React.FC = ({ // Get status text const statusText = getStatusText(status || 'in_progress'); + // Safely prepare a display value for title. Titles may sometimes arrive as + // non-string objects; ensure we render a string in that case. + const titleText = typeof title === 'string' ? title : undefined; + const titleDisplay: React.ReactNode = + typeof title === 'string' ? title : title ? JSON.stringify(title) : null; + return (
@@ -79,8 +85,8 @@ export const InProgressToolCall: React.FC = ({
- {title && title !== kindLabel && ( -
{title}
+ {titleDisplay && (titleText ? titleText !== kindLabel : true) && ( +
{titleDisplay}
)} {locations && locations.length > 0 && ( diff --git a/packages/vscode-ide-companion/src/webview/components/InputForm.tsx b/packages/vscode-ide-companion/src/webview/components/InputForm.tsx index 13ec8d85..1cc4c4f8 100644 --- a/packages/vscode-ide-companion/src/webview/components/InputForm.tsx +++ b/packages/vscode-ide-companion/src/webview/components/InputForm.tsx @@ -10,7 +10,9 @@ type EditMode = 'ask' | 'auto' | 'plan'; interface InputFormProps { inputText: string; - inputFieldRef: React.RefObject; + // Note: RefObject carries nullability in its `current` property, so the + // generic should be `HTMLDivElement` (not `HTMLDivElement | null`). + inputFieldRef: React.RefObject; isStreaming: boolean; isComposing: boolean; editMode: EditMode; diff --git a/packages/vscode-ide-companion/src/webview/components/toolcalls/ReadToolCall.tsx b/packages/vscode-ide-companion/src/webview/components/toolcalls/ReadToolCall.tsx index b6fa7c4a..f38ad266 100644 --- a/packages/vscode-ide-companion/src/webview/components/toolcalls/ReadToolCall.tsx +++ b/packages/vscode-ide-companion/src/webview/components/toolcalls/ReadToolCall.tsx @@ -48,7 +48,9 @@ export const ReadToolCall: React.FC = ({ toolCall }) => { label={`Read ${fileName}`} status="success" toolCallId={toolCallId} - /> + > + {null} + ); }