diff --git a/packages/cli/src/config/settingsSchema.ts b/packages/cli/src/config/settingsSchema.ts index 9bee1977ecf..9455ca11507 100644 --- a/packages/cli/src/config/settingsSchema.ts +++ b/packages/cli/src/config/settingsSchema.ts @@ -424,6 +424,15 @@ const SETTINGS_SCHEMA = { description: 'Hide the application banner', showInDialog: true, }, + showAuthOnStartup: { + type: 'boolean', + label: 'Show Auth On Startup', + category: 'UI', + requiresRestart: true, + default: true, + description: 'Show the authenticated account and plan on startup.', + showInDialog: true, + }, hideContextSummary: { type: 'boolean', label: 'Hide Context Summary', diff --git a/packages/cli/src/ui/AppContainer.tsx b/packages/cli/src/ui/AppContainer.tsx index 72f74a76f0a..aaf9ea4d436 100644 --- a/packages/cli/src/ui/AppContainer.tsx +++ b/packages/cli/src/ui/AppContainer.tsx @@ -40,6 +40,7 @@ import { getErrorMessage, getAllGeminiMdFilenames, AuthType, + UserAccountManager, clearCachedCredentialFile, type ResumedSessionData, recordExitFail, @@ -163,11 +164,50 @@ const SHELL_HEIGHT_PADDING = 10; export const AppContainer = (props: AppContainerProps) => { const { config, initializationResult, resumedSessionData } = props; + const settings = useSettings(); + + const initialHistoryItems = useMemo(() => { + const items: HistoryItem[] = []; + if (resumedSessionData) return items; + + // Check if the user has disabled showing auth on startup + if (settings.merged.ui.showAuthOnStartup === false) return items; + + // We can't use authState here because it's initialized in useAuthCommand which is called later. + // However, we can check config directly since we know startup just finished. + const authType = config.getContentGeneratorConfig()?.authType; + if ( + authType === AuthType.LOGIN_WITH_GOOGLE || + authType === AuthType.COMPUTE_ADC + ) { + try { + const userAccountManager = new UserAccountManager(); + const email = userAccountManager.getCachedGoogleAccount(); + const tier = config.getUserTier(); + + if (email) { + let message = `Authenticated as: ${email}`; + if (tier) { + message += ` (Plan: ${tier})`; + } + items.push({ + id: Date.now(), // Use timestamp as ID for initial item + type: MessageType.INFO, + text: message, + }); + } + } catch (_e) { + // Ignore errors during initial auth check + } + } + return items; + }, [config, resumedSessionData, settings.merged.ui.showAuthOnStartup]); + const historyManager = useHistory({ chatRecordingService: config.getGeminiClient()?.getChatRecordingService(), + initialItems: initialHistoryItems, }); useMemoryMonitor(historyManager); - const settings = useSettings(); const isAlternateBuffer = useAlternateBuffer(); const [corgiMode, setCorgiMode] = useState(false); const [debugMessage, setDebugMessage] = useState(''); @@ -561,10 +601,10 @@ export const AppContainer = (props: AppContainerProps) => { ) { await runExitCleanup(); writeToStdout(` ----------------------------------------------------------------- -Logging in with Google... Restarting Gemini CLI to continue. ----------------------------------------------------------------- - `); + ---------------------------------------------------------------- + Logging in with Google... Restarting Gemini CLI to continue. + ---------------------------------------------------------------- + `); process.exit(RELAUNCH_EXIT_CODE); } } diff --git a/packages/cli/src/ui/hooks/useHistoryManager.ts b/packages/cli/src/ui/hooks/useHistoryManager.ts index 3c7abaacc63..bbcf5c37942 100644 --- a/packages/cli/src/ui/hooks/useHistoryManager.ts +++ b/packages/cli/src/ui/hooks/useHistoryManager.ts @@ -36,10 +36,12 @@ export interface UseHistoryManagerReturn { */ export function useHistory({ chatRecordingService, + initialItems = [], }: { chatRecordingService?: ChatRecordingService | null; + initialItems?: HistoryItem[]; } = {}): UseHistoryManagerReturn { - const [history, setHistory] = useState([]); + const [history, setHistory] = useState(initialItems); const messageIdCounterRef = useRef(0); // Generates a unique message ID based on a timestamp and a counter. diff --git a/packages/core/src/core/loggingContentGenerator.ts b/packages/core/src/core/loggingContentGenerator.ts index cc5ab058903..0eff7d27b71 100644 --- a/packages/core/src/core/loggingContentGenerator.ts +++ b/packages/core/src/core/loggingContentGenerator.ts @@ -51,6 +51,10 @@ export class LoggingContentGenerator implements ContentGenerator { return this.wrapped; } + get userTier() { + return this.wrapped.userTier; + } + private logApiRequest( contents: Content[], model: string, diff --git a/packages/core/src/core/recordingContentGenerator.ts b/packages/core/src/core/recordingContentGenerator.ts index 27abcb418ff..217f0e0b4f8 100644 --- a/packages/core/src/core/recordingContentGenerator.ts +++ b/packages/core/src/core/recordingContentGenerator.ts @@ -15,7 +15,6 @@ import type { import { appendFileSync } from 'node:fs'; import type { ContentGenerator } from './contentGenerator.js'; import type { FakeResponse } from './fakeContentGenerator.js'; -import type { UserTierId } from '../code_assist/types.js'; import { safeJsonStringify } from '../utils/safeJsonStringify.js'; // A ContentGenerator that wraps another content generator and records all the @@ -25,13 +24,15 @@ import { safeJsonStringify } from '../utils/safeJsonStringify.js'; // // Note that only the "interesting" bits of the responses are actually kept. export class RecordingContentGenerator implements ContentGenerator { - userTier?: UserTierId; - constructor( private readonly realGenerator: ContentGenerator, private readonly filePath: string, ) {} + get userTier() { + return this.realGenerator.userTier; + } + async generateContent( request: GenerateContentParameters, userPromptId: string, diff --git a/schemas/settings.schema.json b/schemas/settings.schema.json index fe20216219f..48eac0f77af 100644 --- a/schemas/settings.schema.json +++ b/schemas/settings.schema.json @@ -222,6 +222,13 @@ "default": false, "type": "boolean" }, + "showAuthOnStartup": { + "title": "Show Auth On Startup", + "description": "Show the authenticated account and plan on startup.", + "markdownDescription": "Show the authenticated account and plan on startup.\n\n- Category: `UI`\n- Requires restart: `yes`\n- Default: `true`", + "default": true, + "type": "boolean" + }, "hideContextSummary": { "title": "Hide Context Summary", "description": "Hide the context summary (GEMINI.md, MCP servers) above the input.",