From 5350343d5bbdff4a1f6654ca1629df11b2c9d3d6 Mon Sep 17 00:00:00 2001 From: Pedro Ivo Date: Sat, 8 Aug 2026 15:17:34 -0300 Subject: [PATCH] fix(cli): restore original Verboo mascot --- src/components/LogoV2/WelcomeV2.tsx | 32 ++++++--- src/components/PromptInput/PromptInput.tsx | 5 +- src/components/StartupScreen.test.ts | 12 ++-- src/components/StartupScreen.ts | 84 +++++++++++++++++++--- 4 files changed, 106 insertions(+), 27 deletions(-) diff --git a/src/components/LogoV2/WelcomeV2.tsx b/src/components/LogoV2/WelcomeV2.tsx index 54b7064dc8..563d321d94 100644 --- a/src/components/LogoV2/WelcomeV2.tsx +++ b/src/components/LogoV2/WelcomeV2.tsx @@ -1,19 +1,35 @@ import * as React from 'react' import { Box, Text } from 'src/ink.js' +const VERBOO_LOGO = [ + ' ▄▀▀▀▀▀▀▀▄ ', + '▄▀▀▀▀▀▀▀▀▀▀▀▄', + '▀▀▀ ▀▀▀▀▀ ▀▀▀', + '▀▀▀▀▀▀▀▀▀▀▀▀▀', + '▀▀▀▀▀▄▄▄▀▀▀▀▀', + ' ▀▀▀▀▀▀▀▀▀▀▀ ', + '▄▀▀ ▀▀▀▀▀ ▀▀▄', +] + export function WelcomeV2(): React.ReactElement { const version = MACRO.DISPLAY_VERSION ?? MACRO.VERSION return ( - - - 👻 - - Verboo Code - - v{version} + + + {VERBOO_LOGO.map((line, index) => ( + + {line} + + ))} - + + + + Verboo Code + + v{version} + Build, debug, and ship from your terminal. diff --git a/src/components/PromptInput/PromptInput.tsx b/src/components/PromptInput/PromptInput.tsx index 70cf9010e7..b2fb7404cc 100644 --- a/src/components/PromptInput/PromptInput.tsx +++ b/src/components/PromptInput/PromptInput.tsx @@ -2368,9 +2368,10 @@ function getInitialPasteId(messages: Message[]): number { } return maxId + 1; } -function buildPromptBorderText(mode: PromptInputMode): BorderTextOptions { +function buildPromptBorderText(mode: PromptInputMode): BorderTextOptions | undefined { + if (mode !== 'bash') return undefined; return { - content: mode === 'bash' ? ' shell ' : ' 👻 ', + content: ' shell ', position: 'top', align: 'start', offset: 1 diff --git a/src/components/StartupScreen.test.ts b/src/components/StartupScreen.test.ts index af00c2ace3..02447d7503 100644 --- a/src/components/StartupScreen.test.ts +++ b/src/components/StartupScreen.test.ts @@ -194,20 +194,20 @@ describe('renderStartupScreen', () => { isLocal: false, } - test('uses the compact ghost identity in a wide terminal', () => { + test('uses the original mascot identity in a wide terminal', () => { const output = renderStartupScreen(provider, '0.14.5', '~/project', 120) const plainOutput = stripAnsi(output) - expect(plainOutput).toContain('👻') + expect(plainOutput).not.toContain('👻') expect(plainOutput).toContain('Verboo Code') - expect(plainOutput).not.toContain('▄▀▀▀▀▀▀▀▄') + expect(plainOutput).toContain('▄▀▀▀▀▀▀▀▄') expect(plainOutput).not.toContain('Tokens ilimitados') expect(output).toContain('\x1b[0m') expect(output).not.toContain('undefined') expect(plainOutput.split('\n').every(line => line.length <= 120)).toBe(true) }) - test('keeps the compact identity in a narrow terminal', () => { + test('keeps the original mascot in a narrow terminal when it fits', () => { const output = stripAnsi( renderStartupScreen( { @@ -220,8 +220,8 @@ describe('renderStartupScreen', () => { ), ) - expect(output).toContain('👻') - expect(output).not.toContain('▄▀▀▀▀▀▀▀▄') + expect(output).not.toContain('👻') + expect(output).toContain('▄▀▀▀▀▀▀▀▄') expect(output.split('\n').every(line => line.length <= 70)).toBe(true) }) }) diff --git a/src/components/StartupScreen.ts b/src/components/StartupScreen.ts index 867caf96c2..00f06da23f 100644 --- a/src/components/StartupScreen.ts +++ b/src/components/StartupScreen.ts @@ -22,6 +22,30 @@ const ACCENT = [173, 52, 254] as const const DIMCOL = [120, 100, 140] as const const STARTUP_DEFAULT_COLUMNS = 80 +// Original Verboo mascot. Keep this code-native so it renders consistently in +// terminals without depending on the platform's emoji artwork. +const VERBOO_LOGO = [ + ' ▄▀▀▀▀▀▀▀▄ ', + '▄▀▀▀▀▀▀▀▀▀▀▀▄', + '▀▀▀ ▀▀▀▀▀ ▀▀▀', + '▀▀▀▀▀▀▀▀▀▀▀▀▀', + '▀▀▀▀▀▄▄▄▀▀▀▀▀', + ' ▀▀▀▀▀▀▀▀▀▀▀ ', + '▄▀▀ ▀▀▀▀▀ ▀▀▄', +] + +const VERBOO_LOGO_MASK = [ + ' 011111110 ', + '0111111111110', + '1110111110111', + '1111011101111', + '1111100011111', + ' 11111111111 ', + '110 01110 011', +] + +const STARTUP_LOGO_MIN_COLUMNS = 48 + // ─── Provider detection ─────────────────────────────────────────────────────── function resolveVerbooStartupModel(modelOverride?: string): string { @@ -169,21 +193,59 @@ export function renderStartupScreen( const out: string[] = [''] const bold = `${ESC}1m` const PURPLE = rgb(...ACCENT) + const PURPLE_FILL = `${PURPLE}${ESC}48;2;${ACCENT[0]};${ACCENT[1]};${ACCENT[2]}m` const DIMP = `${DIM}${rgb(...DIMCOL)}` const STATUS_C = p.isLocal ? rgb(130, 200, 140) : PURPLE const statusLabel = p.isLocal ? 'local' : 'cloud' - const detailWidth = Math.max(1, columns - 8) const providerAndModel = p.name === 'Verboo' ? p.model : `${p.name} · ${p.model}` - const model = truncateStartupText(providerAndModel, Math.max(1, detailWidth - statusLabel.length - 4)) - const cwd = truncateStartupText(displayCwd, detailWidth) - const hint = truncateStartupText('Type a request, or use /help for commands', detailWidth) - const shownVersion = truncateStartupText(version, Math.max(1, columns - 24)) - - out.push(` 👻 ${bold}${PURPLE}Verboo Code${RESET} ${DIMP}v${shownVersion}${RESET}`) - out.push(` ${STATUS_C}●${RESET} ${DIMP}${model} · ${statusLabel}${RESET}`) - out.push(` ${DIMP}${cwd}${RESET}`) - out.push('') - out.push(` ${DIMP}${hint}${RESET}`) + + if (columns < STARTUP_LOGO_MIN_COLUMNS) { + const detailWidth = Math.max(1, columns - 4) + const shownVersion = truncateStartupText(version, Math.max(1, columns - 20)) + const model = truncateStartupText(providerAndModel, Math.max(1, detailWidth - statusLabel.length - 4)) + const cwd = truncateStartupText(displayCwd, detailWidth) + + out.push(` ${bold}${PURPLE}Verboo Code${RESET} ${DIMP}v${shownVersion}${RESET}`) + out.push(` ${STATUS_C}●${RESET} ${DIMP}${model} · ${statusLabel}${RESET}`) + out.push(` ${DIMP}${cwd}${RESET}`) + } else { + const maxLogoWidth = Math.max(...VERBOO_LOGO.map(line => line.trimEnd().length)) + const logoTextPadding = 2 + const rightTextWidth = Math.max(1, columns - 2 - maxLogoWidth - logoTextPadding) + const shownVersion = truncateStartupText(version, Math.max(1, rightTextWidth - 16)) + const model = truncateStartupText(providerAndModel, Math.max(1, rightTextWidth - statusLabel.length - 5)) + const cwd = truncateStartupText(displayCwd, rightTextWidth) + const hint = truncateStartupText('Type a request, or use /help for commands', rightTextWidth) + const rightColumn = [ + '', + `${bold}${PURPLE}Verboo Code${RESET} ${DIMP}v${shownVersion}${RESET}`, + `${STATUS_C}●${RESET} ${DIMP}${model} · ${statusLabel}${RESET}`, + `${DIMP}${cwd}${RESET}`, + '', + `${DIMP}${hint}${RESET}`, + '', + ] + + for (let i = 0; i < VERBOO_LOGO.length; i++) { + const line = (VERBOO_LOGO[i] ?? '').trimEnd() + const mask = VERBOO_LOGO_MASK[i] ?? '' + let painted = '' + + for (let j = 0; j < line.length; j++) { + const character = line[j] ?? '' + const isBlock = character === '▀' || character === '▄' + painted += isBlock && mask[j] === '1' + ? `${PURPLE_FILL}${character}${RESET}` + : isBlock + ? `${PURPLE}${character}${RESET}` + : character + } + + const gap = ' '.repeat(Math.max(0, maxLogoWidth - line.length + logoTextPadding)) + out.push(` ${painted}${gap}${rightColumn[i] ?? ''}`) + } + } + out.push('') return `${out.join('\n')}\n`