Add visual cues for nightly version (#3701)
Co-authored-by: Jacob Richman <jacob314@gmail.com>
This commit is contained in:
parent
4197f30278
commit
448838dea8
|
@ -26,6 +26,7 @@ import { getUserStartupWarnings } from './utils/userStartupWarnings.js';
|
|||
import { runNonInteractive } from './nonInteractiveCli.js';
|
||||
import { loadExtensions, Extension } from './config/extension.js';
|
||||
import { cleanupCheckpoints } from './utils/cleanup.js';
|
||||
import { getCliVersion } from './utils/version.js';
|
||||
import {
|
||||
ApprovalMode,
|
||||
Config,
|
||||
|
@ -183,6 +184,7 @@ export async function main() {
|
|||
|
||||
// Render UI, passing necessary config values. Check that there is no command line question.
|
||||
if (process.stdin.isTTY && input?.length === 0) {
|
||||
const version = await getCliVersion();
|
||||
setWindowTitle(basename(workspaceRoot), settings);
|
||||
render(
|
||||
<React.StrictMode>
|
||||
|
@ -190,6 +192,7 @@ export async function main() {
|
|||
config={config}
|
||||
settings={settings}
|
||||
startupWarnings={startupWarnings}
|
||||
version={version}
|
||||
/>
|
||||
</React.StrictMode>,
|
||||
{ exitOnCtrlC: false },
|
||||
|
|
|
@ -186,6 +186,7 @@ vi.mock('./components/Tips.js', () => ({
|
|||
describe('App UI', () => {
|
||||
let mockConfig: MockServerConfig;
|
||||
let mockSettings: LoadedSettings;
|
||||
let mockVersion: string;
|
||||
let currentUnmount: (() => void) | undefined;
|
||||
|
||||
const createMockSettings = (
|
||||
|
@ -229,6 +230,7 @@ describe('App UI', () => {
|
|||
cwd: '/tmp',
|
||||
model: 'model',
|
||||
}) as unknown as MockServerConfig;
|
||||
mockVersion = '0.0.0-test';
|
||||
|
||||
// Ensure the getShowMemoryUsage mock function is specifically set up if not covered by constructor mock
|
||||
if (!mockConfig.getShowMemoryUsage) {
|
||||
|
@ -258,6 +260,7 @@ describe('App UI', () => {
|
|||
<App
|
||||
config={mockConfig as unknown as ServerConfig}
|
||||
settings={mockSettings}
|
||||
version={mockVersion}
|
||||
/>,
|
||||
);
|
||||
currentUnmount = unmount;
|
||||
|
@ -274,6 +277,7 @@ describe('App UI', () => {
|
|||
<App
|
||||
config={mockConfig as unknown as ServerConfig}
|
||||
settings={mockSettings}
|
||||
version={mockVersion}
|
||||
/>,
|
||||
);
|
||||
currentUnmount = unmount;
|
||||
|
@ -293,6 +297,7 @@ describe('App UI', () => {
|
|||
<App
|
||||
config={mockConfig as unknown as ServerConfig}
|
||||
settings={mockSettings}
|
||||
version={mockVersion}
|
||||
/>,
|
||||
);
|
||||
currentUnmount = unmount;
|
||||
|
@ -315,6 +320,7 @@ describe('App UI', () => {
|
|||
<App
|
||||
config={mockConfig as unknown as ServerConfig}
|
||||
settings={mockSettings}
|
||||
version={mockVersion}
|
||||
/>,
|
||||
);
|
||||
currentUnmount = unmount;
|
||||
|
@ -334,6 +340,7 @@ describe('App UI', () => {
|
|||
<App
|
||||
config={mockConfig as unknown as ServerConfig}
|
||||
settings={mockSettings}
|
||||
version={mockVersion}
|
||||
/>,
|
||||
);
|
||||
currentUnmount = unmount;
|
||||
|
@ -353,6 +360,7 @@ describe('App UI', () => {
|
|||
<App
|
||||
config={mockConfig as unknown as ServerConfig}
|
||||
settings={mockSettings}
|
||||
version={mockVersion}
|
||||
/>,
|
||||
);
|
||||
currentUnmount = unmount;
|
||||
|
@ -372,6 +380,7 @@ describe('App UI', () => {
|
|||
<App
|
||||
config={mockConfig as unknown as ServerConfig}
|
||||
settings={mockSettings}
|
||||
version={mockVersion}
|
||||
/>,
|
||||
);
|
||||
currentUnmount = unmount;
|
||||
|
@ -392,6 +401,7 @@ describe('App UI', () => {
|
|||
<App
|
||||
config={mockConfig as unknown as ServerConfig}
|
||||
settings={mockSettings}
|
||||
version={mockVersion}
|
||||
/>,
|
||||
);
|
||||
currentUnmount = unmount;
|
||||
|
@ -404,6 +414,7 @@ describe('App UI', () => {
|
|||
<App
|
||||
config={mockConfig as unknown as ServerConfig}
|
||||
settings={mockSettings}
|
||||
version={mockVersion}
|
||||
/>,
|
||||
);
|
||||
currentUnmount = unmount;
|
||||
|
@ -422,6 +433,7 @@ describe('App UI', () => {
|
|||
<App
|
||||
config={mockConfig as unknown as ServerConfig}
|
||||
settings={mockSettings}
|
||||
version={mockVersion}
|
||||
/>,
|
||||
);
|
||||
currentUnmount = unmount;
|
||||
|
@ -440,6 +452,7 @@ describe('App UI', () => {
|
|||
<App
|
||||
config={mockConfig as unknown as ServerConfig}
|
||||
settings={mockSettings}
|
||||
version={mockVersion}
|
||||
/>,
|
||||
);
|
||||
currentUnmount = unmount;
|
||||
|
@ -469,6 +482,7 @@ describe('App UI', () => {
|
|||
<App
|
||||
config={mockConfig as unknown as ServerConfig}
|
||||
settings={mockSettings}
|
||||
version={mockVersion}
|
||||
/>,
|
||||
);
|
||||
currentUnmount = unmount;
|
||||
|
@ -483,6 +497,7 @@ describe('App UI', () => {
|
|||
<App
|
||||
config={mockConfig as unknown as ServerConfig}
|
||||
settings={mockSettings}
|
||||
version={mockVersion}
|
||||
/>,
|
||||
);
|
||||
currentUnmount = unmount;
|
||||
|
|
|
@ -84,6 +84,7 @@ interface AppProps {
|
|||
config: Config;
|
||||
settings: LoadedSettings;
|
||||
startupWarnings?: string[];
|
||||
version: string;
|
||||
}
|
||||
|
||||
export const AppWrapper = (props: AppProps) => (
|
||||
|
@ -92,10 +93,11 @@ export const AppWrapper = (props: AppProps) => (
|
|||
</SessionStatsProvider>
|
||||
);
|
||||
|
||||
const App = ({ config, settings, startupWarnings = [] }: AppProps) => {
|
||||
const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
useBracketedPaste();
|
||||
const [updateMessage, setUpdateMessage] = useState<string | null>(null);
|
||||
const { stdout } = useStdout();
|
||||
const nightly = version.includes('nightly');
|
||||
|
||||
useEffect(() => {
|
||||
checkForUpdates().then(setUpdateMessage);
|
||||
|
@ -673,7 +675,11 @@ const App = ({ config, settings, startupWarnings = [] }: AppProps) => {
|
|||
key={staticKey}
|
||||
items={[
|
||||
<Box flexDirection="column" key="header">
|
||||
<Header terminalWidth={terminalWidth} />
|
||||
<Header
|
||||
terminalWidth={terminalWidth}
|
||||
version={version}
|
||||
nightly={nightly}
|
||||
/>
|
||||
{!settings.merged.hideTips && <Tips config={config} />}
|
||||
</Box>,
|
||||
...history.map((h) => (
|
||||
|
@ -931,6 +937,7 @@ const App = ({ config, settings, startupWarnings = [] }: AppProps) => {
|
|||
config.getDebugMode() || config.getShowMemoryUsage()
|
||||
}
|
||||
promptTokenCount={sessionStats.lastPromptTokenCount}
|
||||
nightly={nightly}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
|
@ -10,6 +10,7 @@ import { Colors } from '../colors.js';
|
|||
import { shortenPath, tildeifyPath, tokenLimit } from '@google/gemini-cli-core';
|
||||
import { ConsoleSummaryDisplay } from './ConsoleSummaryDisplay.js';
|
||||
import process from 'node:process';
|
||||
import Gradient from 'ink-gradient';
|
||||
import { MemoryUsageDisplay } from './MemoryUsageDisplay.js';
|
||||
|
||||
interface FooterProps {
|
||||
|
@ -23,6 +24,7 @@ interface FooterProps {
|
|||
showErrorDetails: boolean;
|
||||
showMemoryUsage?: boolean;
|
||||
promptTokenCount: number;
|
||||
nightly: boolean;
|
||||
}
|
||||
|
||||
export const Footer: React.FC<FooterProps> = ({
|
||||
|
@ -36,6 +38,7 @@ export const Footer: React.FC<FooterProps> = ({
|
|||
showErrorDetails,
|
||||
showMemoryUsage,
|
||||
promptTokenCount,
|
||||
nightly,
|
||||
}) => {
|
||||
const limit = tokenLimit(model);
|
||||
const percentage = promptTokenCount / limit;
|
||||
|
@ -43,10 +46,19 @@ export const Footer: React.FC<FooterProps> = ({
|
|||
return (
|
||||
<Box marginTop={1} justifyContent="space-between" width="100%">
|
||||
<Box>
|
||||
<Text color={Colors.LightBlue}>
|
||||
{shortenPath(tildeifyPath(targetDir), 70)}
|
||||
{branchName && <Text color={Colors.Gray}> ({branchName}*)</Text>}
|
||||
</Text>
|
||||
{nightly ? (
|
||||
<Gradient colors={Colors.GradientColors}>
|
||||
<Text>
|
||||
{shortenPath(tildeifyPath(targetDir), 70)}
|
||||
{branchName && <Text> ({branchName}*)</Text>}
|
||||
</Text>
|
||||
</Gradient>
|
||||
) : (
|
||||
<Text color={Colors.LightBlue}>
|
||||
{shortenPath(tildeifyPath(targetDir), 70)}
|
||||
{branchName && <Text color={Colors.Gray}> ({branchName}*)</Text>}
|
||||
</Text>
|
||||
)}
|
||||
{debugMode && (
|
||||
<Text color={Colors.AccentRed}>
|
||||
{' ' + (debugMessage || '--debug')}
|
||||
|
|
|
@ -14,11 +14,15 @@ import { getAsciiArtWidth } from '../utils/textUtils.js';
|
|||
interface HeaderProps {
|
||||
customAsciiArt?: string; // For user-defined ASCII art
|
||||
terminalWidth: number; // For responsive logo
|
||||
version: string;
|
||||
nightly: boolean;
|
||||
}
|
||||
|
||||
export const Header: React.FC<HeaderProps> = ({
|
||||
customAsciiArt,
|
||||
terminalWidth,
|
||||
version,
|
||||
nightly,
|
||||
}) => {
|
||||
let displayTitle;
|
||||
const widthOfLongLogo = getAsciiArtWidth(longAsciiLogo);
|
||||
|
@ -38,6 +42,7 @@ export const Header: React.FC<HeaderProps> = ({
|
|||
alignItems="flex-start"
|
||||
width={artWidth}
|
||||
flexShrink={0}
|
||||
flexDirection="column"
|
||||
>
|
||||
{Colors.GradientColors ? (
|
||||
<Gradient colors={Colors.GradientColors}>
|
||||
|
@ -46,6 +51,13 @@ export const Header: React.FC<HeaderProps> = ({
|
|||
) : (
|
||||
<Text>{displayTitle}</Text>
|
||||
)}
|
||||
{nightly && (
|
||||
<Box width="100%" flexDirection="row" justifyContent="flex-end">
|
||||
<Gradient colors={Colors.GradientColors}>
|
||||
<Text>v{version}</Text>
|
||||
</Gradient>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue