Remove previewFeatures and default to Gemini 3 (#18414)

This commit is contained in:
Sehoon Shon
2026-02-06 13:02:57 -05:00
committed by GitHub
parent 1495294cc0
commit 61d92c4a21
57 changed files with 91 additions and 797 deletions

View File

@@ -246,7 +246,7 @@ export const AppContainer = (props: AppContainerProps) => {
[defaultBannerText, warningBannerText],
);
const { bannerText } = useBanner(bannerData, config);
const { bannerText } = useBanner(bannerData);
const extensionManager = config.getExtensionLoader() as ExtensionManager;
// We are in the interactive CLI, update how we request consent and settings.
@@ -1772,7 +1772,8 @@ Logging in with Google... Restarting Gemini CLI to continue.
const fetchBannerTexts = async () => {
const [defaultBanner, warningBanner] = await Promise.all([
config.getBannerTextNoCapacityIssues(),
// TODO: temporarily disabling the banner, it will be re-added.
'',
config.getBannerTextCapacityIssues(),
]);
@@ -1780,15 +1781,6 @@ Logging in with Google... Restarting Gemini CLI to continue.
setDefaultBannerText(defaultBanner);
setWarningBannerText(warningBanner);
setBannerVisible(true);
const authType = config.getContentGeneratorConfig()?.authType;
if (
authType === AuthType.USE_GEMINI ||
authType === AuthType.USE_VERTEX_AI
) {
setDefaultBannerText(
'Gemini 3 Flash and Pro are now available. \nEnable "Preview features" in /settings. \nLearn more at https://goo.gle/enable-preview-features',
);
}
}
};
// eslint-disable-next-line @typescript-eslint/no-floating-promises

View File

