diff --git a/packages/cli/src/ui/components/__snapshots__/ToolConfirmationQueue-ToolConfirmationQueue-renders-a-multiline-shell-command-with-syntax-highlighting-and-redirection-warning-SVG-snapshot-.snap.svg b/packages/cli/src/ui/components/__snapshots__/ToolConfirmationQueue-ToolConfirmationQueue-renders-a-multiline-shell-command-with-syntax-highlighting-and-redirection-warning-SVG-snapshot-.snap.svg new file mode 100644 index 0000000000..32ece1f90f --- /dev/null +++ b/packages/cli/src/ui/components/__snapshots__/ToolConfirmationQueue-ToolConfirmationQueue-renders-a-multiline-shell-command-with-syntax-highlighting-and-redirection-warning-SVG-snapshot-.snap.svg @@ -0,0 +1,88 @@ + + + + + ╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ + + Action Required + + + + + ? + run_shell_command + cat << 'EOF' > foo.txtRoses are red,Violets are blue,The CLI is fast,And h + + + + + + cat + << + 'EOF' + > foo.txt + + + Roses are red, + + + Violets are blue, + + + The CLI is fast, + + + And helpful too. + + + End of the poem. + + + EOF + + + echo + "Poem successfully written to foo.txt" + + + + + Note: + Command contains redirection which can be undesirable. + + + Tip: + Toggle auto-edit (Shift+Tab) to allow redirection in the future. + + + Allow execution of: 'cat, heredoc (<<), redirection (>), echo'? + + + + + + + + + 1. + + + Allow once + + + + 2. Allow for this session + + + 3. Allow for all future sessions + + + 4. No, suggest changes (esc) + + + + ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ + + \ No newline at end of file diff --git a/packages/cli/src/ui/components/__snapshots__/ToolConfirmationQueue.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/ToolConfirmationQueue.test.tsx.snap index a39d668825..8a367e3ecb 100644 --- a/packages/cli/src/ui/components/__snapshots__/ToolConfirmationQueue.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/ToolConfirmationQueue.test.tsx.snap @@ -90,6 +90,33 @@ exports[`ToolConfirmationQueue > renders ExitPlanMode tool confirmation with Suc " `; +exports[`ToolConfirmationQueue > renders a multiline shell command with syntax highlighting and redirection warning (SVG snapshot) 1`] = ` +"╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Action Required │ +│ │ +│ ? run_shell_command cat << 'EOF' > foo.txtRoses are red,Violets are blue,The CLI is fast,And h… │ +│ │ +│ cat << 'EOF' > foo.txt │ +│ Roses are red, │ +│ Violets are blue, │ +│ The CLI is fast, │ +│ And helpful too. │ +│ End of the poem. │ +│ EOF │ +│ echo "Poem successfully written to foo.txt" │ +│ │ +│ Note: Command contains redirection which can be undesirable. │ +│ Tip: Toggle auto-edit (Shift+Tab) to allow redirection in the future. │ +│ Allow execution of: 'cat, heredoc (<<), redirection (>), echo'? │ +│ │ +│ ● 1. Allow once │ +│ 2. Allow for this session │ +│ 3. Allow for all future sessions │ +│ 4. No, suggest changes (esc) │ +│ │ +╰──────────────────────────────────────────────────────────────────────────────────────────────────╯" +`; + exports[`ToolConfirmationQueue > renders expansion hint when content is long and constrained 1`] = ` "╭──────────────────────────────────────────────────────────────────────────────╮ │ Action Required │ diff --git a/packages/cli/src/ui/components/messages/ToolConfirmationMessage.test.tsx b/packages/cli/src/ui/components/messages/ToolConfirmationMessage.test.tsx index b3b34ae0a8..fec1228c63 100644 --- a/packages/cli/src/ui/components/messages/ToolConfirmationMessage.test.tsx +++ b/packages/cli/src/ui/components/messages/ToolConfirmationMessage.test.tsx @@ -240,6 +240,37 @@ describe('ToolConfirmationMessage', () => { unmount(); }); + it('should render multiline shell scripts with correct newlines and syntax highlighting (SVG snapshot)', async () => { + const confirmationDetails: SerializableConfirmationDetails = { + type: 'exec', + title: 'Confirm Multiline Script', + command: 'echo "hello"\nfor i in 1 2 3; do\n echo $i\ndone', + rootCommand: 'echo', + rootCommands: ['echo'], + }; + + const result = renderWithProviders( + , + ); + await result.waitUntilReady(); + + const output = result.lastFrame(); + expect(output).toContain('echo "hello"'); + expect(output).toContain('for i in 1 2 3; do'); + expect(output).toContain('echo $i'); + expect(output).toContain('done'); + + await expect(result).toMatchSvgSnapshot(); + result.unmount(); + }); + describe('with folder trust', () => { const editConfirmationDetails: SerializableConfirmationDetails = { type: 'edit', diff --git a/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx b/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx index 022a68e953..b60dd4dc8b 100644 --- a/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx +++ b/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx @@ -40,6 +40,7 @@ import { import { AskUserDialog } from '../AskUserDialog.js'; import { ExitPlanModeDialog } from '../ExitPlanModeDialog.js'; import { WarningMessage } from './WarningMessage.js'; +import { colorizeCode } from '../../utils/CodeColorizer.js'; import { getDeceptiveUrlDetails, toUnicodeUrl, @@ -548,9 +549,19 @@ export const ToolConfirmationMessage: React.FC< > {commandsToDisplay.map((cmd, idx) => ( - - {sanitizeForDisplay(cmd)} - + + {colorizeCode({ + code: cmd, + language: 'bash', + maxWidth: Math.max(terminalWidth, 1), + settings, + hideLineNumbers: true, + })} + ))} @@ -634,6 +645,7 @@ export const ToolConfirmationMessage: React.FC< mcpToolDetailsText, expandDetailsHintKey, getPreferredEditor, + settings, ]); const bodyOverflowDirection: 'top' | 'bottom' = diff --git a/packages/cli/src/ui/components/messages/__snapshots__/ToolConfirmationMessage-ToolConfirmationMessage-should-render-multiline-shell-scripts-with-correct-newlines-and-syntax-highlighting-SVG-snapshot-.snap.svg b/packages/cli/src/ui/components/messages/__snapshots__/ToolConfirmationMessage-ToolConfirmationMessage-should-render-multiline-shell-scripts-with-correct-newlines-and-syntax-highlighting-SVG-snapshot-.snap.svg new file mode 100644 index 0000000000..f6500b1d1d --- /dev/null +++ b/packages/cli/src/ui/components/messages/__snapshots__/ToolConfirmationMessage-ToolConfirmationMessage-should-render-multiline-shell-scripts-with-correct-newlines-and-syntax-highlighting-SVG-snapshot-.snap.svg @@ -0,0 +1,30 @@ + + + + + echo + "hello" + for + i + in + 1 2 3; + do + echo + $i + done + Allow execution of: 'echo'? + + + + + 1. + + + Allow once + + 2. Allow for this session + 3. No, suggest changes (esc) + + \ No newline at end of file diff --git a/packages/cli/src/ui/components/messages/__snapshots__/ToolConfirmationMessage.test.tsx.snap b/packages/cli/src/ui/components/messages/__snapshots__/ToolConfirmationMessage.test.tsx.snap index 9e8dfe3a15..3f207df881 100644 --- a/packages/cli/src/ui/components/messages/__snapshots__/ToolConfirmationMessage.test.tsx.snap +++ b/packages/cli/src/ui/components/messages/__snapshots__/ToolConfirmationMessage.test.tsx.snap @@ -2,7 +2,9 @@ exports[`ToolConfirmationMessage > should display multiple commands for exec type when provided 1`] = ` "echo "hello" + ls -la + whoami Allow execution of 3 commands? @@ -35,6 +37,19 @@ Do you want to proceed? " `; +exports[`ToolConfirmationMessage > should render multiline shell scripts with correct newlines and syntax highlighting (SVG snapshot) 1`] = ` +"echo "hello" +for i in 1 2 3; do + echo $i +done +Allow execution of: 'echo'? + +● 1. Allow once + 2. Allow for this session + 3. No, suggest changes (esc) +" +`; + exports[`ToolConfirmationMessage > should strip BiDi characters from MCP tool and server names 1`] = ` "MCP Server: testserver Tool: testtool diff --git a/packages/cli/src/ui/hooks/useGeminiStream.ts b/packages/cli/src/ui/hooks/useGeminiStream.ts index 3066d1c173..630566090b 100644 --- a/packages/cli/src/ui/hooks/useGeminiStream.ts +++ b/packages/cli/src/ui/hooks/useGeminiStream.ts @@ -1799,7 +1799,6 @@ export const useGeminiStream = ( addItem, registerBackgroundShell, consumeUserHint, - config, isLowErrorVerbosity, maybeAddSuppressedToolErrorNote, maybeAddLowVerbosityFailureNote,