From 7ce1590eafc2fba66e346d9d48519afdb1dfd17e Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 28 Nov 2025 10:12:21 +0800 Subject: [PATCH] fix: add null checks and type guards to all MessageAgentTools to prevent rendering errors (#11512) * Initial plan * fix: add null checks to BashTool to prevent rendering errors Co-authored-by: DeJeune <67425183+DeJeune@users.noreply.github.com> * fix: add null checks to all MessageAgentTools to prevent rendering errors Co-authored-by: DeJeune <67425183+DeJeune@users.noreply.github.com> * fix: add Array.isArray checks to prevent map errors on non-array values Co-authored-by: DeJeune <67425183+DeJeune@users.noreply.github.com> * fix: add typeof checks for string operations to prevent type errors Co-authored-by: DeJeune <67425183+DeJeune@users.noreply.github.com> * refactor: remove redundant typeof string checks for typed outputs Co-authored-by: DeJeune <67425183+DeJeune@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: DeJeune <67425183+DeJeune@users.noreply.github.com> --- .../Tools/MessageAgentTools/BashOutputTool.tsx | 4 ++-- .../Messages/Tools/MessageAgentTools/BashTool.tsx | 8 ++++---- .../Messages/Tools/MessageAgentTools/EditTool.tsx | 8 ++++---- .../Tools/MessageAgentTools/ExitPlanModeTool.tsx | 7 ++++--- .../Messages/Tools/MessageAgentTools/GlobTool.tsx | 4 ++-- .../Messages/Tools/MessageAgentTools/GrepTool.tsx | 6 +++--- .../Tools/MessageAgentTools/MultiEditTool.tsx | 11 ++++++----- .../Tools/MessageAgentTools/NotebookEditTool.tsx | 6 +++--- .../Messages/Tools/MessageAgentTools/ReadTool.tsx | 4 ++-- .../Tools/MessageAgentTools/SearchTool.tsx | 6 +++--- .../Tools/MessageAgentTools/SkillTool.tsx | 4 ++-- .../Messages/Tools/MessageAgentTools/TaskTool.tsx | 15 ++++++++------- .../Tools/MessageAgentTools/TodoWriteTool.tsx | 9 +++++---- .../Tools/MessageAgentTools/WebFetchTool.tsx | 4 ++-- .../Tools/MessageAgentTools/WebSearchTool.tsx | 4 ++-- .../Tools/MessageAgentTools/WriteTool.tsx | 6 +++--- 16 files changed, 55 insertions(+), 51 deletions(-) diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/BashOutputTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/BashOutputTool.tsx index b47bb3f64..39d72abcf 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/BashOutputTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/BashOutputTool.tsx @@ -76,7 +76,7 @@ export function BashOutputTool({ input, output }: { - input: BashOutputToolInput + input?: BashOutputToolInput output?: BashOutputToolOutput }): NonNullable[number] { const parsedOutput = parseBashOutput(output) @@ -144,7 +144,7 @@ export function BashOutputTool({ label="Bash Output" params={
- {input.bash_id} + {input?.bash_id} {statusConfig && ( [number] { // 如果有输出,计算输出行数 const outputLines = output ? output.split('\n').length : 0 - // 处理命令字符串的截断 - const command = input.command + // 处理命令字符串的截断,添加空值检查 + const command = input?.command ?? '' const needsTruncate = command.length > MAX_TAG_LENGTH const displayCommand = needsTruncate ? `${command.slice(0, MAX_TAG_LENGTH)}...` : command @@ -31,7 +31,7 @@ export function BashTool({ } label="Bash" - params={input.description} + params={input?.description} stats={output ? `${outputLines} ${outputLines === 1 ? 'line' : 'lines'}` : undefined} />
diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/EditTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/EditTool.tsx index a49a89664..3eff8118e 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/EditTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/EditTool.tsx @@ -32,19 +32,19 @@ export function EditTool({ input, output }: { - input: EditToolInput + input?: EditToolInput output?: EditToolOutput }): NonNullable[number] { return { key: AgentToolsType.Edit, - label: } label="Edit" params={input.file_path} />, + label: } label="Edit" params={input?.file_path} />, children: ( <> {/* Diff View */} {/* Old Content */} - {renderCodeBlock(input.old_string, 'old')} + {renderCodeBlock(input?.old_string ?? '', 'old')} {/* New Content */} - {renderCodeBlock(input.new_string, 'new')} + {renderCodeBlock(input?.new_string ?? '', 'new')} {/* Output */} {output} diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/ExitPlanModeTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/ExitPlanModeTool.tsx index 0c0a4ec4a..f92116478 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/ExitPlanModeTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/ExitPlanModeTool.tsx @@ -10,18 +10,19 @@ export function ExitPlanModeTool({ input, output }: { - input: ExitPlanModeToolInput + input?: ExitPlanModeToolInput output?: ExitPlanModeToolOutput }): NonNullable[number] { + const plan = input?.plan ?? '' return { key: AgentToolsType.ExitPlanMode, label: ( } label="ExitPlanMode" - stats={`${input.plan.split('\n\n').length} plans`} + stats={`${plan.split('\n\n').length} plans`} /> ), - children: {input.plan + '\n\n' + (output ?? '')} + children: {plan + '\n\n' + (output ?? '')} } } diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/GlobTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/GlobTool.tsx index 97e816be1..b70d6da40 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/GlobTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/GlobTool.tsx @@ -8,7 +8,7 @@ export function GlobTool({ input, output }: { - input: GlobToolInputType + input?: GlobToolInputType output?: GlobToolOutputType }): NonNullable[number] { // 如果有输出,计算文件数量 @@ -20,7 +20,7 @@ export function GlobTool({ } label="Glob" - params={input.pattern} + params={input?.pattern} stats={output ? `${lineCount} ${lineCount === 1 ? 'file' : 'files'}` : undefined} /> ), diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/GrepTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/GrepTool.tsx index dbf7e0bbf..16149549d 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/GrepTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/GrepTool.tsx @@ -8,7 +8,7 @@ export function GrepTool({ input, output }: { - input: GrepToolInput + input?: GrepToolInput output?: GrepToolOutput }): NonNullable[number] { // 如果有输出,计算结果行数 @@ -22,8 +22,8 @@ export function GrepTool({ label="Grep" params={ <> - {input.pattern} - {input.output_mode && ({input.output_mode})} + {input?.pattern} + {input?.output_mode && ({input.output_mode})} } stats={output ? `${resultLines} ${resultLines === 1 ? 'line' : 'lines'}` : undefined} diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/MultiEditTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/MultiEditTool.tsx index 546fd439d..00922126e 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/MultiEditTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/MultiEditTool.tsx @@ -9,18 +9,19 @@ import { AgentToolsType } from './types' export function MultiEditTool({ input }: { - input: MultiEditToolInput + input?: MultiEditToolInput output?: MultiEditToolOutput }): NonNullable[number] { + const edits = Array.isArray(input?.edits) ? input.edits : [] return { key: AgentToolsType.MultiEdit, - label: } label="MultiEdit" params={input.file_path} />, + label: } label="MultiEdit" params={input?.file_path} />, children: (
- {input.edits.map((edit, index) => ( + {edits.map((edit, index) => (
- {renderCodeBlock(edit.old_string, 'old')} - {renderCodeBlock(edit.new_string, 'new')} + {renderCodeBlock(edit.old_string ?? '', 'old')} + {renderCodeBlock(edit.new_string ?? '', 'new')}
))}
diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/NotebookEditTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/NotebookEditTool.tsx index 8f9eb36a2..fe0638f3c 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/NotebookEditTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/NotebookEditTool.tsx @@ -11,7 +11,7 @@ export function NotebookEditTool({ input, output }: { - input: NotebookEditToolInput + input?: NotebookEditToolInput output?: NotebookEditToolOutput }): NonNullable[number] { return { @@ -20,10 +20,10 @@ export function NotebookEditTool({ <> } label="NotebookEdit" /> - {input.notebook_path}{' '} + {input?.notebook_path}{' '} ), - children: {output} + children: {output ?? ''} } } diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/ReadTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/ReadTool.tsx index 043d8a94c..30ae16227 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/ReadTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/ReadTool.tsx @@ -46,7 +46,7 @@ export function ReadTool({ input, output }: { - input: ReadToolInputType + input?: ReadToolInputType output?: ReadToolOutputType }): NonNullable[number] { const outputString = normalizeOutputString(output) @@ -58,7 +58,7 @@ export function ReadTool({ } label="Read File" - params={input.file_path.split('/').pop()} + params={input?.file_path?.split('/').pop()} stats={stats ? `${stats.lineCount} lines, ${stats.formatSize(stats.fileSize)}` : undefined} /> ), diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/SearchTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/SearchTool.tsx index 8eda9dea5..66bf28c67 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/SearchTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/SearchTool.tsx @@ -8,7 +8,7 @@ export function SearchTool({ input, output }: { - input: SearchToolInputType + input?: SearchToolInputType output?: SearchToolOutputType }): NonNullable[number] { // 如果有输出,计算结果数量 @@ -20,13 +20,13 @@ export function SearchTool({ } label="Search" - params={`"${input}"`} + params={input ? `"${input}"` : undefined} stats={output ? `${resultCount} ${resultCount === 1 ? 'result' : 'results'}` : undefined} /> ), children: (
- + {input && } {output && (
diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/SkillTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/SkillTool.tsx index 1c0651a9e..612798467 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/SkillTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/SkillTool.tsx @@ -8,12 +8,12 @@ export function SkillTool({ input, output }: { - input: SkillToolInput + input?: SkillToolInput output?: SkillToolOutput }): NonNullable[number] { return { key: 'tool', - label: } label="Skill" params={input.command} />, + label: } label="Skill" params={input?.command} />, children:
{output}
} } diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/TaskTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/TaskTool.tsx index 2c5a4a1c7..18117590c 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/TaskTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/TaskTool.tsx @@ -9,19 +9,20 @@ export function TaskTool({ input, output }: { - input: TaskToolInputType + input?: TaskToolInputType output?: TaskToolOutputType }): NonNullable[number] { return { key: 'tool', - label: } label="Task" params={input.description} />, + label: } label="Task" params={input?.description} />, children: (
- {output?.map((item) => ( -
-
{item.type === 'text' ? {item.text} : item.text}
-
- ))} + {Array.isArray(output) && + output.map((item) => ( +
+
{item.type === 'text' ? {item.text} : item.text}
+
+ ))}
) } diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/TodoWriteTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/TodoWriteTool.tsx index 2796e44fc..a81de46dc 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/TodoWriteTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/TodoWriteTool.tsx @@ -38,9 +38,10 @@ const getStatusConfig = (status: TodoItem['status']) => { export function TodoWriteTool({ input }: { - input: TodoWriteToolInputType + input?: TodoWriteToolInputType }): NonNullable[number] { - const doneCount = input.todos.filter((todo) => todo.status === 'completed').length + const todos = Array.isArray(input?.todos) ? input.todos : [] + const doneCount = todos.filter((todo) => todo.status === 'completed').length return { key: AgentToolsType.TodoWrite, @@ -49,12 +50,12 @@ export function TodoWriteTool({ icon={} label="Todo Write" params={`${doneCount} Done`} - stats={`${input.todos.length} ${input.todos.length === 1 ? 'item' : 'items'}`} + stats={`${todos.length} ${todos.length === 1 ? 'item' : 'items'}`} /> ), children: (
- {input.todos.map((todo, index) => { + {todos.map((todo, index) => { const statusConfig = getStatusConfig(todo.status) return (
diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/WebFetchTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/WebFetchTool.tsx index f54c54145..f8bd27df5 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/WebFetchTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/WebFetchTool.tsx @@ -8,12 +8,12 @@ export function WebFetchTool({ input, output }: { - input: WebFetchToolInput + input?: WebFetchToolInput output?: WebFetchToolOutput }): NonNullable[number] { return { key: 'tool', - label: } label="Web Fetch" params={input.url} />, + label: } label="Web Fetch" params={input?.url} />, children:
{output}
} } diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/WebSearchTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/WebSearchTool.tsx index 7042c63af..4f50839cc 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/WebSearchTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/WebSearchTool.tsx @@ -8,7 +8,7 @@ export function WebSearchTool({ input, output }: { - input: WebSearchToolInput + input?: WebSearchToolInput output?: WebSearchToolOutput }): NonNullable[number] { // 如果有输出,计算结果数量 @@ -20,7 +20,7 @@ export function WebSearchTool({ } label="Web Search" - params={input.query} + params={input?.query} stats={output ? `${resultCount} ${resultCount === 1 ? 'result' : 'results'}` : undefined} /> ), diff --git a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/WriteTool.tsx b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/WriteTool.tsx index d035163dc..fd0d637f5 100644 --- a/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/WriteTool.tsx +++ b/src/renderer/src/pages/home/Messages/Tools/MessageAgentTools/WriteTool.tsx @@ -7,12 +7,12 @@ import type { WriteToolInput, WriteToolOutput } from './types' export function WriteTool({ input }: { - input: WriteToolInput + input?: WriteToolInput output?: WriteToolOutput }): NonNullable[number] { return { key: 'tool', - label: } label="Write" params={input.file_path} />, - children:
{input.content}
+ label: } label="Write" params={input?.file_path} />, + children:
{input?.content}
} }