diff --git a/packages/cli/src/ui/components/AskUserDialog.test.tsx b/packages/cli/src/ui/components/AskUserDialog.test.tsx index 63cf901235..52013bf175 100644 --- a/packages/cli/src/ui/components/AskUserDialog.test.tsx +++ b/packages/cli/src/ui/components/AskUserDialog.test.tsx @@ -10,6 +10,7 @@ import { renderWithProviders } from '../../test-utils/render.js'; import { waitFor } from '../../test-utils/async.js'; import { AskUserDialog } from './AskUserDialog.js'; import { QuestionType, type Question } from '@google/gemini-cli-core'; +import chalk from 'chalk'; import { UIStateContext, type UIState } from '../contexts/UIStateContext.js'; // Helper to write to stdin with proper act() wrapping @@ -941,6 +942,125 @@ describe('AskUserDialog', () => { }); }); + describe('Markdown rendering', () => { + it('auto-bolds plain single-line questions', async () => { + const questions: Question[] = [ + { + question: 'Which option do you prefer?', + header: 'Test', + options: [{ label: 'Yes', description: '' }], + multiSelect: false, + }, + ]; + + const { lastFrame } = renderWithProviders( + , + { width: 120 }, + ); + + await waitFor(() => { + const frame = lastFrame(); + // Plain text should be rendered as bold + expect(frame).toContain(chalk.bold('Which option do you prefer?')); + }); + }); + + it('does not auto-bold questions that already have markdown', async () => { + const questions: Question[] = [ + { + question: 'Is **this** working?', + header: 'Test', + options: [{ label: 'Yes', description: '' }], + multiSelect: false, + }, + ]; + + const { lastFrame } = renderWithProviders( + , + { width: 120 }, + ); + + await waitFor(() => { + const frame = lastFrame(); + // Should NOT have double-bold (the whole question bolded AND "this" bolded) + // "Is " should not be bold, only "this" should be bold + expect(frame).toContain('Is '); + expect(frame).toContain(chalk.bold('this')); + expect(frame).not.toContain('**this**'); + }); + }); + + it('renders bold markdown in question', async () => { + const questions: Question[] = [ + { + question: 'Is **this** working?', + header: 'Test', + options: [{ label: 'Yes', description: '' }], + multiSelect: false, + }, + ]; + + const { lastFrame } = renderWithProviders( + , + { width: 120 }, + ); + + await waitFor(() => { + const frame = lastFrame(); + // Check for chalk.bold('this') - asterisks should be gone, text should be bold + expect(frame).toContain(chalk.bold('this')); + expect(frame).not.toContain('**this**'); + }); + }); + + it('renders inline code markdown in question', async () => { + const questions: Question[] = [ + { + question: 'Run `npm start`?', + header: 'Test', + options: [{ label: 'Yes', description: '' }], + multiSelect: false, + }, + ]; + + const { lastFrame } = renderWithProviders( + , + { width: 120 }, + ); + + await waitFor(() => { + const frame = lastFrame(); + // Backticks should be removed + expect(frame).toContain('npm start'); + expect(frame).not.toContain('`npm start`'); + }); + }); + }); + it('uses availableTerminalHeight from UIStateContext if availableHeight prop is missing', () => { const questions: Question[] = [ { diff --git a/packages/cli/src/ui/components/AskUserDialog.tsx b/packages/cli/src/ui/components/AskUserDialog.tsx index c579ee8933..62a1f3c70b 100644 --- a/packages/cli/src/ui/components/AskUserDialog.tsx +++ b/packages/cli/src/ui/components/AskUserDialog.tsx @@ -27,10 +27,60 @@ import { useTextBuffer } from './shared/text-buffer.js'; import { getCachedStringWidth } from '../utils/textUtils.js'; import { useTabbedNavigation } from '../hooks/useTabbedNavigation.js'; import { DialogFooter } from './shared/DialogFooter.js'; +import { MarkdownDisplay } from '../utils/MarkdownDisplay.js'; +import { RenderInline } from '../utils/InlineMarkdownRenderer.js'; import { MaxSizedBox } from './shared/MaxSizedBox.js'; import { UIStateContext } from '../contexts/UIStateContext.js'; import { useAlternateBuffer } from '../hooks/useAlternateBuffer.js'; +/** Padding for dialog content to prevent text from touching edges. */ +const DIALOG_PADDING = 4; + +/** + * Checks if text is a single line without markdown identifiers. + */ +function isPlainSingleLine(text: string): boolean { + // Must be a single line (no newlines) + if (text.includes('\n') || text.includes('\r')) { + return false; + } + + // Check for common markdown identifiers + const markdownPatterns = [ + /^#{1,6}\s/, // Headers + /^[`~]{3,}/, // Code fences + /^[-*+]\s/, // Unordered lists + /^\d+\.\s/, // Ordered lists + /^[-*_]{3,}$/, // Horizontal rules + /\|/, // Tables + /\*\*|__/, // Bold + /(? = ({ maxWidth={availableWidth} overflowDirection="bottom" > - - {question.question} - + @@ -734,7 +786,7 @@ const ChoiceQuestionView: React.FC = ({ : undefined; const questionHeight = listHeight && !isAlternateBuffer - ? Math.min(15, Math.max(1, listHeight - 4)) + ? Math.min(15, Math.max(1, listHeight - DIALOG_PADDING)) : undefined; const maxItemsToShow = listHeight && questionHeight @@ -750,15 +802,18 @@ const ChoiceQuestionView: React.FC = ({ maxWidth={availableWidth} overflowDirection="bottom" > - - {question.question} + + {question.multiSelect && ( - {' '} (Select all that apply) )} - + @@ -833,7 +888,10 @@ const ChoiceQuestionView: React.FC = ({ {optionItem.description && ( {' '} - {optionItem.description} + )} diff --git a/packages/cli/src/ui/components/__snapshots__/ExitPlanModeDialog.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/ExitPlanModeDialog.test.tsx.snap index 2e4317d990..252066d445 100644 --- a/packages/cli/src/ui/components/__snapshots__/ExitPlanModeDialog.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/ExitPlanModeDialog.test.tsx.snap @@ -1,21 +1,21 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`ExitPlanModeDialog > useAlternateBuffer: false > bubbles up Ctrl+C when feedback is empty while editing 1`] = ` -"## Overview +"Overview Add user authentication to the CLI application. -## Implementation Steps +Implementation Steps -1. Create \`src/auth/AuthService.ts\` with login/logout methods -2. Add session storage in \`src/storage/SessionStore.ts\` -3. Update \`src/commands/index.ts\` to check auth status -4. Add tests in \`src/auth/__tests__/\` + 1. Create src/auth/AuthService.ts with login/logout methods + 2. Add session storage in src/storage/SessionStore.ts + 3. Update src/commands/index.ts to check auth status + 4. Add tests in src/auth/__tests__/ -## Files to Modify +Files to Modify -- \`src/index.ts\` - Add auth middleware -- \`src/config.ts\` - Add auth configuration options + - src/index.ts - Add auth middleware + - src/config.ts - Add auth configuration options 1. Yes, automatically accept edits Approves plan and allows tools to run automatically @@ -27,21 +27,21 @@ Enter to submit · Esc to cancel" `; exports[`ExitPlanModeDialog > useAlternateBuffer: false > calls onFeedback when feedback is typed and submitted 1`] = ` -"## Overview +"Overview Add user authentication to the CLI application. -## Implementation Steps +Implementation Steps -1. Create \`src/auth/AuthService.ts\` with login/logout methods -2. Add session storage in \`src/storage/SessionStore.ts\` -3. Update \`src/commands/index.ts\` to check auth status -4. Add tests in \`src/auth/__tests__/\` + 1. Create src/auth/AuthService.ts with login/logout methods + 2. Add session storage in src/storage/SessionStore.ts + 3. Update src/commands/index.ts to check auth status + 4. Add tests in src/auth/__tests__/ -## Files to Modify +Files to Modify -- \`src/index.ts\` - Add auth middleware -- \`src/config.ts\` - Add auth configuration options + - src/index.ts - Add auth middleware + - src/config.ts - Add auth configuration options 1. Yes, automatically accept edits Approves plan and allows tools to run automatically @@ -55,20 +55,20 @@ Enter to submit · Esc to cancel" exports[`ExitPlanModeDialog > useAlternateBuffer: false > displays error state when file read fails 1`] = `" Error reading plan: File not found"`; exports[`ExitPlanModeDialog > useAlternateBuffer: false > handles long plan content appropriately 1`] = ` -"## Overview +"Overview Implement a comprehensive authentication system with multiple providers. -## Implementation Steps +Implementation Steps -1. Create \`src/auth/AuthService.ts\` with login/logout methods -2. Add session storage in \`src/storage/SessionStore.ts\` -3. Update \`src/commands/index.ts\` to check auth status -4. Add OAuth2 provider support in \`src/auth/providers/OAuth2Provider.ts\` -5. Add SAML provider support in \`src/auth/providers/SAMLProvider.ts\` -6. Add LDAP provider support in \`src/auth/providers/LDAPProvider.ts\` -7. Create token refresh mechanism in \`src/auth/TokenManager.ts\` -8. Add multi-factor authentication in \`src/auth/MFAService.ts\` + 1. Create src/auth/AuthService.ts with login/logout methods + 2. Add session storage in src/storage/SessionStore.ts + 3. Update src/commands/index.ts to check auth status + 4. Add OAuth2 provider support in src/auth/providers/OAuth2Provider.ts + 5. Add SAML provider support in src/auth/providers/SAMLProvider.ts + 6. Add LDAP provider support in src/auth/providers/LDAPProvider.ts + 7. Create token refresh mechanism in src/auth/TokenManager.ts + 8. Add multi-factor authentication in src/auth/MFAService.ts ... last 22 lines hidden ... ● 1. Yes, automatically accept edits @@ -81,21 +81,21 @@ Enter to select · ↑/↓ to navigate · Esc to cancel" `; exports[`ExitPlanModeDialog > useAlternateBuffer: false > renders correctly with plan content 1`] = ` -"## Overview +"Overview Add user authentication to the CLI application. -## Implementation Steps +Implementation Steps -1. Create \`src/auth/AuthService.ts\` with login/logout methods -2. Add session storage in \`src/storage/SessionStore.ts\` -3. Update \`src/commands/index.ts\` to check auth status -4. Add tests in \`src/auth/__tests__/\` + 1. Create src/auth/AuthService.ts with login/logout methods + 2. Add session storage in src/storage/SessionStore.ts + 3. Update src/commands/index.ts to check auth status + 4. Add tests in src/auth/__tests__/ -## Files to Modify +Files to Modify -- \`src/index.ts\` - Add auth middleware -- \`src/config.ts\` - Add auth configuration options + - src/index.ts - Add auth middleware + - src/config.ts - Add auth configuration options ● 1. Yes, automatically accept edits Approves plan and allows tools to run automatically @@ -107,21 +107,21 @@ Enter to select · ↑/↓ to navigate · Esc to cancel" `; exports[`ExitPlanModeDialog > useAlternateBuffer: true > bubbles up Ctrl+C when feedback is empty while editing 1`] = ` -"## Overview +"Overview Add user authentication to the CLI application. -## Implementation Steps +Implementation Steps -1. Create \`src/auth/AuthService.ts\` with login/logout methods -2. Add session storage in \`src/storage/SessionStore.ts\` -3. Update \`src/commands/index.ts\` to check auth status -4. Add tests in \`src/auth/__tests__/\` + 1. Create src/auth/AuthService.ts with login/logout methods + 2. Add session storage in src/storage/SessionStore.ts + 3. Update src/commands/index.ts to check auth status + 4. Add tests in src/auth/__tests__/ -## Files to Modify +Files to Modify -- \`src/index.ts\` - Add auth middleware -- \`src/config.ts\` - Add auth configuration options + - src/index.ts - Add auth middleware + - src/config.ts - Add auth configuration options 1. Yes, automatically accept edits Approves plan and allows tools to run automatically @@ -133,21 +133,21 @@ Enter to submit · Esc to cancel" `; exports[`ExitPlanModeDialog > useAlternateBuffer: true > calls onFeedback when feedback is typed and submitted 1`] = ` -"## Overview +"Overview Add user authentication to the CLI application. -## Implementation Steps +Implementation Steps -1. Create \`src/auth/AuthService.ts\` with login/logout methods -2. Add session storage in \`src/storage/SessionStore.ts\` -3. Update \`src/commands/index.ts\` to check auth status -4. Add tests in \`src/auth/__tests__/\` + 1. Create src/auth/AuthService.ts with login/logout methods + 2. Add session storage in src/storage/SessionStore.ts + 3. Update src/commands/index.ts to check auth status + 4. Add tests in src/auth/__tests__/ -## Files to Modify +Files to Modify -- \`src/index.ts\` - Add auth middleware -- \`src/config.ts\` - Add auth configuration options + - src/index.ts - Add auth middleware + - src/config.ts - Add auth configuration options 1. Yes, automatically accept edits Approves plan and allows tools to run automatically @@ -161,42 +161,42 @@ Enter to submit · Esc to cancel" exports[`ExitPlanModeDialog > useAlternateBuffer: true > displays error state when file read fails 1`] = `" Error reading plan: File not found"`; exports[`ExitPlanModeDialog > useAlternateBuffer: true > handles long plan content appropriately 1`] = ` -"## Overview +"Overview Implement a comprehensive authentication system with multiple providers. -## Implementation Steps +Implementation Steps -1. Create \`src/auth/AuthService.ts\` with login/logout methods -2. Add session storage in \`src/storage/SessionStore.ts\` -3. Update \`src/commands/index.ts\` to check auth status -4. Add OAuth2 provider support in \`src/auth/providers/OAuth2Provider.ts\` -5. Add SAML provider support in \`src/auth/providers/SAMLProvider.ts\` -6. Add LDAP provider support in \`src/auth/providers/LDAPProvider.ts\` -7. Create token refresh mechanism in \`src/auth/TokenManager.ts\` -8. Add multi-factor authentication in \`src/auth/MFAService.ts\` -9. Implement session timeout handling in \`src/auth/SessionManager.ts\` -10. Add audit logging for auth events in \`src/auth/AuditLogger.ts\` -11. Create user profile management in \`src/auth/UserProfile.ts\` -12. Add role-based access control in \`src/auth/RBACService.ts\` -13. Implement password policy enforcement in \`src/auth/PasswordPolicy.ts\` -14. Add brute force protection in \`src/auth/BruteForceGuard.ts\` -15. Create secure cookie handling in \`src/auth/CookieManager.ts\` + 1. Create src/auth/AuthService.ts with login/logout methods + 2. Add session storage in src/storage/SessionStore.ts + 3. Update src/commands/index.ts to check auth status + 4. Add OAuth2 provider support in src/auth/providers/OAuth2Provider.ts + 5. Add SAML provider support in src/auth/providers/SAMLProvider.ts + 6. Add LDAP provider support in src/auth/providers/LDAPProvider.ts + 7. Create token refresh mechanism in src/auth/TokenManager.ts + 8. Add multi-factor authentication in src/auth/MFAService.ts + 9. Implement session timeout handling in src/auth/SessionManager.ts + 10. Add audit logging for auth events in src/auth/AuditLogger.ts + 11. Create user profile management in src/auth/UserProfile.ts + 12. Add role-based access control in src/auth/RBACService.ts + 13. Implement password policy enforcement in src/auth/PasswordPolicy.ts + 14. Add brute force protection in src/auth/BruteForceGuard.ts + 15. Create secure cookie handling in src/auth/CookieManager.ts -## Files to Modify +Files to Modify -- \`src/index.ts\` - Add auth middleware -- \`src/config.ts\` - Add auth configuration options -- \`src/routes/api.ts\` - Add auth endpoints -- \`src/middleware/cors.ts\` - Update CORS for auth headers -- \`src/utils/crypto.ts\` - Add encryption utilities + - src/index.ts - Add auth middleware + - src/config.ts - Add auth configuration options + - src/routes/api.ts - Add auth endpoints + - src/middleware/cors.ts - Update CORS for auth headers + - src/utils/crypto.ts - Add encryption utilities -## Testing Strategy +Testing Strategy -- Unit tests for each auth provider -- Integration tests for full auth flows -- Security penetration testing -- Load testing for session management + - Unit tests for each auth provider + - Integration tests for full auth flows + - Security penetration testing + - Load testing for session management ● 1. Yes, automatically accept edits Approves plan and allows tools to run automatically @@ -208,21 +208,21 @@ Enter to select · ↑/↓ to navigate · Esc to cancel" `; exports[`ExitPlanModeDialog > useAlternateBuffer: true > renders correctly with plan content 1`] = ` -"## Overview +"Overview Add user authentication to the CLI application. -## Implementation Steps +Implementation Steps -1. Create \`src/auth/AuthService.ts\` with login/logout methods -2. Add session storage in \`src/storage/SessionStore.ts\` -3. Update \`src/commands/index.ts\` to check auth status -4. Add tests in \`src/auth/__tests__/\` + 1. Create src/auth/AuthService.ts with login/logout methods + 2. Add session storage in src/storage/SessionStore.ts + 3. Update src/commands/index.ts to check auth status + 4. Add tests in src/auth/__tests__/ -## Files to Modify +Files to Modify -- \`src/index.ts\` - Add auth middleware -- \`src/config.ts\` - Add auth configuration options + - src/index.ts - Add auth middleware + - src/config.ts - Add auth configuration options ● 1. Yes, automatically accept edits Approves plan and allows tools to run automatically