@@ -89,53 +89,6 @@ describe('<AppHeader />', () => {
unmount();
});
it('should render the banner when previewFeatures is disabled', () => {
const mockConfig = makeFakeConfig({ previewFeatures: false });
const uiState = {
history: [],
bannerData: {
defaultText: 'This is the default banner',
warningText: '',
},
bannerVisible: true,
};
const { lastFrame, unmount } = renderWithProviders(
<AppHeader version="1.0.0" />,
{
config: mockConfig,
uiState,
},
);
expect(lastFrame()).toContain('This is the default banner');
expect(lastFrame()).toMatchSnapshot();
unmount();
});
it('should not render the banner when previewFeatures is enabled', () => {
const mockConfig = makeFakeConfig({ previewFeatures: true });
const uiState = {
history: [],
bannerData: {
defaultText: 'This is the default banner',
warningText: '',
},
};
const { lastFrame, unmount } = renderWithProviders(
<AppHeader version="1.0.0" />,
{
config: mockConfig,
uiState,
},
);
expect(lastFrame()).not.toContain('This is the default banner');
expect(lastFrame()).toMatchSnapshot();
unmount();
});
it('should not render the default banner if shown count is 5 or more', () => {
const mockConfig = makeFakeConfig();
const uiState = {

View File

@@ -24,7 +24,7 @@ export const AppHeader = ({ version }: AppHeaderProps) => {
const config = useConfig();
const { nightly, terminalWidth, bannerData, bannerVisible } = useUIState();
const { bannerText } = useBanner(bannerData, config);
const { bannerText } = useBanner(bannerData);
const { showTips } = useTips();
return (

View File

@@ -147,7 +147,7 @@ export const Footer: React.FC = () => {
<Box alignItems="center" justifyContent="flex-end">
<Box alignItems="center">
<Text color={theme.text.accent}>
{getDisplayString(model, config.getPreviewFeatures())}
{getDisplayString(model)}
<Text color={theme.text.secondary}> /model</Text>
{!hideContextPercentage && (
<>

View File

@@ -14,8 +14,6 @@ import {
DEFAULT_GEMINI_MODEL_AUTO,
DEFAULT_GEMINI_FLASH_MODEL,
DEFAULT_GEMINI_FLASH_LITE_MODEL,
PREVIEW_GEMINI_MODEL,
PREVIEW_GEMINI_MODEL_AUTO,
} from '@google/gemini-cli-core';
import type { Config, ModelSlashCommandEvent } from '@google/gemini-cli-core';
@@ -42,28 +40,24 @@ vi.mock('@google/gemini-cli-core', async () => {
describe('<ModelDialog />', () => {
const mockSetModel = vi.fn();
const mockGetModel = vi.fn();
const mockGetPreviewFeatures = vi.fn();
const mockOnClose = vi.fn();
const mockGetHasAccessToPreviewModel = vi.fn();
interface MockConfig extends Partial<Config> {
setModel: (model: string, isTemporary?: boolean) => void;
getModel: () => string;
getPreviewFeatures: () => boolean;
getHasAccessToPreviewModel: () => boolean;
}
const mockConfig: MockConfig = {
setModel: mockSetModel,
getModel: mockGetModel,
getPreviewFeatures: mockGetPreviewFeatures,
getHasAccessToPreviewModel: mockGetHasAccessToPreviewModel,
};
beforeEach(() => {
vi.resetAllMocks();
mockGetModel.mockReturnValue(DEFAULT_GEMINI_MODEL_AUTO);
mockGetPreviewFeatures.mockReturnValue(false);
mockGetHasAccessToPreviewModel.mockReturnValue(false);
// Default implementation for getDisplayString
@@ -94,13 +88,6 @@ describe('<ModelDialog />', () => {
expect(lastFrame()).toContain('Manual');
});
it('renders "main" view with preview options when preview features are enabled', () => {
mockGetPreviewFeatures.mockReturnValue(true);
mockGetHasAccessToPreviewModel.mockReturnValue(true); // Must have access
const { lastFrame } = renderComponent();
expect(lastFrame()).toContain('Auto (Preview)');
});
it('switches to "manual" view when "Manual" is selected', async () => {
const { lastFrame, stdin } = renderComponent();
@@ -119,26 +106,6 @@ describe('<ModelDialog />', () => {
expect(lastFrame()).toContain(DEFAULT_GEMINI_FLASH_LITE_MODEL);
});
it('renders "manual" view with preview options when preview features are enabled', async () => {
mockGetPreviewFeatures.mockReturnValue(true);
mockGetHasAccessToPreviewModel.mockReturnValue(true); // Must have access
mockGetModel.mockReturnValue(PREVIEW_GEMINI_MODEL_AUTO);
const { lastFrame, stdin } = renderComponent();
// Select "Manual" (index 2 because Preview Auto is first, then Auto (Gemini 2.5))
// Press down enough times to ensure we reach the bottom (Manual)
stdin.write('\u001B[B'); // Arrow Down
await waitForUpdate();
stdin.write('\u001B[B'); // Arrow Down
await waitForUpdate();
// Press enter to select Manual
stdin.write('\r');
await waitForUpdate();
expect(lastFrame()).toContain(PREVIEW_GEMINI_MODEL);
});
it('sets model and closes when a model is selected in "main" view', async () => {
const { stdin } = renderComponent();
@@ -220,50 +187,4 @@ describe('<ModelDialog />', () => {
// Should be back to main view (Manual option visible)
expect(lastFrame()).toContain('Manual');
});
describe('Preview Logic', () => {
it('should NOT show preview options if user has no access', () => {
mockGetHasAccessToPreviewModel.mockReturnValue(false);
mockGetPreviewFeatures.mockReturnValue(true); // Even if enabled
const { lastFrame } = renderComponent();
expect(lastFrame()).not.toContain('Auto (Preview)');
});
it('should NOT show preview options if user has access but preview features are disabled', () => {
mockGetHasAccessToPreviewModel.mockReturnValue(true);
mockGetPreviewFeatures.mockReturnValue(false);
const { lastFrame } = renderComponent();
expect(lastFrame()).not.toContain('Auto (Preview)');
});
it('should show preview options if user has access AND preview features are enabled', () => {
mockGetHasAccessToPreviewModel.mockReturnValue(true);
mockGetPreviewFeatures.mockReturnValue(true);
const { lastFrame } = renderComponent();
expect(lastFrame()).toContain('Auto (Preview)');
});
it('should show "Gemini 3 is now available" header if user has access but preview features disabled', () => {
mockGetHasAccessToPreviewModel.mockReturnValue(true);
mockGetPreviewFeatures.mockReturnValue(false);
const { lastFrame } = renderComponent();
expect(lastFrame()).toContain('Gemini 3 is now available.');
expect(lastFrame()).toContain('Enable "Preview features" in /settings');
});
it('should show "Gemini 3 is coming soon" header if user has no access', () => {
mockGetHasAccessToPreviewModel.mockReturnValue(false);
mockGetPreviewFeatures.mockReturnValue(false);
const { lastFrame } = renderComponent();
expect(lastFrame()).toContain('Gemini 3 is coming soon.');
});
it('should NOT show header/subheader if preview options are shown', () => {
mockGetHasAccessToPreviewModel.mockReturnValue(true);
mockGetPreviewFeatures.mockReturnValue(true);
const { lastFrame } = renderComponent();
expect(lastFrame()).not.toContain('Gemini 3 is now available.');
expect(lastFrame()).not.toContain('Gemini 3 is coming soon.');
});
});
});

View File

@@ -23,7 +23,6 @@ import { useKeypress } from '../hooks/useKeypress.js';
import { theme } from '../semantic-colors.js';
import { DescriptiveRadioButtonSelect } from './shared/DescriptiveRadioButtonSelect.js';
import { ConfigContext } from '../contexts/ConfigContext.js';
import { ThemedGradient } from './ThemedGradient.js';
interface ModelDialogProps {
onClose: () => void;
@@ -37,8 +36,7 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element {
// Determine the Preferred Model (read once when the dialog opens).
const preferredModel = config?.getModel() || DEFAULT_GEMINI_MODEL_AUTO;
const shouldShowPreviewModels =
config?.getPreviewFeatures() && config.getHasAccessToPreviewModel();
const shouldShowPreviewModels = config?.getHasAccessToPreviewModel();
const manualModelSelected = useMemo(() => {
const manualModels = [
@@ -173,24 +171,6 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element {
[config, onClose, persistMode],
);
let header;
let subheader;
// Do not show any header or subheader since it's already showing preview model
// options
if (shouldShowPreviewModels) {
header = undefined;
subheader = undefined;
// When a user has the access but has not enabled the preview features.
} else if (config?.getHasAccessToPreviewModel()) {
header = 'Gemini 3 is now available.';
subheader =
'Enable "Preview features" in /settings.\nLearn more at https://goo.gle/enable-preview-features';
} else {
header = 'Gemini 3 is coming soon.';
subheader = undefined;
}
return (
<Box
borderStyle="round"
@@ -201,16 +181,6 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element {
>
<Text bold>Select Model</Text>
<Box flexDirection="column">
{header && (
<Box marginTop={1}>
<ThemedGradient>
<Text>{header}</Text>
</ThemedGradient>
</Box>
)}
{subheader && <Text>{subheader}</Text>}
</Box>
<Box marginTop={1}>
<DescriptiveRadioButtonSelect
items={options}

View File

@@ -368,20 +368,12 @@ describe('SettingsDialog', () => {
const { stdin, unmount, lastFrame } = renderDialog(settings, onSelect);
// Wait for initial render and verify we're on Preview Features (first setting)
await waitFor(() => {
expect(lastFrame()).toContain('Preview Features (e.g., models)');
});
// Navigate to Vim Mode setting and verify we're there
act(() => {
stdin.write(TerminalKeys.DOWN_ARROW as string);
});
// Wait for initial render and verify we're on Vim Mode (first setting)
await waitFor(() => {
expect(lastFrame()).toContain('Vim Mode');
});
// Toggle the setting
// Toggle the setting (Vim Mode is the first setting now)
act(() => {
stdin.write(TerminalKeys.ENTER as string);
});

View File

@@ -355,10 +355,6 @@ export function SettingsDialog({
next.delete(key);
return next;
});
if (key === 'general.previewFeatures') {
config?.setPreviewFeatures(newValue as boolean);
}
} else {
// For restart-required settings, track as modified
setModifiedSettings((prev) => {
@@ -387,14 +383,7 @@ export function SettingsDialog({
});
}
},
[
pendingSettings,
settings,
selectedScope,
vimEnabled,
toggleVimEnabled,
config,
],
[pendingSettings, settings, selectedScope, vimEnabled, toggleVimEnabled],
);
// Edit commit handler
@@ -522,12 +511,6 @@ export function SettingsDialog({
});
}
}
if (key === 'general.previewFeatures') {
const booleanDefaultValue =
typeof defaultValue === 'boolean' ? defaultValue : false;
config?.setPreviewFeatures(booleanDefaultValue);
}
}
// Remove from modified sets

View File

@@ -18,24 +18,6 @@ Tips for getting started:
4. /help for more information."
`;
exports[`<AppHeader /> > should not render the banner when previewFeatures is enabled 1`] = `
"
███ █████████
░░░███ ███░░░░░███
░░░███ ███ ░░░
░░░███░███
███░ ░███ █████
███░ ░░███ ░░███
███░ ░░█████████
░░░ ░░░░░░░░░
Tips for getting started:
1. Ask questions, edit files, or run commands.
2. Be specific for the best results.
3. Create GEMINI.md files to customize your interactions with Gemini.
4. /help for more information."
`;
exports[`<AppHeader /> > should not render the default banner if shown count is 5 or more 1`] = `
"
███ █████████
@@ -54,27 +36,6 @@ Tips for getting started:
4. /help for more information."
`;
exports[`<AppHeader /> > should render the banner when previewFeatures is disabled 1`] = `
"
███ █████████
░░░███ ███░░░░░███
░░░███ ███ ░░░
░░░███░███
███░ ░███ █████
███░ ░░███ ░░███
███░ ░░█████████
░░░ ░░░░░░░░░
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ This is the default banner │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Tips for getting started:
1. Ask questions, edit files, or run commands.
2. Be specific for the best results.
3. Create GEMINI.md files to customize your interactions with Gemini.
4. /help for more information."
`;
exports[`<AppHeader /> > should render the banner with default text 1`] = `
"
███ █████████

View File

@@ -10,10 +10,7 @@ exports[`SettingsDialog > Initial Rendering > should render settings list with v
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ ▲ │
│ ● Preview Features (e.g., models) false │
│ Enable preview features (e.g., preview models). │
│ │
│ Vim Mode false │
│ ● Vim Mode false │
│ Enable Vim keybindings │
│ │
│ Enable Auto Update true │
@@ -34,6 +31,9 @@ exports[`SettingsDialog > Initial Rendering > should render settings list with v
│ Auto Theme Switching true │
│ Automatically switch between default light and dark themes based on terminal backgro… │
│ │
│ Terminal Background Polling Interval 60 │
│ Interval in seconds to poll the terminal background color. │
│ │
│ ▼ │
│ │
│ Apply To │
@@ -56,10 +56,7 @@ exports[`SettingsDialog > Snapshot Tests > should render 'accessibility settings
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ ▲ │
│ ● Preview Features (e.g., models) false
│ Enable preview features (e.g., preview models). │
│ │
│ Vim Mode true* │
│ ● Vim Mode true*
│ Enable Vim keybindings │
│ │
│ Enable Auto Update true │
@@ -80,6 +77,9 @@ exports[`SettingsDialog > Snapshot Tests > should render 'accessibility settings
│ Auto Theme Switching true │
│ Automatically switch between default light and dark themes based on terminal backgro… │
│ │
│ Terminal Background Polling Interval 60 │
│ Interval in seconds to poll the terminal background color. │
│ │
│ ▼ │
│ │
│ Apply To │
@@ -102,10 +102,7 @@ exports[`SettingsDialog > Snapshot Tests > should render 'all boolean settings d
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ ▲ │
│ ● Preview Features (e.g., models) false │
│ Enable preview features (e.g., preview models). │
│ │
│ Vim Mode false* │
│ ● Vim Mode false*
│ Enable Vim keybindings │
│ │
│ Enable Auto Update true* │
@@ -126,6 +123,9 @@ exports[`SettingsDialog > Snapshot Tests > should render 'all boolean settings d
│ Auto Theme Switching true │
│ Automatically switch between default light and dark themes based on terminal backgro… │
│ │
│ Terminal Background Polling Interval 60 │
│ Interval in seconds to poll the terminal background color. │
│ │
│ ▼ │
│ │
│ Apply To │
@@ -148,10 +148,7 @@ exports[`SettingsDialog > Snapshot Tests > should render 'default state' correct
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ ▲ │
│ ● Preview Features (e.g., models) false │
│ Enable preview features (e.g., preview models). │
│ │
│ Vim Mode false │
│ ● Vim Mode false │
│ Enable Vim keybindings │
│ │
│ Enable Auto Update true │
@@ -172,6 +169,9 @@ exports[`SettingsDialog > Snapshot Tests > should render 'default state' correct
│ Auto Theme Switching true │
│ Automatically switch between default light and dark themes based on terminal backgro… │
│ │
│ Terminal Background Polling Interval 60 │
│ Interval in seconds to poll the terminal background color. │
│ │
│ ▼ │
│ │
│ Apply To │
@@ -194,10 +194,7 @@ exports[`SettingsDialog > Snapshot Tests > should render 'file filtering setting
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ ▲ │
│ ● Preview Features (e.g., models) false │
│ Enable preview features (e.g., preview models). │
│ │
│ Vim Mode false │
│ ● Vim Mode false │
│ Enable Vim keybindings │
│ │
│ Enable Auto Update true │
@@ -218,6 +215,9 @@ exports[`SettingsDialog > Snapshot Tests > should render 'file filtering setting
│ Auto Theme Switching true │
│ Automatically switch between default light and dark themes based on terminal backgro… │
│ │
│ Terminal Background Polling Interval 60 │
│ Interval in seconds to poll the terminal background color. │
│ │
│ ▼ │
│ │
│ Apply To │
@@ -240,9 +240,6 @@ exports[`SettingsDialog > Snapshot Tests > should render 'focused on scope selec
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ ▲ │
│ Preview Features (e.g., models) false │
│ Enable preview features (e.g., preview models). │
│ │
│ Vim Mode false │
│ Enable Vim keybindings │
│ │
@@ -264,6 +261,9 @@ exports[`SettingsDialog > Snapshot Tests > should render 'focused on scope selec
│ Auto Theme Switching true │
│ Automatically switch between default light and dark themes based on terminal backgro… │
│ │
│ Terminal Background Polling Interval 60 │
│ Interval in seconds to poll the terminal background color. │
│ │
│ ▼ │
│ │
│ > Apply To │
@@ -286,10 +286,7 @@ exports[`SettingsDialog > Snapshot Tests > should render 'mixed boolean and numb
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ ▲ │
│ ● Preview Features (e.g., models) false │
│ Enable preview features (e.g., preview models). │
│ │
│ Vim Mode false* │
│ ● Vim Mode false*
│ Enable Vim keybindings │
│ │
│ Enable Auto Update false* │
@@ -310,6 +307,9 @@ exports[`SettingsDialog > Snapshot Tests > should render 'mixed boolean and numb
│ Auto Theme Switching true │
│ Automatically switch between default light and dark themes based on terminal backgro… │
│ │
│ Terminal Background Polling Interval 60 │
│ Interval in seconds to poll the terminal background color. │
│ │
│ ▼ │
│ │
│ Apply To │
@@ -332,10 +332,7 @@ exports[`SettingsDialog > Snapshot Tests > should render 'tools and security set
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ ▲ │
│ ● Preview Features (e.g., models) false │
│ Enable preview features (e.g., preview models). │
│ │
│ Vim Mode false │
│ ● Vim Mode false │
│ Enable Vim keybindings │
│ │
│ Enable Auto Update true │
@@ -356,6 +353,9 @@ exports[`SettingsDialog > Snapshot Tests > should render 'tools and security set
│ Auto Theme Switching true │
│ Automatically switch between default light and dark themes based on terminal backgro… │
│ │
│ Terminal Background Polling Interval 60 │
│ Interval in seconds to poll the terminal background color. │
│ │
│ ▼ │
│ │
│ Apply To │
@@ -378,10 +378,7 @@ exports[`SettingsDialog > Snapshot Tests > should render 'various boolean settin
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ ▲ │
│ ● Preview Features (e.g., models) false
│ Enable preview features (e.g., preview models). │
│ │
│ Vim Mode true* │
│ ● Vim Mode true*
│ Enable Vim keybindings │
│ │
│ Enable Auto Update false* │
@@ -402,6 +399,9 @@ exports[`SettingsDialog > Snapshot Tests > should render 'various boolean settin
│ Auto Theme Switching true │
│ Automatically switch between default light and dark themes based on terminal backgro… │
│ │
│ Terminal Background Polling Interval 60 │
│ Interval in seconds to poll the terminal background color. │
│ │
│ ▼ │
│ │
│ Apply To │

View File

@@ -45,7 +45,6 @@ describe('<ToolGroupMessage />', () => {
folderTrust: false,
ideMode: false,
enableInteractiveShell: true,
previewFeatures: false,
enableEventDrivenScheduler: true,
});

View File

@@ -15,7 +15,6 @@ import {
import { renderHook } from '../../test-utils/render.js';
import { useBanner } from './useBanner.js';
import { persistentState } from '../../utils/persistentState.js';
import type { Config } from '@google/gemini-cli-core';
import crypto from 'node:crypto';
vi.mock('../../utils/persistentState.js', () => ({
@@ -39,13 +38,7 @@ vi.mock('../colors.js', () => ({
},
}));
// Define the shape of the config methods used by this hook
interface MockConfigShape {
getPreviewFeatures: MockedFunction<() => boolean>;
}
describe('useBanner', () => {
let mockConfig: MockConfigShape;
const mockedPersistentStateGet = persistentState.get as MockedFunction<
typeof persistentState.get
>;
@@ -61,11 +54,6 @@ describe('useBanner', () => {
beforeEach(() => {
vi.resetAllMocks();
// Initialize the mock config with default behavior
mockConfig = {
getPreviewFeatures: vi.fn().mockReturnValue(false),
};
// Default persistentState behavior: return empty object (no counts)
mockedPersistentStateGet.mockReturnValue({});
});
@@ -73,25 +61,11 @@ describe('useBanner', () => {
it('should return warning text and warning color if warningText is present', () => {
const data = { defaultText: 'Standard', warningText: 'Critical Error' };
const { result } = renderHook(() =>
useBanner(data, mockConfig as unknown as Config),
);
const { result } = renderHook(() => useBanner(data));
expect(result.current.bannerText).toBe('Critical Error');
});
it('should NOT show default banner if preview features are enabled in config', () => {
// Simulate Preview Features Enabled
mockConfig.getPreviewFeatures.mockReturnValue(true);
const { result } = renderHook(() =>
useBanner(defaultBannerData, mockConfig as unknown as Config),
);
// Should fall back to warningText (which is empty)
expect(result.current.bannerText).toBe('');
});
it('should hide banner if show count exceeds max limit (Legacy format)', () => {
mockedPersistentStateGet.mockReturnValue({
[crypto
@@ -100,9 +74,7 @@ describe('useBanner', () => {
.digest('hex')]: 5,
});
const { result } = renderHook(() =>
useBanner(defaultBannerData, mockConfig as unknown as Config),
);
const { result } = renderHook(() => useBanner(defaultBannerData));
expect(result.current.bannerText).toBe('');
});
@@ -115,7 +87,7 @@ describe('useBanner', () => {
[crypto.createHash('sha256').update(data.defaultText).digest('hex')]: 1,
});
renderHook(() => useBanner(data, mockConfig as unknown as Config));
renderHook(() => useBanner(data));
// Expect set to be called with incremented count
expect(mockedPersistentStateSet).toHaveBeenCalledWith(
@@ -129,7 +101,7 @@ describe('useBanner', () => {
it('should NOT increment count if warning text is shown instead', () => {
const data = { defaultText: 'Standard', warningText: 'Warning' };
renderHook(() => useBanner(data, mockConfig as unknown as Config));
renderHook(() => useBanner(data));
// Since warning text takes precedence, default banner logic (and increment) is skipped
expect(mockedPersistentStateSet).not.toHaveBeenCalled();
@@ -138,9 +110,7 @@ describe('useBanner', () => {
it('should handle newline replacements', () => {
const data = { defaultText: 'Line1\\nLine2', warningText: '' };
const { result } = renderHook(() =>
useBanner(data, mockConfig as unknown as Config),
);
const { result } = renderHook(() => useBanner(data));
expect(result.current.bannerText).toBe('Line1\nLine2');
});

View File

@@ -6,7 +6,6 @@
import { useState, useEffect, useRef } from 'react';
import { persistentState } from '../../utils/persistentState.js';
import type { Config } from '@google/gemini-cli-core';
import crypto from 'node:crypto';
const DEFAULT_MAX_BANNER_SHOWN_COUNT = 5;
@@ -16,20 +15,9 @@ interface BannerData {
warningText: string;
}
export function useBanner(bannerData: BannerData, config: Config) {
export function useBanner(bannerData: BannerData) {
const { defaultText, warningText } = bannerData;
const [previewEnabled, setPreviewEnabled] = useState(
config.getPreviewFeatures(),
);
useEffect(() => {
const isEnabled = config.getPreviewFeatures();
if (isEnabled !== previewEnabled) {
setPreviewEnabled(isEnabled);
}
}, [config, previewEnabled]);
const [bannerCounts] = useState(
() => persistentState.get('defaultBannerShownCount') || {},
);
@@ -42,9 +30,7 @@ export function useBanner(bannerData: BannerData, config: Config) {
const currentBannerCount = bannerCounts[hashedText] || 0;
const showDefaultBanner =
warningText === '' &&
!previewEnabled &&
currentBannerCount < DEFAULT_MAX_BANNER_SHOWN_COUNT;
warningText === '' && currentBannerCount < DEFAULT_MAX_BANNER_SHOWN_COUNT;
const rawBannerText = showDefaultBanner ? defaultText : warningText;
const bannerText = rawBannerText.replace(/\\n/g, '\n');

View File

@@ -328,8 +328,7 @@ describe('useQuotaAndFallback', () => {
const message = request!.message;
expect(message).toBe(
`It seems like you don't have access to gemini-3-pro-preview.
Learn more at https://goo.gle/enable-preview-features
To disable gemini-3-pro-preview, disable "Preview features" in /settings.`,
Your admin might have disabled the access. Contact them to enable the Preview Release Channel.`,
);
// Simulate the user choosing to switch

View File

@@ -90,8 +90,7 @@ export function useQuotaAndFallback({
isModelNotFoundError = true;
const messageLines = [
`It seems like you don't have access to ${failedModel}.`,
`Learn more at https://goo.gle/enable-preview-features`,
`To disable ${failedModel}, disable "Preview features" in /settings.`,
`Your admin might have disabled the access. Contact them to enable the Preview Release Channel.`,
];
message = messageLines.join('\n');
} else {