fix: prevent null output and string render crashes in MessagesBoundary

UserToolSuccessMessage now requires parsedOutput.success before trusting
data, and guards toolResult against non-object values before calling
renderToolResultMessage. String renderedMessage is wrapped in <Text> so
multi-line tool reports (e.g. GoalTool usage report) don't crash Ink.

Defense in depth added to VaultHttpFetchTool/UI (matches the existing
pattern in LocalMemoryRecallTool and GoalTool) and to the
mapToolResultToToolResultBlockParam of both vault/memory tools.

Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
This commit is contained in:
claude-code-best
2026-06-26 05:47:52 +08:00
parent 0753dafccc
commit 8246ffa392
6 changed files with 24 additions and 6 deletions

View File

@@ -137,7 +137,10 @@ export const GoalTool = buildTool({
return `Updating goal: ${input.status}${input.reason ? `${input.reason}` : ''}`
},
renderToolResultMessage(output: Output) {
if (output.error) return `Goal error: ${output.error}`
if (!output) {
return null
}
if (output?.error) return `Goal error: ${output.error}`
if (output.report) return output.report
if (output.goal) {
return `Goal "${output.goal.objective}" — ${output.goal.status}`

View File

@@ -547,7 +547,7 @@ export const LocalMemoryRecallTool = buildTool({
type: 'tool_result',
tool_use_id: toolUseID,
content: jsonStringify(output),
is_error: output.error !== undefined,
is_error: output?.error !== undefined,
}
},
} satisfies ToolDef<InputSchema, Output>)

View File

@@ -33,6 +33,9 @@ export function renderToolResultMessage(
_progressMessagesForMessage: ProgressMessage<ToolProgressData>[],
{ verbose }: { verbose: boolean },
): React.ReactNode {
// Defense in depth: framework validates via outputSchema, but resumed
// transcripts can still produce null here via deserialization edge cases.
if (!output) return null;
if (output.error) {
return (
<MessageResponse height={1}>

View File

@@ -409,7 +409,7 @@ export const VaultHttpFetchTool = buildTool({
type: 'tool_result',
tool_use_id: toolUseID,
content: jsonStringify(output),
is_error: output.error !== undefined,
is_error: output?.error !== undefined,
}
},
} satisfies ToolDef<InputSchema, Output>)