From a55d278905bc68b80bb4069f2fa8df4e8d707c14 Mon Sep 17 00:00:00 2001 From: Dmitry Lyalin Date: Sat, 31 Jan 2026 11:35:59 -0500 Subject: [PATCH] Add emoji thought bubble with fallback --- .../messages/ThinkingMessage.test.tsx | 6 ++-- .../components/messages/ThinkingMessage.tsx | 35 +++++++++++++++---- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/packages/cli/src/ui/components/messages/ThinkingMessage.test.tsx b/packages/cli/src/ui/components/messages/ThinkingMessage.test.tsx index 59c62b3cb0..20caec2971 100644 --- a/packages/cli/src/ui/components/messages/ThinkingMessage.test.tsx +++ b/packages/cli/src/ui/components/messages/ThinkingMessage.test.tsx @@ -9,7 +9,7 @@ import { render } from '../../../test-utils/render.js'; import { ThinkingMessage } from './ThinkingMessage.js'; describe('ThinkingMessage', () => { - it('renders thinking header', () => { + it('renders thinking subject', () => { const { lastFrame } = render( { />, ); - expect(lastFrame()).toContain('Thinking'); + expect(lastFrame()).toContain('Planning'); }); it('renders with thought subject', () => { @@ -54,6 +54,6 @@ describe('ThinkingMessage', () => { />, ); - expect(lastFrame()).toContain('Thinking'); + expect(lastFrame()).not.toContain('Planning'); }); }); diff --git a/packages/cli/src/ui/components/messages/ThinkingMessage.tsx b/packages/cli/src/ui/components/messages/ThinkingMessage.tsx index 5dcad55058..8541f27110 100644 --- a/packages/cli/src/ui/components/messages/ThinkingMessage.tsx +++ b/packages/cli/src/ui/components/messages/ThinkingMessage.tsx @@ -6,6 +6,7 @@ import type React from 'react'; import { Box, Text } from 'ink'; +import process from 'node:process'; import type { ThoughtSummary } from '@google/gemini-cli-core'; import { MaxSizedBox, MINIMUM_MAX_HEIGHT } from '../shared/MaxSizedBox.js'; @@ -22,10 +23,13 @@ export const ThinkingMessage: React.FC = ({ }) => { const subject = thought.subject.trim(); const description = thought.description.trim(); + const headerText = subject || description; + const bodyText = subject ? description : ''; const contentMaxHeight = availableTerminalHeight !== undefined ? Math.max(availableTerminalHeight - 4, MINIMUM_MAX_HEIGHT) : undefined; + const bubbleIcon = shouldUseEmojiBubble() ? '💬' : '◆'; return ( = ({ maxWidth={terminalWidth - 2} overflowDirection="top" > - {(subject || description) && ( + {headerText && ( - {subject && ( - - ◆ {subject} - - )} - {description && {description}} + + {bubbleIcon} {headerText} + + {bodyText && {bodyText}} )} ); }; + +function shouldUseEmojiBubble(): boolean { + const locale = ( + process.env['LC_ALL'] || + process.env['LC_CTYPE'] || + process.env['LANG'] || + '' + ).toLowerCase(); + const supportsUtf8 = locale.includes('utf-8') || locale.includes('utf8'); + if (!supportsUtf8) { + return false; + } + + if (process.env['TERM'] === 'linux') { + return false; + } + + return true; +}