diff --git a/packages/cli/src/ui/components/AnsiOutput.test.tsx b/packages/cli/src/ui/components/AnsiOutput.test.tsx index 758361be0a..6331c149a8 100644 --- a/packages/cli/src/ui/components/AnsiOutput.test.tsx +++ b/packages/cli/src/ui/components/AnsiOutput.test.tsx @@ -156,4 +156,30 @@ describe('', () => { expect(lastFrame()).toBeDefined(); unmount(); }); + + describe('robustness', () => { + it('does NOT crash when data is undefined', async () => { + const { lastFrame, unmount } = await render( + , + ); + expect(lastFrame({ allowEmpty: true }).trim()).toBe(''); + unmount(); + }); + + it('does NOT crash when data is an object but not an array', async () => { + const { lastFrame, unmount } = await render( + , + ); + expect(lastFrame({ allowEmpty: true }).trim()).toBe(''); + unmount(); + }); + }); }); diff --git a/packages/cli/src/ui/components/AnsiOutput.tsx b/packages/cli/src/ui/components/AnsiOutput.tsx index a1b30b0856..617740d4ad 100644 --- a/packages/cli/src/ui/components/AnsiOutput.tsx +++ b/packages/cli/src/ui/components/AnsiOutput.tsx @@ -35,14 +35,16 @@ export const AnsiOutputText: React.FC = ({ ? Math.min(availableHeightLimit, maxLines) : (availableHeightLimit ?? maxLines ?? DEFAULT_HEIGHT); - const lastLines = disableTruncation - ? data - : numLinesRetained === 0 - ? [] - : data.slice(-numLinesRetained); + const lastLines = Array.isArray(data) + ? disableTruncation + ? data + : numLinesRetained === 0 + ? [] + : data.slice(-numLinesRetained) + : []; return ( - {lastLines.map((line: AnsiLine, lineIndex: number) => ( + {(lastLines as AnsiLine[]).map((line: AnsiLine, lineIndex: number) => ( diff --git a/packages/cli/src/ui/components/messages/ToolResultDisplay.tsx b/packages/cli/src/ui/components/messages/ToolResultDisplay.tsx index 92791328be..4abe79345b 100644 --- a/packages/cli/src/ui/components/messages/ToolResultDisplay.tsx +++ b/packages/cli/src/ui/components/messages/ToolResultDisplay.tsx @@ -158,7 +158,7 @@ export const ToolResultDisplay: React.FC = ({ terminalWidth={childWidth} /> ); - } else { + } else if (Array.isArray(contentData)) { const shouldDisableTruncation = isAlternateBuffer || (availableTerminalHeight === undefined && maxLines === undefined); @@ -175,6 +175,15 @@ export const ToolResultDisplay: React.FC = ({ disableTruncation={shouldDisableTruncation} /> ); + } else if (typeof contentData === 'object' && contentData !== null) { + // Render as JSON for other non-null objects + content = ( + + {JSON.stringify(contentData, null, 2)} + + ); + } else { + content = null; } // Final render based on session mode