Remove useModelRouter experimental flag (#13593)

This commit is contained in:
Adib234
2025-11-21 09:54:17 -08:00
committed by GitHub
parent fe67ef63c1
commit 99c5bf2e97
21 changed files with 8 additions and 336 deletions
-122
View File
@@ -9,8 +9,6 @@ import * as os from 'node:os';
import * as path from 'node:path';
import {
DEFAULT_FILE_FILTERING_OPTIONS,
DEFAULT_GEMINI_MODEL,
DEFAULT_GEMINI_MODEL_AUTO,
OutputFormat,
SHELL_TOOL_NAME,
WRITE_FILE_TOOL_NAME,
@@ -1364,100 +1362,6 @@ describe('loadCliConfig model selection', () => {
});
});
describe('loadCliConfig model selection with model router', () => {
beforeEach(() => {
vi.spyOn(ExtensionManager.prototype, 'getExtensions').mockReturnValue([]);
});
afterEach(() => {
vi.resetAllMocks();
});
it('should use auto model when useModelRouter is true and no model is provided', async () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments({} as Settings);
const config = await loadCliConfig(
{
experimental: {
useModelRouter: true,
},
},
'test-session',
argv,
);
expect(config.getModel()).toBe(DEFAULT_GEMINI_MODEL_AUTO);
});
it('should use default model when useModelRouter is false and no model is provided', async () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments({} as Settings);
const config = await loadCliConfig(
{
experimental: {
useModelRouter: false,
},
},
'test-session',
argv,
);
expect(config.getModel()).toBe(DEFAULT_GEMINI_MODEL);
});
it('should prioritize argv over useModelRouter', async () => {
process.argv = ['node', 'script.js', '--model', 'gemini-from-argv'];
const argv = await parseArguments({} as Settings);
const config = await loadCliConfig(
{
experimental: {
useModelRouter: true,
},
},
'test-session',
argv,
);
expect(config.getModel()).toBe('gemini-from-argv');
});
it('should prioritize settings over useModelRouter', async () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments({} as Settings);
const config = await loadCliConfig(
{
experimental: {
useModelRouter: true,
},
model: {
name: 'gemini-from-settings',
},
},
'test-session',
argv,
);
expect(config.getModel()).toBe('gemini-from-settings');
});
it('should prioritize environment variable over useModelRouter', async () => {
process.argv = ['node', 'script.js'];
vi.stubEnv('GEMINI_MODEL', 'gemini-from-env');
const argv = await parseArguments({} as Settings);
const config = await loadCliConfig(
{
experimental: {
useModelRouter: true,
},
},
'test-session',
argv,
);
expect(config.getModel()).toBe('gemini-from-env');
});
});
describe('loadCliConfig folderTrust', () => {
beforeEach(() => {
vi.resetAllMocks();
@@ -1633,32 +1537,6 @@ describe('loadCliConfig useRipgrep', () => {
const config = await loadCliConfig(settings, 'test-session', argv);
expect(config.getUseRipgrep()).toBe(true);
});
describe('loadCliConfig useModelRouter', () => {
it('should be true by default when useModelRouter is not set in settings', async () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments({} as Settings);
const settings: Settings = {};
const config = await loadCliConfig(settings, 'test-session', argv);
expect(config.getUseModelRouter()).toBe(true);
});
it('should be true when useModelRouter is set to true in settings', async () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments({} as Settings);
const settings: Settings = { experimental: { useModelRouter: true } };
const config = await loadCliConfig(settings, 'test-session', argv);
expect(config.getUseModelRouter()).toBe(true);
});
it('should be false when useModelRouter is explicitly set to false in settings', async () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments({} as Settings);
const settings: Settings = { experimental: { useModelRouter: false } };
const config = await loadCliConfig(settings, 'test-session', argv);
expect(config.getUseModelRouter()).toBe(false);
});
});
});
describe('screenReader configuration', () => {
+1 -6
View File
@@ -15,7 +15,6 @@ import {
setGeminiMdFilename as setServerGeminiMdFilename,
getCurrentGeminiMdFilename,
ApprovalMode,
DEFAULT_GEMINI_MODEL,
DEFAULT_GEMINI_MODEL_AUTO,
DEFAULT_GEMINI_EMBEDDING_MODEL,
DEFAULT_FILE_FILTERING_OPTIONS,
@@ -580,10 +579,7 @@ export async function loadCliConfig(
extraExcludes.length > 0 ? extraExcludes : undefined,
);
const useModelRouter = settings.experimental?.useModelRouter ?? true;
const defaultModel = useModelRouter
? DEFAULT_GEMINI_MODEL_AUTO
: DEFAULT_GEMINI_MODEL;
const defaultModel = DEFAULT_GEMINI_MODEL_AUTO;
const resolvedModel: string =
argv.model ||
process.env['GEMINI_MODEL'] ||
@@ -674,7 +670,6 @@ export async function loadCliConfig(
output: {
format: (argv.outputFormat ?? settings.output?.format) as OutputFormat,
},
useModelRouter,
enableMessageBusIntegration,
codebaseInvestigatorSettings:
settings.experimental?.codebaseInvestigatorSettings,
@@ -345,21 +345,6 @@ describe('SettingsSchema', () => {
getSettingsSchema().general.properties.previewFeatures.description,
).toBe('Enable preview features (e.g., preview models).');
});
it('should have useModelRouter setting in schema', () => {
expect(
getSettingsSchema().experimental.properties.useModelRouter,
).toBeDefined();
expect(
getSettingsSchema().experimental.properties.useModelRouter.type,
).toBe('boolean');
expect(
getSettingsSchema().experimental.properties.useModelRouter.category,
).toBe('Experimental');
expect(
getSettingsSchema().experimental.properties.useModelRouter.default,
).toBe(true);
});
});
it('has JSON schema definitions for every referenced ref', () => {
-10
View File
@@ -1281,16 +1281,6 @@ const SETTINGS_SCHEMA = {
'Enables extension loading/unloading within the CLI session.',
showInDialog: false,
},
useModelRouter: {
type: 'boolean',
label: 'Use Model Router',
category: 'Experimental',
requiresRestart: true,
default: true,
description:
'Enable model routing to route requests to the best model based on complexity.',
showInDialog: true,
},
codebaseInvestigatorSettings: {
type: 'object',
label: 'Codebase Investigator Settings',
@@ -95,7 +95,6 @@ describe('BuiltinCommandLoader', () => {
vi.clearAllMocks();
mockConfig = {
getFolderTrust: vi.fn().mockReturnValue(true),
getUseModelRouter: () => false,
getEnableMessageBusIntegration: () => false,
getEnableExtensionReloading: () => false,
} as unknown as Config;
@@ -168,28 +167,6 @@ describe('BuiltinCommandLoader', () => {
expect(permissionsCmd).toBeUndefined();
});
it('should include modelCommand when getUseModelRouter is true', async () => {
const mockConfigWithModelRouter = {
...mockConfig,
getUseModelRouter: () => true,
} as unknown as Config;
const loader = new BuiltinCommandLoader(mockConfigWithModelRouter);
const commands = await loader.loadCommands(new AbortController().signal);
const modelCmd = commands.find((c) => c.name === 'model');
expect(modelCmd).toBeDefined();
});
it('should not include modelCommand when getUseModelRouter is false', async () => {
const mockConfigWithoutModelRouter = {
...mockConfig,
getUseModelRouter: () => false,
} as unknown as Config;
const loader = new BuiltinCommandLoader(mockConfigWithoutModelRouter);
const commands = await loader.loadCommands(new AbortController().signal);
const modelCmd = commands.find((c) => c.name === 'model');
expect(modelCmd).toBeUndefined();
});
it('should include policies command when message bus integration is enabled', async () => {
const mockConfigWithMessageBus = {
...mockConfig,
@@ -220,7 +197,6 @@ describe('BuiltinCommandLoader profile', () => {
vi.resetModules();
mockConfig = {
getFolderTrust: vi.fn().mockReturnValue(false),
getUseModelRouter: () => false,
getCheckpointingEnabled: () => false,
getEnableMessageBusIntegration: () => false,
getEnableExtensionReloading: () => false,
@@ -73,7 +73,7 @@ export class BuiltinCommandLoader implements ICommandLoader {
initCommand,
mcpCommand,
memoryCommand,
...(this.config?.getUseModelRouter() ? [modelCommand] : []),
modelCommand,
...(this.config?.getFolderTrust() ? [permissionsCommand] : []),
privacyCommand,
...(this.config?.getEnableMessageBusIntegration()
@@ -51,7 +51,6 @@ const renderComponent = (
getDebugMode: vi.fn(() => false),
getContentGeneratorConfig: vi.fn(() => ({ authType: 'mock' })),
getUseSmartEdit: vi.fn(() => false),
getUseModelRouter: vi.fn(() => false),
getProxy: vi.fn(() => undefined),
isInteractive: vi.fn(() => false),
@@ -222,7 +222,6 @@ describe('useGeminiStream', () => {
.fn()
.mockReturnValue(contentGeneratorConfig),
getUseSmartEdit: () => false,
getUseModelRouter: () => false,
isInteractive: () => false,
} as unknown as Config;
mockOnDebugMessage = vi.fn();
@@ -74,7 +74,6 @@ const mockConfig = {
authType: 'oauth-personal',
}),
getUseSmartEdit: () => false,
getUseModelRouter: () => false,
getGeminiClient: () => null, // No client needed for these tests
getShellExecutionConfig: () => ({ terminalWidth: 80, terminalHeight: 24 }),
getEnableMessageBusIntegration: () => false,
-93
View File
@@ -750,99 +750,6 @@ describe('Server Config (config.ts)', () => {
});
});
describe('Model Router with Auth', () => {
it('should disable model router by default for oauth-personal', async () => {
const config = new Config({
...baseParams,
useModelRouter: true,
});
await config.refreshAuth(AuthType.LOGIN_WITH_GOOGLE);
expect(config.getUseModelRouter()).toBe(true);
});
it('should enable model router by default for other auth types', async () => {
const config = new Config({
...baseParams,
useModelRouter: true,
});
await config.refreshAuth(AuthType.USE_GEMINI);
expect(config.getUseModelRouter()).toBe(true);
});
it('should disable model router for specified auth type', async () => {
const config = new Config({
...baseParams,
useModelRouter: true,
disableModelRouterForAuth: [AuthType.USE_GEMINI],
});
await config.refreshAuth(AuthType.USE_GEMINI);
expect(config.getUseModelRouter()).toBe(false);
});
it('should enable model router for other auth type', async () => {
const config = new Config({
...baseParams,
useModelRouter: true,
disableModelRouterForAuth: [],
});
await config.refreshAuth(AuthType.LOGIN_WITH_GOOGLE);
expect(config.getUseModelRouter()).toBe(true);
});
it('should keep model router disabled when useModelRouter is false', async () => {
const config = new Config({
...baseParams,
useModelRouter: false,
disableModelRouterForAuth: [AuthType.USE_GEMINI],
});
await config.refreshAuth(AuthType.LOGIN_WITH_GOOGLE);
expect(config.getUseModelRouter()).toBe(false);
});
it('should keep the user-chosen model after refreshAuth, even when model router is disabled for the auth type', async () => {
const config = new Config({
...baseParams,
useModelRouter: true,
disableModelRouterForAuth: [AuthType.USE_GEMINI],
});
const chosenModel = 'gemini-1.5-pro-latest';
config.setModel(chosenModel);
await config.refreshAuth(AuthType.USE_GEMINI);
expect(config.getUseModelRouter()).toBe(false);
expect(config.getModel()).toBe(chosenModel);
});
it('should keep the user-chosen model after refreshAuth, when model router is enabled for the auth type', async () => {
const config = new Config({
...baseParams,
useModelRouter: true,
disableModelRouterForAuth: [AuthType.USE_GEMINI],
});
const chosenModel = 'gemini-1.5-pro-latest';
config.setModel(chosenModel);
await config.refreshAuth(AuthType.LOGIN_WITH_GOOGLE);
expect(config.getUseModelRouter()).toBe(true);
expect(config.getModel()).toBe(chosenModel);
});
it('should NOT switch to auto model if cli provides specific model, even if router is enabled', async () => {
const config = new Config({
...baseParams,
useModelRouter: true,
model: 'gemini-flash-latest',
});
await config.refreshAuth(AuthType.LOGIN_WITH_GOOGLE);
expect(config.getUseModelRouter()).toBe(true);
expect(config.getModel()).toBe('gemini-flash-latest');
});
});
describe('ContinueOnFailedApiCall Configuration', () => {
it('should default continueOnFailedApiCall to false when not provided', () => {
const config = new Config(baseParams);
-20
View File
@@ -48,7 +48,6 @@ import {
DEFAULT_GEMINI_EMBEDDING_MODEL,
DEFAULT_GEMINI_FLASH_MODEL,
DEFAULT_GEMINI_MODEL,
DEFAULT_GEMINI_MODEL_AUTO,
DEFAULT_THINKING_MODE,
} from './models.js';
import { shouldAttemptBrowserLaunch } from '../utils/browser.js';
@@ -288,7 +287,6 @@ export interface ConfigParameters {
useWriteTodos?: boolean;
policyEngineConfig?: PolicyEngineConfig;
output?: OutputSettings;
useModelRouter?: boolean;
enableMessageBusIntegration?: boolean;
disableModelRouterForAuth?: AuthType[];
codebaseInvestigatorSettings?: CodebaseInvestigatorSettings;
@@ -402,9 +400,6 @@ export class Config {
private readonly messageBus: MessageBus;
private readonly policyEngine: PolicyEngine;
private readonly outputSettings: OutputSettings;
private useModelRouter: boolean;
private readonly initialUseModelRouter: boolean;
private readonly disableModelRouterForAuth?: AuthType[];
private readonly enableMessageBusIntegration: boolean;
private readonly codebaseInvestigatorSettings: CodebaseInvestigatorSettings;
private readonly continueOnFailedApiCall: boolean;
@@ -519,9 +514,6 @@ export class Config {
this.enableToolOutputTruncation = params.enableToolOutputTruncation ?? true;
this.useSmartEdit = params.useSmartEdit ?? true;
this.useWriteTodos = params.useWriteTodos ?? true;
this.initialUseModelRouter = params.useModelRouter ?? false;
this.useModelRouter = this.initialUseModelRouter;
this.disableModelRouterForAuth = params.disableModelRouterForAuth ?? [];
this.enableHooks = params.enableHooks ?? false;
// Enable MessageBus integration if:
@@ -643,14 +635,6 @@ export class Config {
}
async refreshAuth(authMethod: AuthType) {
this.useModelRouter = this.initialUseModelRouter;
if (this.disableModelRouterForAuth?.includes(authMethod)) {
this.useModelRouter = false;
if (this.model === DEFAULT_GEMINI_MODEL_AUTO) {
this.model = DEFAULT_GEMINI_MODEL;
}
}
// Vertex and Genai have incompatible encryption and sending history with
// thoughtSignature from Genai to Vertex will fail, we need to strip them
if (
@@ -1341,10 +1325,6 @@ export class Config {
: OutputFormat.TEXT;
}
getUseModelRouter(): boolean {
return this.useModelRouter;
}
async getGitService(): Promise<GitService> {
if (!this.gitService) {
this.gitService = new GitService(this.targetDir, this.storage);
-1
View File
@@ -216,7 +216,6 @@ describe('Gemini Client (client.ts)', () => {
getChatCompression: vi.fn().mockReturnValue(undefined),
getSkipNextSpeakerCheck: vi.fn().mockReturnValue(false),
getUseSmartEdit: vi.fn().mockReturnValue(false),
getUseModelRouter: vi.fn().mockReturnValue(false),
getShowModelInfoInChat: vi.fn().mockReturnValue(false),
getContinueOnFailedApiCall: vi.fn(),
getProjectRoot: vi.fn().mockReturnValue('/test/project/root'),
@@ -248,7 +248,6 @@ function createMockConfig(overrides: Partial<Config> = {}): Config {
getTruncateToolOutputLines: () => DEFAULT_TRUNCATE_TOOL_OUTPUT_LINES,
getToolRegistry: () => defaultToolRegistry,
getUseSmartEdit: () => false,
getUseModelRouter: () => false,
getGeminiClient: () => null,
getEnableMessageBusIntegration: () => false,
getMessageBus: () => null,
@@ -60,7 +60,6 @@ describe('executeToolCall', () => {
DEFAULT_TRUNCATE_TOOL_OUTPUT_THRESHOLD,
getTruncateToolOutputLines: () => DEFAULT_TRUNCATE_TOOL_OUTPUT_LINES,
getUseSmartEdit: () => false,
getUseModelRouter: () => false,
getGeminiClient: () => null, // No client needed for these tests
getEnableMessageBusIntegration: () => false,
getMessageBus: () => null,
@@ -312,7 +312,7 @@ describe('ClearcutLogger', () => {
it('logs all user settings', () => {
const { logger } = setup({
config: { useSmartEdit: true, useModelRouter: true },
config: { useSmartEdit: true },
});
vi.stubEnv('TERM_PROGRAM', 'vscode');
@@ -1544,7 +1544,6 @@ describe('loggers', () => {
getUsageStatisticsEnabled: () => true,
getContentGeneratorConfig: () => null,
getUseSmartEdit: () => null,
getUseModelRouter: () => null,
isInteractive: () => false,
} as unknown as Config;
@@ -1595,7 +1594,6 @@ describe('loggers', () => {
getUsageStatisticsEnabled: () => true,
getContentGeneratorConfig: () => null,
getUseSmartEdit: () => null,
getUseModelRouter: () => null,
isInteractive: () => false,
} as unknown as Config;
@@ -1648,7 +1646,6 @@ describe('loggers', () => {
getUsageStatisticsEnabled: () => true,
getContentGeneratorConfig: () => null,
getUseSmartEdit: () => null,
getUseModelRouter: () => null,
isInteractive: () => false,
} as unknown as Config;
@@ -90,7 +90,6 @@ describe('SmartEditTool', () => {
getSessionId: vi.fn(() => 'mock-session-id'),
getContentGeneratorConfig: vi.fn(() => ({ authType: 'mock' })),
getUseSmartEdit: vi.fn(() => false),
getUseModelRouter: vi.fn(() => false),
getProxy: vi.fn(() => undefined),
getGeminiClient: vi.fn().mockReturnValue(geminiClient),
getBaseLlmClient: vi.fn().mockReturnValue(baseLlmClient),