mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-26 13:04:49 -07:00
Remove previewFeatures and default to Gemini 3 (#18414)
This commit is contained in:
@@ -18,7 +18,6 @@ import {
|
||||
loadServerHierarchicalMemory,
|
||||
GEMINI_DIR,
|
||||
DEFAULT_GEMINI_EMBEDDING_MODEL,
|
||||
DEFAULT_GEMINI_MODEL,
|
||||
type ExtensionLoader,
|
||||
startupProfiler,
|
||||
PREVIEW_GEMINI_MODEL,
|
||||
@@ -60,9 +59,7 @@ export async function loadConfig(
|
||||
|
||||
const configParams: ConfigParameters = {
|
||||
sessionId: taskId,
|
||||
model: settings.general?.previewFeatures
|
||||
? PREVIEW_GEMINI_MODEL
|
||||
: DEFAULT_GEMINI_MODEL,
|
||||
model: PREVIEW_GEMINI_MODEL,
|
||||
embeddingModel: DEFAULT_GEMINI_EMBEDDING_MODEL,
|
||||
sandbox: undefined, // Sandbox might not be relevant for a server-side agent
|
||||
targetDir: workspaceDir, // Or a specific directory the agent operates on
|
||||
@@ -104,7 +101,6 @@ export async function loadConfig(
|
||||
trustedFolder: true,
|
||||
extensionLoader,
|
||||
checkpointing,
|
||||
previewFeatures: settings.general?.previewFeatures,
|
||||
interactive: true,
|
||||
enableInteractiveShell: true,
|
||||
ptyInfo: 'auto',
|
||||
|
||||
@@ -89,67 +89,6 @@ describe('loadSettings', () => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('should load nested previewFeatures from user settings', () => {
|
||||
const settings = {
|
||||
general: {
|
||||
previewFeatures: true,
|
||||
},
|
||||
};
|
||||
fs.writeFileSync(USER_SETTINGS_PATH, JSON.stringify(settings));
|
||||
|
||||
const result = loadSettings(mockWorkspaceDir);
|
||||
expect(result.general?.previewFeatures).toBe(true);
|
||||
});
|
||||
|
||||
it('should load nested previewFeatures from workspace settings', () => {
|
||||
const settings = {
|
||||
general: {
|
||||
previewFeatures: true,
|
||||
},
|
||||
};
|
||||
const workspaceSettingsPath = path.join(
|
||||
mockGeminiWorkspaceDir,
|
||||
'settings.json',
|
||||
);
|
||||
fs.writeFileSync(workspaceSettingsPath, JSON.stringify(settings));
|
||||
|
||||
const result = loadSettings(mockWorkspaceDir);
|
||||
expect(result.general?.previewFeatures).toBe(true);
|
||||
});
|
||||
|
||||
it('should prioritize workspace settings over user settings', () => {
|
||||
const userSettings = {
|
||||
general: {
|
||||
previewFeatures: false,
|
||||
},
|
||||
};
|
||||
fs.writeFileSync(USER_SETTINGS_PATH, JSON.stringify(userSettings));
|
||||
|
||||
const workspaceSettings = {
|
||||
general: {
|
||||
previewFeatures: true,
|
||||
},
|
||||
};
|
||||
const workspaceSettingsPath = path.join(
|
||||
mockGeminiWorkspaceDir,
|
||||
'settings.json',
|
||||
);
|
||||
fs.writeFileSync(workspaceSettingsPath, JSON.stringify(workspaceSettings));
|
||||
|
||||
const result = loadSettings(mockWorkspaceDir);
|
||||
expect(result.general?.previewFeatures).toBe(true);
|
||||
});
|
||||
|
||||
it('should handle missing previewFeatures', () => {
|
||||
const settings = {
|
||||
general: {},
|
||||
};
|
||||
fs.writeFileSync(USER_SETTINGS_PATH, JSON.stringify(settings));
|
||||
|
||||
const result = loadSettings(mockWorkspaceDir);
|
||||
expect(result.general?.previewFeatures).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should load other top-level settings correctly', () => {
|
||||
const settings = {
|
||||
showMemoryUsage: true,
|
||||
|
||||
@@ -31,9 +31,6 @@ export interface Settings {
|
||||
showMemoryUsage?: boolean;
|
||||
checkpointing?: CheckpointingSettings;
|
||||
folderTrust?: boolean;
|
||||
general?: {
|
||||
previewFeatures?: boolean;
|
||||
};
|
||||
|
||||
// Git-aware file filtering settings
|
||||
fileFiltering?: {
|
||||
|
||||
@@ -1683,7 +1683,7 @@ describe('loadCliConfig model selection', () => {
|
||||
argv,
|
||||
);
|
||||
|
||||
expect(config.getModel()).toBe('auto-gemini-2.5');
|
||||
expect(config.getModel()).toBe('auto-gemini-3');
|
||||
});
|
||||
|
||||
it('always prefers model from argv', async () => {
|
||||
@@ -1727,7 +1727,7 @@ describe('loadCliConfig model selection', () => {
|
||||
argv,
|
||||
);
|
||||
|
||||
expect(config.getModel()).toBe('auto-gemini-2.5');
|
||||
expect(config.getModel()).toBe('auto-gemini-3');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
setGeminiMdFilename as setServerGeminiMdFilename,
|
||||
getCurrentGeminiMdFilename,
|
||||
ApprovalMode,
|
||||
DEFAULT_GEMINI_MODEL_AUTO,
|
||||
DEFAULT_GEMINI_EMBEDDING_MODEL,
|
||||
DEFAULT_FILE_FILTERING_OPTIONS,
|
||||
DEFAULT_MEMORY_FILE_FILTERING_OPTIONS,
|
||||
@@ -662,9 +661,7 @@ export async function loadCliConfig(
|
||||
);
|
||||
policyEngineConfig.nonInteractive = !interactive;
|
||||
|
||||
const defaultModel = settings.general?.previewFeatures
|
||||
? PREVIEW_GEMINI_MODEL_AUTO
|
||||
: DEFAULT_GEMINI_MODEL_AUTO;
|
||||
const defaultModel = PREVIEW_GEMINI_MODEL_AUTO;
|
||||
const specifiedModel =
|
||||
argv.model || process.env['GEMINI_MODEL'] || settings.model?.name;
|
||||
|
||||
@@ -740,7 +737,6 @@ export async function loadCliConfig(
|
||||
settings.context?.loadMemoryFromIncludeDirectories || false,
|
||||
debugMode,
|
||||
question,
|
||||
previewFeatures: settings.general?.previewFeatures,
|
||||
|
||||
coreTools: settings.tools?.core || undefined,
|
||||
allowedTools: allowedTools.length > 0 ? allowedTools : undefined,
|
||||
|
||||
@@ -328,30 +328,6 @@ describe('SettingsSchema', () => {
|
||||
).toBe('Enable debug logging of keystrokes to the console.');
|
||||
});
|
||||
|
||||
it('should have previewFeatures setting in schema', () => {
|
||||
expect(
|
||||
getSettingsSchema().general.properties.previewFeatures,
|
||||
).toBeDefined();
|
||||
expect(getSettingsSchema().general.properties.previewFeatures.type).toBe(
|
||||
'boolean',
|
||||
);
|
||||
expect(
|
||||
getSettingsSchema().general.properties.previewFeatures.category,
|
||||
).toBe('General');
|
||||
expect(
|
||||
getSettingsSchema().general.properties.previewFeatures.default,
|
||||
).toBe(false);
|
||||
expect(
|
||||
getSettingsSchema().general.properties.previewFeatures.requiresRestart,
|
||||
).toBe(false);
|
||||
expect(
|
||||
getSettingsSchema().general.properties.previewFeatures.showInDialog,
|
||||
).toBe(true);
|
||||
expect(
|
||||
getSettingsSchema().general.properties.previewFeatures.description,
|
||||
).toBe('Enable preview features (e.g., preview models).');
|
||||
});
|
||||
|
||||
it('should have enableAgents setting in schema', () => {
|
||||
const setting = getSettingsSchema().experimental.properties.enableAgents;
|
||||
expect(setting).toBeDefined();
|
||||
|
||||
@@ -162,15 +162,6 @@ const SETTINGS_SCHEMA = {
|
||||
description: 'General application settings.',
|
||||
showInDialog: false,
|
||||
properties: {
|
||||
previewFeatures: {
|
||||
type: 'boolean',
|
||||
label: 'Preview Features (e.g., models)',
|
||||
category: 'General',
|
||||
requiresRestart: false,
|
||||
default: false,
|
||||
description: 'Enable preview features (e.g., preview models).',
|
||||
showInDialog: true,
|
||||
},
|
||||
preferredEditor: {
|
||||
type: 'string',
|
||||
label: 'Preferred Editor',
|
||||
|
||||
@@ -134,7 +134,6 @@ describe('Settings Repro', () => {
|
||||
enablePromptCompletion: false,
|
||||
preferredEditor: 'vim',
|
||||
vimMode: false,
|
||||
previewFeatures: false,
|
||||
},
|
||||
security: {
|
||||
auth: {
|
||||
|
||||
@@ -151,7 +151,6 @@ export const createMockConfig = (overrides: Partial<Config> = {}): Config =>
|
||||
getAllowedMcpServers: vi.fn().mockReturnValue([]),
|
||||
getBlockedMcpServers: vi.fn().mockReturnValue([]),
|
||||
getExperiments: vi.fn().mockReturnValue(undefined),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
getHasAccessToPreviewModel: vi.fn().mockReturnValue(false),
|
||||
...overrides,
|
||||
}) as unknown as Config;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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 && (
|
||||
<>
|
||||
|
||||
@@ -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.');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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`] = `
|
||||
"
|
||||
███ █████████
|
||||
|
||||
@@ -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 │
|
||||
|
||||
@@ -45,7 +45,6 @@ describe('<ToolGroupMessage />', () => {
|
||||
folderTrust: false,
|
||||
ideMode: false,
|
||||
enableInteractiveShell: true,
|
||||
previewFeatures: false,
|
||||
enableEventDrivenScheduler: true,
|
||||
});
|
||||
|
||||
|
||||
@@ -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');
|
||||
});
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -110,7 +110,6 @@ describe('GeminiAgent', () => {
|
||||
getContentGeneratorConfig: vi.fn(),
|
||||
getActiveModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue({}),
|
||||
getGeminiClient: vi.fn().mockReturnValue({
|
||||
startChat: vi.fn().mockResolvedValue({}),
|
||||
}),
|
||||
@@ -343,7 +342,6 @@ describe('Session', () => {
|
||||
mockConfig = {
|
||||
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getActiveModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue({}),
|
||||
getToolRegistry: vi.fn().mockReturnValue(mockToolRegistry),
|
||||
getFileService: vi.fn().mockReturnValue({
|
||||
shouldIgnoreFile: vi.fn().mockReturnValue(false),
|
||||
|
||||
@@ -482,10 +482,7 @@ export class Session {
|
||||
const functionCalls: FunctionCall[] = [];
|
||||
|
||||
try {
|
||||
const model = resolveModel(
|
||||
this.config.getModel(),
|
||||
this.config.getPreviewFeatures(),
|
||||
);
|
||||
const model = resolveModel(this.config.getModel());
|
||||
const responseStream = await chat.sendMessageStream(
|
||||
{ model },
|
||||
nextMessage?.parts ?? [],
|
||||
|
||||
@@ -27,7 +27,6 @@ describe('Fallback Integration', () => {
|
||||
getModel: () => PREVIEW_GEMINI_MODEL_AUTO,
|
||||
getActiveModel: () => PREVIEW_GEMINI_MODEL_AUTO,
|
||||
setActiveModel: vi.fn(),
|
||||
getPreviewFeatures: () => true, // Preview enabled for Gemini 3
|
||||
getUserTier: () => undefined,
|
||||
getModelAvailabilityService: () => availabilityService,
|
||||
modelConfigService: undefined as unknown as ModelConfigService,
|
||||
|
||||
@@ -19,7 +19,6 @@ import {
|
||||
|
||||
const createMockConfig = (overrides: Partial<Config> = {}): Config =>
|
||||
({
|
||||
getPreviewFeatures: () => false,
|
||||
getUserTier: () => undefined,
|
||||
getModel: () => 'gemini-2.5-pro',
|
||||
...overrides,
|
||||
|
||||
@@ -39,12 +39,7 @@ import { ToolRegistry } from '../tools/tool-registry.js';
|
||||
import { ACTIVATE_SKILL_TOOL_NAME } from '../tools/tool-names.js';
|
||||
import type { SkillDefinition } from '../skills/skillLoader.js';
|
||||
import { DEFAULT_MODEL_CONFIGS } from './defaultModelConfigs.js';
|
||||
import {
|
||||
DEFAULT_GEMINI_MODEL,
|
||||
DEFAULT_GEMINI_MODEL_AUTO,
|
||||
PREVIEW_GEMINI_MODEL,
|
||||
PREVIEW_GEMINI_MODEL_AUTO,
|
||||
} from './models.js';
|
||||
import { DEFAULT_GEMINI_MODEL, PREVIEW_GEMINI_MODEL } from './models.js';
|
||||
|
||||
vi.mock('fs', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('fs')>();
|
||||
@@ -511,78 +506,6 @@ describe('Server Config (config.ts)', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Preview Features Logic in refreshAuth', () => {
|
||||
beforeEach(() => {
|
||||
// Set up default mock behavior for these functions before each test
|
||||
vi.mocked(getCodeAssistServer).mockReturnValue(undefined);
|
||||
vi.mocked(getExperiments).mockResolvedValue({
|
||||
flags: {},
|
||||
experimentIds: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('should enable preview features for Google auth when remote flag is true', async () => {
|
||||
// Override the default mock for this specific test
|
||||
vi.mocked(getCodeAssistServer).mockReturnValue({} as CodeAssistServer); // Simulate Google auth by returning a truthy value
|
||||
vi.mocked(getExperiments).mockResolvedValue({
|
||||
flags: {
|
||||
[ExperimentFlags.ENABLE_PREVIEW]: { boolValue: true },
|
||||
},
|
||||
experimentIds: [],
|
||||
});
|
||||
const config = new Config({ ...baseParams, previewFeatures: undefined });
|
||||
await config.refreshAuth(AuthType.LOGIN_WITH_GOOGLE);
|
||||
expect(config.getPreviewFeatures()).toBe(true);
|
||||
});
|
||||
|
||||
it('should disable preview features for Google auth when remote flag is false', async () => {
|
||||
// Override the default mock
|
||||
vi.mocked(getCodeAssistServer).mockReturnValue({} as CodeAssistServer);
|
||||
vi.mocked(getExperiments).mockResolvedValue({
|
||||
flags: {
|
||||
[ExperimentFlags.ENABLE_PREVIEW]: { boolValue: false },
|
||||
},
|
||||
experimentIds: [],
|
||||
});
|
||||
const config = new Config({ ...baseParams, previewFeatures: undefined });
|
||||
await config.refreshAuth(AuthType.LOGIN_WITH_GOOGLE);
|
||||
expect(config.getPreviewFeatures()).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should disable preview features for Google auth when remote flag is missing', async () => {
|
||||
// Override the default mock for getCodeAssistServer, the getExperiments mock is already correct
|
||||
vi.mocked(getCodeAssistServer).mockReturnValue({} as CodeAssistServer);
|
||||
const config = new Config({ ...baseParams, previewFeatures: undefined });
|
||||
await config.refreshAuth(AuthType.LOGIN_WITH_GOOGLE);
|
||||
expect(config.getPreviewFeatures()).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should not change preview features or model if it is already set to true', async () => {
|
||||
const initialModel = 'some-other-model';
|
||||
const config = new Config({
|
||||
...baseParams,
|
||||
previewFeatures: true,
|
||||
model: initialModel,
|
||||
});
|
||||
// It doesn't matter which auth method we use here, the logic should exit early
|
||||
await config.refreshAuth(AuthType.USE_GEMINI);
|
||||
expect(config.getPreviewFeatures()).toBe(true);
|
||||
expect(config.getModel()).toBe(initialModel);
|
||||
});
|
||||
|
||||
it('should not change preview features or model if it is already set to false', async () => {
|
||||
const initialModel = 'some-other-model';
|
||||
const config = new Config({
|
||||
...baseParams,
|
||||
previewFeatures: false,
|
||||
model: initialModel,
|
||||
});
|
||||
await config.refreshAuth(AuthType.USE_GEMINI);
|
||||
expect(config.getPreviewFeatures()).toBe(false);
|
||||
expect(config.getModel()).toBe(initialModel);
|
||||
});
|
||||
});
|
||||
|
||||
it('Config constructor should store userMemory correctly', () => {
|
||||
const config = new Config(baseParams);
|
||||
|
||||
@@ -2105,45 +2028,6 @@ describe('Config Quota & Preview Model Access', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('setPreviewFeatures', () => {
|
||||
it('should reset model to default auto if disabling preview features while using a preview model', () => {
|
||||
config.setPreviewFeatures(true);
|
||||
config.setModel(PREVIEW_GEMINI_MODEL);
|
||||
|
||||
config.setPreviewFeatures(false);
|
||||
|
||||
expect(config.getModel()).toBe(DEFAULT_GEMINI_MODEL_AUTO);
|
||||
});
|
||||
|
||||
it('should NOT reset model if disabling preview features while NOT using a preview model', () => {
|
||||
config.setPreviewFeatures(true);
|
||||
const nonPreviewModel = 'gemini-1.5-pro';
|
||||
config.setModel(nonPreviewModel);
|
||||
|
||||
config.setPreviewFeatures(false);
|
||||
|
||||
expect(config.getModel()).toBe(nonPreviewModel);
|
||||
});
|
||||
|
||||
it('should switch to preview auto model if enabling preview features while using default auto model', () => {
|
||||
config.setPreviewFeatures(false);
|
||||
config.setModel(DEFAULT_GEMINI_MODEL_AUTO);
|
||||
|
||||
config.setPreviewFeatures(true);
|
||||
|
||||
expect(config.getModel()).toBe(PREVIEW_GEMINI_MODEL_AUTO);
|
||||
});
|
||||
|
||||
it('should NOT reset model if enabling preview features', () => {
|
||||
config.setPreviewFeatures(false);
|
||||
config.setModel(PREVIEW_GEMINI_MODEL); // Just pretending it was set somehow
|
||||
|
||||
config.setPreviewFeatures(true);
|
||||
|
||||
expect(config.getModel()).toBe(PREVIEW_GEMINI_MODEL);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isPlanEnabled', () => {
|
||||
it('should return false by default', () => {
|
||||
const config = new Config(baseParams);
|
||||
|
||||
@@ -56,7 +56,6 @@ import {
|
||||
DEFAULT_GEMINI_MODEL_AUTO,
|
||||
isPreviewModel,
|
||||
PREVIEW_GEMINI_MODEL,
|
||||
PREVIEW_GEMINI_MODEL_AUTO,
|
||||
} from './models.js';
|
||||
import { shouldAttemptBrowserLaunch } from '../utils/browser.js';
|
||||
import type { MCPOAuthConfig } from '../mcp/oauth-provider.js';
|
||||
@@ -467,7 +466,6 @@ export interface ConfigParameters {
|
||||
hooks?: { [K in HookEventName]?: HookDefinition[] };
|
||||
disabledHooks?: string[];
|
||||
projectHooks?: { [K in HookEventName]?: HookDefinition[] };
|
||||
previewFeatures?: boolean;
|
||||
enableAgents?: boolean;
|
||||
enableEventDrivenScheduler?: boolean;
|
||||
skillsSupport?: boolean;
|
||||
@@ -552,7 +550,6 @@ export class Config {
|
||||
private readonly bugCommand: BugCommandSettings | undefined;
|
||||
private model: string;
|
||||
private readonly disableLoopDetection: boolean;
|
||||
private previewFeatures: boolean | undefined;
|
||||
private hasAccessToPreviewModel: boolean = false;
|
||||
private readonly noBrowser: boolean;
|
||||
private readonly folderTrust: boolean;
|
||||
@@ -733,7 +730,6 @@ export class Config {
|
||||
this.disabledSkills = params.disabledSkills ?? [];
|
||||
this.adminSkillsEnabled = params.adminSkillsEnabled ?? true;
|
||||
this.modelAvailabilityService = new ModelAvailabilityService();
|
||||
this.previewFeatures = params.previewFeatures ?? undefined;
|
||||
this.experimentalJitContext = params.experimentalJitContext ?? false;
|
||||
this.toolOutputMasking = {
|
||||
enabled: params.toolOutputMasking?.enabled ?? false,
|
||||
@@ -1027,15 +1023,6 @@ export class Config {
|
||||
this.experimentsPromise = getExperiments(codeAssistServer)
|
||||
.then((experiments) => {
|
||||
this.setExperiments(experiments);
|
||||
|
||||
// If preview features have not been set and the user authenticated through Google, we enable preview based on remote config only if it's true
|
||||
if (this.getPreviewFeatures() === undefined) {
|
||||
const remotePreviewFeatures =
|
||||
experiments.flags[ExperimentFlags.ENABLE_PREVIEW]?.boolValue;
|
||||
if (remotePreviewFeatures === true) {
|
||||
this.setPreviewFeatures(remotePreviewFeatures);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
debugLogger.error('Failed to fetch experiments', e);
|
||||
@@ -1288,29 +1275,6 @@ export class Config {
|
||||
return this.question;
|
||||
}
|
||||
|
||||
getPreviewFeatures(): boolean | undefined {
|
||||
return this.previewFeatures;
|
||||
}
|
||||
|
||||
setPreviewFeatures(previewFeatures: boolean) {
|
||||
// No change in state, no action needed
|
||||
if (this.previewFeatures === previewFeatures) {
|
||||
return;
|
||||
}
|
||||
this.previewFeatures = previewFeatures;
|
||||
const currentModel = this.getModel();
|
||||
|
||||
// Case 1: Disabling preview features while on a preview model
|
||||
if (!previewFeatures && isPreviewModel(currentModel)) {
|
||||
this.setModel(DEFAULT_GEMINI_MODEL_AUTO);
|
||||
}
|
||||
|
||||
// Case 2: Enabling preview features while on the default auto model
|
||||
else if (previewFeatures && currentModel === DEFAULT_GEMINI_MODEL_AUTO) {
|
||||
this.setModel(PREVIEW_GEMINI_MODEL_AUTO);
|
||||
}
|
||||
}
|
||||
|
||||
getHasAccessToPreviewModel(): boolean {
|
||||
return this.hasAccessToPreviewModel;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
supportsMultimodalFunctionResponse,
|
||||
GEMINI_MODEL_ALIAS_PRO,
|
||||
GEMINI_MODEL_ALIAS_FLASH,
|
||||
GEMINI_MODEL_ALIAS_FLASH_LITE,
|
||||
GEMINI_MODEL_ALIAS_AUTO,
|
||||
PREVIEW_GEMINI_FLASH_MODEL,
|
||||
PREVIEW_GEMINI_MODEL_AUTO,
|
||||
@@ -37,19 +36,11 @@ describe('getDisplayString', () => {
|
||||
});
|
||||
|
||||
it('should return concrete model name for pro alias', () => {
|
||||
expect(getDisplayString(GEMINI_MODEL_ALIAS_PRO, false)).toBe(
|
||||
DEFAULT_GEMINI_MODEL,
|
||||
);
|
||||
expect(getDisplayString(GEMINI_MODEL_ALIAS_PRO, true)).toBe(
|
||||
PREVIEW_GEMINI_MODEL,
|
||||
);
|
||||
expect(getDisplayString(GEMINI_MODEL_ALIAS_PRO)).toBe(PREVIEW_GEMINI_MODEL);
|
||||
});
|
||||
|
||||
it('should return concrete model name for flash alias', () => {
|
||||
expect(getDisplayString(GEMINI_MODEL_ALIAS_FLASH, false)).toBe(
|
||||
DEFAULT_GEMINI_FLASH_MODEL,
|
||||
);
|
||||
expect(getDisplayString(GEMINI_MODEL_ALIAS_FLASH, true)).toBe(
|
||||
expect(getDisplayString(GEMINI_MODEL_ALIAS_FLASH)).toBe(
|
||||
PREVIEW_GEMINI_FLASH_MODEL,
|
||||
);
|
||||
});
|
||||
@@ -81,69 +72,30 @@ describe('supportsMultimodalFunctionResponse', () => {
|
||||
describe('resolveModel', () => {
|
||||
describe('delegation logic', () => {
|
||||
it('should return the Preview Pro model when auto-gemini-3 is requested', () => {
|
||||
const model = resolveModel(PREVIEW_GEMINI_MODEL_AUTO, false);
|
||||
const model = resolveModel(PREVIEW_GEMINI_MODEL_AUTO);
|
||||
expect(model).toBe(PREVIEW_GEMINI_MODEL);
|
||||
});
|
||||
|
||||
it('should return the Default Pro model when auto-gemini-2.5 is requested', () => {
|
||||
const model = resolveModel(DEFAULT_GEMINI_MODEL_AUTO, false);
|
||||
const model = resolveModel(DEFAULT_GEMINI_MODEL_AUTO);
|
||||
expect(model).toBe(DEFAULT_GEMINI_MODEL);
|
||||
});
|
||||
|
||||
it('should return the requested model as-is for explicit specific models', () => {
|
||||
expect(resolveModel(DEFAULT_GEMINI_MODEL, false)).toBe(
|
||||
DEFAULT_GEMINI_MODEL,
|
||||
);
|
||||
expect(resolveModel(DEFAULT_GEMINI_FLASH_MODEL, false)).toBe(
|
||||
expect(resolveModel(DEFAULT_GEMINI_MODEL)).toBe(DEFAULT_GEMINI_MODEL);
|
||||
expect(resolveModel(DEFAULT_GEMINI_FLASH_MODEL)).toBe(
|
||||
DEFAULT_GEMINI_FLASH_MODEL,
|
||||
);
|
||||
expect(resolveModel(DEFAULT_GEMINI_FLASH_LITE_MODEL, false)).toBe(
|
||||
expect(resolveModel(DEFAULT_GEMINI_FLASH_LITE_MODEL)).toBe(
|
||||
DEFAULT_GEMINI_FLASH_LITE_MODEL,
|
||||
);
|
||||
});
|
||||
|
||||
it('should return a custom model name when requested', () => {
|
||||
const customModel = 'custom-model-v1';
|
||||
const model = resolveModel(customModel, false);
|
||||
const model = resolveModel(customModel);
|
||||
expect(model).toBe(customModel);
|
||||
});
|
||||
|
||||
describe('with preview features', () => {
|
||||
it('should return the preview model when pro alias is requested', () => {
|
||||
const model = resolveModel(GEMINI_MODEL_ALIAS_PRO, true);
|
||||
expect(model).toBe(PREVIEW_GEMINI_MODEL);
|
||||
});
|
||||
|
||||
it('should return the default pro model when pro alias is requested and preview is off', () => {
|
||||
const model = resolveModel(GEMINI_MODEL_ALIAS_PRO, false);
|
||||
expect(model).toBe(DEFAULT_GEMINI_MODEL);
|
||||
});
|
||||
|
||||
it('should return the flash model when flash is requested and preview is on', () => {
|
||||
const model = resolveModel(GEMINI_MODEL_ALIAS_FLASH, true);
|
||||
expect(model).toBe(PREVIEW_GEMINI_FLASH_MODEL);
|
||||
});
|
||||
|
||||
it('should return the flash model when lite is requested and preview is on', () => {
|
||||
const model = resolveModel(GEMINI_MODEL_ALIAS_FLASH_LITE, true);
|
||||
expect(model).toBe(DEFAULT_GEMINI_FLASH_LITE_MODEL);
|
||||
});
|
||||
|
||||
it('should return the flash model when the flash model name is explicitly requested and preview is on', () => {
|
||||
const model = resolveModel(DEFAULT_GEMINI_FLASH_MODEL, true);
|
||||
expect(model).toBe(DEFAULT_GEMINI_FLASH_MODEL);
|
||||
});
|
||||
|
||||
it('should return the lite model when the lite model name is requested and preview is on', () => {
|
||||
const model = resolveModel(DEFAULT_GEMINI_FLASH_LITE_MODEL, true);
|
||||
expect(model).toBe(DEFAULT_GEMINI_FLASH_LITE_MODEL);
|
||||
});
|
||||
|
||||
it('should return the default gemini model when the model is explicitly set and preview is on', () => {
|
||||
const model = resolveModel(DEFAULT_GEMINI_MODEL, true);
|
||||
expect(model).toBe(DEFAULT_GEMINI_MODEL);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -217,18 +169,4 @@ describe('resolveClassifierModel', () => {
|
||||
resolveClassifierModel(PREVIEW_GEMINI_MODEL_AUTO, GEMINI_MODEL_ALIAS_PRO),
|
||||
).toBe(PREVIEW_GEMINI_MODEL);
|
||||
});
|
||||
|
||||
it('should handle preview features being enabled', () => {
|
||||
// If preview is enabled, resolving 'flash' without context (fallback) might switch to preview flash,
|
||||
// but here we test explicit auto models which should stick to their families if possible?
|
||||
// Actually our logic forces DEFAULT_GEMINI_FLASH_MODEL for DEFAULT_GEMINI_MODEL_AUTO even if preview is on,
|
||||
// because the USER requested 2.5 explicitly via "auto-gemini-2.5".
|
||||
expect(
|
||||
resolveClassifierModel(
|
||||
DEFAULT_GEMINI_MODEL_AUTO,
|
||||
GEMINI_MODEL_ALIAS_FLASH,
|
||||
true,
|
||||
),
|
||||
).toBe(DEFAULT_GEMINI_FLASH_MODEL);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -34,16 +34,12 @@ export const DEFAULT_THINKING_MODE = 8192;
|
||||
|
||||
/**
|
||||
* Resolves the requested model alias (e.g., 'auto-gemini-3', 'pro', 'flash', 'flash-lite')
|
||||
* to a concrete model name, considering preview features.
|
||||
* to a concrete model name.
|
||||
*
|
||||
* @param requestedModel The model alias or concrete model name requested by the user.
|
||||
* @param previewFeaturesEnabled A boolean indicating if preview features are enabled.
|
||||
* @returns The resolved concrete model name.
|
||||
*/
|
||||
export function resolveModel(
|
||||
requestedModel: string,
|
||||
previewFeaturesEnabled: boolean = false,
|
||||
): string {
|
||||
export function resolveModel(requestedModel: string): string {
|
||||
switch (requestedModel) {
|
||||
case PREVIEW_GEMINI_MODEL_AUTO: {
|
||||
return PREVIEW_GEMINI_MODEL;
|
||||
@@ -53,14 +49,10 @@ export function resolveModel(
|
||||
}
|
||||
case GEMINI_MODEL_ALIAS_AUTO:
|
||||
case GEMINI_MODEL_ALIAS_PRO: {
|
||||
return previewFeaturesEnabled
|
||||
? PREVIEW_GEMINI_MODEL
|
||||
: DEFAULT_GEMINI_MODEL;
|
||||
return PREVIEW_GEMINI_MODEL;
|
||||
}
|
||||
case GEMINI_MODEL_ALIAS_FLASH: {
|
||||
return previewFeaturesEnabled
|
||||
? PREVIEW_GEMINI_FLASH_MODEL
|
||||
: DEFAULT_GEMINI_FLASH_MODEL;
|
||||
return PREVIEW_GEMINI_FLASH_MODEL;
|
||||
}
|
||||
case GEMINI_MODEL_ALIAS_FLASH_LITE: {
|
||||
return DEFAULT_GEMINI_FLASH_LITE_MODEL;
|
||||
@@ -76,13 +68,11 @@ export function resolveModel(
|
||||
*
|
||||
* @param requestedModel The current requested model (e.g. auto-gemini-2.5).
|
||||
* @param modelAlias The alias selected by the classifier ('flash' or 'pro').
|
||||
* @param previewFeaturesEnabled Whether preview features are enabled.
|
||||
* @returns The resolved concrete model name.
|
||||
*/
|
||||
export function resolveClassifierModel(
|
||||
requestedModel: string,
|
||||
modelAlias: string,
|
||||
previewFeaturesEnabled: boolean = false,
|
||||
): string {
|
||||
if (modelAlias === GEMINI_MODEL_ALIAS_FLASH) {
|
||||
if (
|
||||
@@ -97,27 +87,20 @@ export function resolveClassifierModel(
|
||||
) {
|
||||
return PREVIEW_GEMINI_FLASH_MODEL;
|
||||
}
|
||||
return resolveModel(GEMINI_MODEL_ALIAS_FLASH, previewFeaturesEnabled);
|
||||
return resolveModel(GEMINI_MODEL_ALIAS_FLASH);
|
||||
}
|
||||
return resolveModel(requestedModel, previewFeaturesEnabled);
|
||||
return resolveModel(requestedModel);
|
||||
}
|
||||
export function getDisplayString(
|
||||
model: string,
|
||||
previewFeaturesEnabled: boolean = false,
|
||||
) {
|
||||
export function getDisplayString(model: string) {
|
||||
switch (model) {
|
||||
case PREVIEW_GEMINI_MODEL_AUTO:
|
||||
return 'Auto (Gemini 3)';
|
||||
case DEFAULT_GEMINI_MODEL_AUTO:
|
||||
return 'Auto (Gemini 2.5)';
|
||||
case GEMINI_MODEL_ALIAS_PRO:
|
||||
return previewFeaturesEnabled
|
||||
? PREVIEW_GEMINI_MODEL
|
||||
: DEFAULT_GEMINI_MODEL;
|
||||
return PREVIEW_GEMINI_MODEL;
|
||||
case GEMINI_MODEL_ALIAS_FLASH:
|
||||
return previewFeaturesEnabled
|
||||
? PREVIEW_GEMINI_FLASH_MODEL
|
||||
: DEFAULT_GEMINI_FLASH_MODEL;
|
||||
return PREVIEW_GEMINI_FLASH_MODEL;
|
||||
default:
|
||||
return model;
|
||||
}
|
||||
|
||||
@@ -115,7 +115,6 @@ describe('BaseLlmClient', () => {
|
||||
.fn()
|
||||
.mockReturnValue(createAvailabilityServiceMock()),
|
||||
setActiveModel: vi.fn(),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
getUserTier: vi.fn().mockReturnValue(undefined),
|
||||
getModel: vi.fn().mockReturnValue('test-model'),
|
||||
getActiveModel: vi.fn().mockReturnValue('test-model'),
|
||||
|
||||
@@ -228,7 +228,6 @@ describe('Gemini Client (client.ts)', () => {
|
||||
getIdeModeFeature: vi.fn().mockReturnValue(false),
|
||||
getIdeMode: vi.fn().mockReturnValue(true),
|
||||
getDebugMode: vi.fn().mockReturnValue(false),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
getWorkspaceContext: vi.fn().mockReturnValue({
|
||||
getDirectories: vi.fn().mockReturnValue(['/test/dir']),
|
||||
}),
|
||||
|
||||
@@ -31,7 +31,6 @@ const mockConfig = {
|
||||
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getProxy: vi.fn().mockReturnValue(undefined),
|
||||
getUsageStatisticsEnabled: vi.fn().mockReturnValue(true),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
|
||||
describe('createContentGenerator', () => {
|
||||
@@ -121,7 +120,6 @@ describe('createContentGenerator', () => {
|
||||
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getProxy: vi.fn().mockReturnValue(undefined),
|
||||
getUsageStatisticsEnabled: () => true,
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
|
||||
// Set a fixed version for testing
|
||||
@@ -189,7 +187,6 @@ describe('createContentGenerator', () => {
|
||||
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getProxy: vi.fn().mockReturnValue(undefined),
|
||||
getUsageStatisticsEnabled: () => false,
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
|
||||
const mockGenerator = {
|
||||
@@ -236,7 +233,6 @@ describe('createContentGenerator', () => {
|
||||
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getProxy: vi.fn().mockReturnValue(undefined),
|
||||
getUsageStatisticsEnabled: () => false,
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
|
||||
const mockGenerator = {
|
||||
@@ -270,7 +266,6 @@ describe('createContentGenerator', () => {
|
||||
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getProxy: vi.fn().mockReturnValue(undefined),
|
||||
getUsageStatisticsEnabled: () => false,
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
|
||||
const mockGenerator = {
|
||||
@@ -312,7 +307,6 @@ describe('createContentGenerator', () => {
|
||||
const mockConfig = {
|
||||
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getUsageStatisticsEnabled: () => false,
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
const mockGenerator = {
|
||||
models: {},
|
||||
@@ -344,7 +338,6 @@ describe('createContentGenerator', () => {
|
||||
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getProxy: vi.fn().mockReturnValue(undefined),
|
||||
getUsageStatisticsEnabled: () => false,
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
|
||||
const mockGenerator = {
|
||||
@@ -378,7 +371,6 @@ describe('createContentGenerator', () => {
|
||||
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getProxy: vi.fn().mockReturnValue(undefined),
|
||||
getUsageStatisticsEnabled: () => false,
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
|
||||
const mockGenerator = {
|
||||
@@ -416,7 +408,6 @@ describe('createContentGenerator', () => {
|
||||
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getProxy: vi.fn().mockReturnValue(undefined),
|
||||
getUsageStatisticsEnabled: () => false,
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
|
||||
const mockGenerator = {
|
||||
@@ -455,7 +446,6 @@ describe('createContentGenerator', () => {
|
||||
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getProxy: vi.fn().mockReturnValue(undefined),
|
||||
getUsageStatisticsEnabled: () => false,
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
|
||||
const mockGenerator = {
|
||||
|
||||
@@ -122,10 +122,7 @@ export async function createContentGenerator(
|
||||
return new LoggingContentGenerator(fakeGenerator, gcConfig);
|
||||
}
|
||||
const version = await getVersion();
|
||||
const model = resolveModel(
|
||||
gcConfig.getModel(),
|
||||
gcConfig.getPreviewFeatures(),
|
||||
);
|
||||
const model = resolveModel(gcConfig.getModel());
|
||||
const customHeadersEnv =
|
||||
process.env['GEMINI_CLI_CUSTOM_HEADERS'] || undefined;
|
||||
const userAgent = `GeminiCLI/${version}/${model} (${process.platform}; ${process.arch})`;
|
||||
|
||||
@@ -130,7 +130,6 @@ describe('GeminiChat', () => {
|
||||
getTelemetryLogPromptsEnabled: () => true,
|
||||
getUsageStatisticsEnabled: () => true,
|
||||
getDebugMode: () => false,
|
||||
getPreviewFeatures: () => false,
|
||||
getContentGeneratorConfig: vi.fn().mockImplementation(() => ({
|
||||
authType: 'oauth-personal',
|
||||
model: currentModel,
|
||||
|
||||
@@ -492,18 +492,12 @@ export class GeminiChat {
|
||||
|
||||
const apiCall = async () => {
|
||||
// Default to the last used model (which respects arguments/availability selection)
|
||||
let modelToUse = resolveModel(
|
||||
lastModelToUse,
|
||||
this.config.getPreviewFeatures(),
|
||||
);
|
||||
let modelToUse = resolveModel(lastModelToUse);
|
||||
|
||||
// If the active model has changed (e.g. due to a fallback updating the config),
|
||||
// we switch to the new active model.
|
||||
if (this.config.getActiveModel() !== initialActiveModel) {
|
||||
modelToUse = resolveModel(
|
||||
this.config.getActiveModel(),
|
||||
this.config.getPreviewFeatures(),
|
||||
);
|
||||
modelToUse = resolveModel(this.config.getActiveModel());
|
||||
}
|
||||
|
||||
if (modelToUse !== lastModelToUse) {
|
||||
|
||||
@@ -78,7 +78,6 @@ describe('GeminiChat Network Retries', () => {
|
||||
getTelemetryLogPromptsEnabled: () => true,
|
||||
getUsageStatisticsEnabled: () => true,
|
||||
getDebugMode: () => false,
|
||||
getPreviewFeatures: () => false,
|
||||
getContentGeneratorConfig: vi.fn().mockReturnValue({
|
||||
authType: 'oauth-personal',
|
||||
model: 'test-model',
|
||||
|
||||
@@ -38,7 +38,6 @@ describe('Core System Prompt Substitution', () => {
|
||||
isAgentsEnabled: vi.fn().mockReturnValue(false),
|
||||
getModel: vi.fn().mockReturnValue('auto'),
|
||||
getActiveModel: vi.fn().mockReturnValue('gemini-1.5-pro'),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
getAgentRegistry: vi.fn().mockReturnValue({
|
||||
getDirectoryContext: vi.fn().mockReturnValue('Mock Agent Directory'),
|
||||
}),
|
||||
|
||||
@@ -96,7 +96,6 @@ describe('Core System Prompt (prompts.ts)', () => {
|
||||
isAgentsEnabled: vi.fn().mockReturnValue(false),
|
||||
getModel: vi.fn().mockReturnValue(DEFAULT_GEMINI_MODEL_AUTO),
|
||||
getActiveModel: vi.fn().mockReturnValue(DEFAULT_GEMINI_MODEL),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
getMessageBus: vi.fn(),
|
||||
getAgentRegistry: vi.fn().mockReturnValue({
|
||||
getDirectoryContext: vi.fn().mockReturnValue('Mock Agent Directory'),
|
||||
@@ -259,7 +258,6 @@ describe('Core System Prompt (prompts.ts)', () => {
|
||||
isAgentsEnabled: vi.fn().mockReturnValue(false),
|
||||
getModel: vi.fn().mockReturnValue('auto'),
|
||||
getActiveModel: vi.fn().mockReturnValue(DEFAULT_GEMINI_MODEL),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
getAgentRegistry: vi.fn().mockReturnValue({
|
||||
getDirectoryContext: vi.fn().mockReturnValue('Mock Agent Directory'),
|
||||
}),
|
||||
|
||||
@@ -75,7 +75,6 @@ const createMockConfig = (overrides: Partial<Config> = {}): Config =>
|
||||
),
|
||||
getActiveModel: vi.fn(() => MOCK_PRO_MODEL),
|
||||
getModel: vi.fn(() => MOCK_PRO_MODEL),
|
||||
getPreviewFeatures: vi.fn(() => false),
|
||||
getUserTier: vi.fn(() => undefined),
|
||||
isInteractive: vi.fn(() => false),
|
||||
...overrides,
|
||||
@@ -141,7 +140,6 @@ describe('handleFallback', () => {
|
||||
|
||||
it('uses availability selection with correct candidates when enabled', async () => {
|
||||
// Direct mock manipulation since it's already a vi.fn()
|
||||
vi.mocked(policyConfig.getPreviewFeatures).mockReturnValue(true);
|
||||
vi.mocked(policyConfig.getModel).mockReturnValue(
|
||||
DEFAULT_GEMINI_MODEL_AUTO,
|
||||
);
|
||||
@@ -210,7 +208,6 @@ describe('handleFallback', () => {
|
||||
|
||||
it('does not wrap around to upgrade candidates if the current model was selected at the end (e.g. by router)', async () => {
|
||||
// Last-resort failure (Flash) in [Preview, Pro, Flash] checks Preview then Pro (all upstream).
|
||||
vi.mocked(policyConfig.getPreviewFeatures).mockReturnValue(true);
|
||||
vi.mocked(policyConfig.getModel).mockReturnValue(
|
||||
DEFAULT_GEMINI_MODEL_AUTO,
|
||||
);
|
||||
@@ -241,7 +238,6 @@ describe('handleFallback', () => {
|
||||
skipped: [],
|
||||
});
|
||||
policyHandler.mockResolvedValue('retry_once');
|
||||
vi.mocked(policyConfig.getPreviewFeatures).mockReturnValue(true);
|
||||
vi.mocked(policyConfig.getActiveModel).mockReturnValue(
|
||||
PREVIEW_GEMINI_MODEL,
|
||||
);
|
||||
|
||||
@@ -52,10 +52,7 @@ export class PromptProvider {
|
||||
const enabledToolNames = new Set(toolNames);
|
||||
const approvedPlanPath = config.getApprovedPlanPath();
|
||||
|
||||
const desiredModel = resolveModel(
|
||||
config.getActiveModel(),
|
||||
config.getPreviewFeatures(),
|
||||
);
|
||||
const desiredModel = resolveModel(config.getActiveModel());
|
||||
const isGemini3 = isPreviewModel(desiredModel);
|
||||
|
||||
// --- Context Gathering ---
|
||||
|
||||
@@ -51,7 +51,6 @@ describe('ClassifierStrategy', () => {
|
||||
getResolvedConfig: vi.fn().mockReturnValue(mockResolvedConfig),
|
||||
},
|
||||
getModel: () => DEFAULT_GEMINI_MODEL_AUTO,
|
||||
getPreviewFeatures: () => false,
|
||||
getNumericalRoutingEnabled: vi.fn().mockResolvedValue(false),
|
||||
} as unknown as Config;
|
||||
mockBaseLlmClient = {
|
||||
|
||||
@@ -166,7 +166,6 @@ export class ClassifierStrategy implements RoutingStrategy {
|
||||
const selectedModel = resolveClassifierModel(
|
||||
context.requestedModel ?? config.getModel(),
|
||||
routerResponse.model_choice,
|
||||
config.getPreviewFeatures(),
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -24,7 +24,6 @@ describe('DefaultStrategy', () => {
|
||||
const mockContext = {} as RoutingContext;
|
||||
const mockConfig = {
|
||||
getModel: vi.fn().mockReturnValue(DEFAULT_GEMINI_MODEL_AUTO),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
const mockClient = {} as BaseLlmClient;
|
||||
|
||||
@@ -45,7 +44,6 @@ describe('DefaultStrategy', () => {
|
||||
const mockContext = {} as RoutingContext;
|
||||
const mockConfig = {
|
||||
getModel: vi.fn().mockReturnValue(PREVIEW_GEMINI_MODEL_AUTO),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
const mockClient = {} as BaseLlmClient;
|
||||
|
||||
@@ -61,12 +59,11 @@ describe('DefaultStrategy', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should route to the preview model when requested model is auto and previewfeature is on', async () => {
|
||||
it('should route to the default model when requested model is auto', async () => {
|
||||
const strategy = new DefaultStrategy();
|
||||
const mockContext = {} as RoutingContext;
|
||||
const mockConfig = {
|
||||
getModel: vi.fn().mockReturnValue(GEMINI_MODEL_ALIAS_AUTO),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(true),
|
||||
} as unknown as Config;
|
||||
const mockClient = {} as BaseLlmClient;
|
||||
|
||||
@@ -82,34 +79,12 @@ describe('DefaultStrategy', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should route to the default model when requested model is auto and previewfeature is off', async () => {
|
||||
const strategy = new DefaultStrategy();
|
||||
const mockContext = {} as RoutingContext;
|
||||
const mockConfig = {
|
||||
getModel: vi.fn().mockReturnValue(GEMINI_MODEL_ALIAS_AUTO),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
const mockClient = {} as BaseLlmClient;
|
||||
|
||||
const decision = await strategy.route(mockContext, mockConfig, mockClient);
|
||||
|
||||
expect(decision).toEqual({
|
||||
model: DEFAULT_GEMINI_MODEL,
|
||||
metadata: {
|
||||
source: 'default',
|
||||
latencyMs: 0,
|
||||
reasoning: `Routing to default model: ${DEFAULT_GEMINI_MODEL}`,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// this should not happen, adding the test just in case it happens.
|
||||
it('should route to the same model if it is not an auto mode', async () => {
|
||||
const strategy = new DefaultStrategy();
|
||||
const mockContext = {} as RoutingContext;
|
||||
const mockConfig = {
|
||||
getModel: vi.fn().mockReturnValue(PREVIEW_GEMINI_FLASH_MODEL),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
const mockClient = {} as BaseLlmClient;
|
||||
|
||||
|
||||
@@ -21,10 +21,7 @@ export class DefaultStrategy implements TerminalStrategy {
|
||||
config: Config,
|
||||
_baseLlmClient: BaseLlmClient,
|
||||
): Promise<RoutingDecision> {
|
||||
const defaultModel = resolveModel(
|
||||
config.getModel(),
|
||||
config.getPreviewFeatures(),
|
||||
);
|
||||
const defaultModel = resolveModel(config.getModel());
|
||||
return {
|
||||
model: defaultModel,
|
||||
metadata: {
|
||||
|
||||
@@ -25,7 +25,6 @@ const createMockConfig = (overrides: Partial<Config> = {}): Config =>
|
||||
({
|
||||
getModelAvailabilityService: vi.fn(),
|
||||
getModel: vi.fn().mockReturnValue(DEFAULT_GEMINI_MODEL),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
...overrides,
|
||||
}) as unknown as Config;
|
||||
|
||||
|
||||
@@ -23,10 +23,7 @@ export class FallbackStrategy implements RoutingStrategy {
|
||||
_baseLlmClient: BaseLlmClient,
|
||||
): Promise<RoutingDecision | null> {
|
||||
const requestedModel = context.requestedModel ?? config.getModel();
|
||||
const resolvedModel = resolveModel(
|
||||
requestedModel,
|
||||
config.getPreviewFeatures(),
|
||||
);
|
||||
const resolvedModel = resolveModel(requestedModel);
|
||||
const service = config.getModelAvailabilityService();
|
||||
const snapshot = service.snapshot(resolvedModel);
|
||||
|
||||
|
||||
@@ -47,7 +47,6 @@ describe('NumericalClassifierStrategy', () => {
|
||||
getResolvedConfig: vi.fn().mockReturnValue(mockResolvedConfig),
|
||||
},
|
||||
getModel: () => DEFAULT_GEMINI_MODEL_AUTO,
|
||||
getPreviewFeatures: () => false,
|
||||
getSessionId: vi.fn().mockReturnValue('control-group-id'), // Default to Control Group (Hash 71 >= 50)
|
||||
getNumericalRoutingEnabled: vi.fn().mockResolvedValue(true),
|
||||
getClassifierThreshold: vi.fn().mockResolvedValue(undefined),
|
||||
|
||||
@@ -179,7 +179,6 @@ export class NumericalClassifierStrategy implements RoutingStrategy {
|
||||
const selectedModel = resolveClassifierModel(
|
||||
config.getModel(),
|
||||
modelAlias,
|
||||
config.getPreviewFeatures(),
|
||||
);
|
||||
|
||||
const latencyMs = Date.now() - startTime;
|
||||
|
||||
@@ -19,7 +19,6 @@ describe('OverrideStrategy', () => {
|
||||
it('should return null when the override model is auto', async () => {
|
||||
const mockConfig = {
|
||||
getModel: () => DEFAULT_GEMINI_MODEL_AUTO,
|
||||
getPreviewFeatures: () => false,
|
||||
} as Config;
|
||||
|
||||
const decision = await strategy.route(mockContext, mockConfig, mockClient);
|
||||
@@ -30,7 +29,6 @@ describe('OverrideStrategy', () => {
|
||||
const overrideModel = 'gemini-2.5-pro-custom';
|
||||
const mockConfig = {
|
||||
getModel: () => overrideModel,
|
||||
getPreviewFeatures: () => false,
|
||||
} as Config;
|
||||
|
||||
const decision = await strategy.route(mockContext, mockConfig, mockClient);
|
||||
@@ -48,7 +46,6 @@ describe('OverrideStrategy', () => {
|
||||
const overrideModel = 'gemini-2.5-flash-experimental';
|
||||
const mockConfig = {
|
||||
getModel: () => overrideModel,
|
||||
getPreviewFeatures: () => false,
|
||||
} as Config;
|
||||
|
||||
const decision = await strategy.route(mockContext, mockConfig, mockClient);
|
||||
@@ -62,7 +59,6 @@ describe('OverrideStrategy', () => {
|
||||
const configModel = 'config-model';
|
||||
const mockConfig = {
|
||||
getModel: () => configModel,
|
||||
getPreviewFeatures: () => false,
|
||||
} as Config;
|
||||
const contextWithRequestedModel = {
|
||||
requestedModel,
|
||||
|
||||
@@ -33,7 +33,7 @@ export class OverrideStrategy implements RoutingStrategy {
|
||||
|
||||
// Return the overridden model name.
|
||||
return {
|
||||
model: resolveModel(overrideModel, config.getPreviewFeatures()),
|
||||
model: resolveModel(overrideModel),
|
||||
metadata: {
|
||||
source: this.name,
|
||||
latencyMs: 0,
|
||||
|
||||
@@ -390,7 +390,6 @@ export class TestRig {
|
||||
// Nightly releases sometimes becomes out of sync with local code and
|
||||
// triggers auto-update, which causes tests to fail.
|
||||
disableAutoUpdate: true,
|
||||
previewFeatures: false,
|
||||
},
|
||||
telemetry: {
|
||||
enabled: true,
|
||||
|
||||
Reference in New Issue
Block a user