mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-21 18:44:30 -07:00
Guard pro model usage (#22665)
This commit is contained in:
@@ -17,6 +17,7 @@ export const ExperimentFlags = {
|
||||
MASKING_PRUNABLE_THRESHOLD: 45758818,
|
||||
MASKING_PROTECT_LATEST_TURN: 45758819,
|
||||
GEMINI_3_1_PRO_LAUNCHED: 45760185,
|
||||
PRO_MODEL_NO_ACCESS: 45768879,
|
||||
} as const;
|
||||
|
||||
export type ExperimentFlagName =
|
||||
|
||||
@@ -65,6 +65,8 @@ import {
|
||||
DEFAULT_GEMINI_MODEL,
|
||||
PREVIEW_GEMINI_3_1_MODEL,
|
||||
DEFAULT_GEMINI_MODEL_AUTO,
|
||||
PREVIEW_GEMINI_MODEL_AUTO,
|
||||
PREVIEW_GEMINI_FLASH_MODEL,
|
||||
} from './models.js';
|
||||
import { Storage } from './storage.js';
|
||||
import type { AgentLoopContext } from './agent-loop-context.js';
|
||||
@@ -687,6 +689,46 @@ describe('Server Config (config.ts)', () => {
|
||||
loopContext.geminiClient.stripThoughtsFromHistory,
|
||||
).not.toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it('should switch to flash model if user has no Pro access and model is auto', async () => {
|
||||
vi.mocked(getExperiments).mockResolvedValue({
|
||||
experimentIds: [],
|
||||
flags: {
|
||||
[ExperimentFlags.PRO_MODEL_NO_ACCESS]: {
|
||||
boolValue: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const config = new Config({
|
||||
...baseParams,
|
||||
model: PREVIEW_GEMINI_MODEL_AUTO,
|
||||
});
|
||||
|
||||
await config.refreshAuth(AuthType.LOGIN_WITH_GOOGLE);
|
||||
|
||||
expect(config.getModel()).toBe(PREVIEW_GEMINI_FLASH_MODEL);
|
||||
});
|
||||
|
||||
it('should NOT switch to flash model if user has Pro access and model is auto', async () => {
|
||||
vi.mocked(getExperiments).mockResolvedValue({
|
||||
experimentIds: [],
|
||||
flags: {
|
||||
[ExperimentFlags.PRO_MODEL_NO_ACCESS]: {
|
||||
boolValue: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const config = new Config({
|
||||
...baseParams,
|
||||
model: PREVIEW_GEMINI_MODEL_AUTO,
|
||||
});
|
||||
|
||||
await config.refreshAuth(AuthType.LOGIN_WITH_GOOGLE);
|
||||
|
||||
expect(config.getModel()).toBe(PREVIEW_GEMINI_MODEL_AUTO);
|
||||
});
|
||||
});
|
||||
|
||||
it('Config constructor should store userMemory correctly', () => {
|
||||
|
||||
@@ -1386,6 +1386,10 @@ export class Config implements McpContext, AgentLoopContext {
|
||||
},
|
||||
);
|
||||
this.setRemoteAdminSettings(adminControls);
|
||||
|
||||
if ((await this.getProModelNoAccess()) && isAutoModel(this.model)) {
|
||||
this.setModel(PREVIEW_GEMINI_FLASH_MODEL);
|
||||
}
|
||||
}
|
||||
|
||||
async getExperimentsAsync(): Promise<Experiments | undefined> {
|
||||
@@ -2681,6 +2685,30 @@ export class Config implements McpContext, AgentLoopContext {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the user has access to Pro models.
|
||||
* This is determined by the PRO_MODEL_NO_ACCESS experiment flag.
|
||||
*/
|
||||
async getProModelNoAccess(): Promise<boolean> {
|
||||
await this.ensureExperimentsLoaded();
|
||||
return this.getProModelNoAccessSync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the user has access to Pro models synchronously.
|
||||
*
|
||||
* Note: This method should only be called after startup, once experiments have been loaded.
|
||||
*/
|
||||
getProModelNoAccessSync(): boolean {
|
||||
if (this.contentGeneratorConfig?.authType !== AuthType.LOGIN_WITH_GOOGLE) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
this.experiments?.flags[ExperimentFlags.PRO_MODEL_NO_ACCESS]?.boolValue ??
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether Gemini 3.1 has been launched.
|
||||
* This method is async and ensures that experiments are loaded before returning the result.
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
DEFAULT_GEMINI_MODEL_AUTO,
|
||||
isActiveModel,
|
||||
PREVIEW_GEMINI_3_1_MODEL,
|
||||
PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL,
|
||||
PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL,
|
||||
isPreviewModel,
|
||||
isProModel,
|
||||
@@ -245,6 +246,12 @@ describe('getDisplayString', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should return PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL for PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL', () => {
|
||||
expect(getDisplayString(PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL)).toBe(
|
||||
PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL,
|
||||
);
|
||||
});
|
||||
|
||||
it('should return the model name as is for other models', () => {
|
||||
expect(getDisplayString('custom-model')).toBe('custom-model');
|
||||
expect(getDisplayString(DEFAULT_GEMINI_FLASH_LITE_MODEL)).toBe(
|
||||
@@ -321,6 +328,12 @@ describe('resolveModel', () => {
|
||||
).toBe(DEFAULT_GEMINI_FLASH_MODEL);
|
||||
});
|
||||
|
||||
it('should return default flash lite model when access to preview is false and preview flash lite model is requested', () => {
|
||||
expect(
|
||||
resolveModel(PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, false, false, false),
|
||||
).toBe(DEFAULT_GEMINI_FLASH_LITE_MODEL);
|
||||
});
|
||||
|
||||
it('should return default model when access to preview is false and auto-gemini-3 is requested', () => {
|
||||
expect(resolveModel(PREVIEW_GEMINI_MODEL_AUTO, false, false, false)).toBe(
|
||||
DEFAULT_GEMINI_MODEL,
|
||||
@@ -439,6 +452,7 @@ describe('isActiveModel', () => {
|
||||
expect(isActiveModel(DEFAULT_GEMINI_MODEL)).toBe(true);
|
||||
expect(isActiveModel(PREVIEW_GEMINI_MODEL)).toBe(true);
|
||||
expect(isActiveModel(DEFAULT_GEMINI_FLASH_MODEL)).toBe(true);
|
||||
expect(isActiveModel(PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for unknown models and aliases', () => {
|
||||
@@ -452,6 +466,7 @@ describe('isActiveModel', () => {
|
||||
|
||||
it('should return true for other valid models when useGemini3_1 is true', () => {
|
||||
expect(isActiveModel(DEFAULT_GEMINI_MODEL, true)).toBe(true);
|
||||
expect(isActiveModel(PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, true)).toBe(true);
|
||||
});
|
||||
|
||||
it('should correctly filter Gemini 3.1 models based on useCustomToolModel when useGemini3_1 is true', () => {
|
||||
|
||||
@@ -36,6 +36,8 @@ export const PREVIEW_GEMINI_3_1_MODEL = 'gemini-3.1-pro-preview';
|
||||
export const PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL =
|
||||
'gemini-3.1-pro-preview-customtools';
|
||||
export const PREVIEW_GEMINI_FLASH_MODEL = 'gemini-3-flash-preview';
|
||||
export const PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL =
|
||||
'gemini-3.1-flash-lite-preview';
|
||||
export const DEFAULT_GEMINI_MODEL = 'gemini-2.5-pro';
|
||||
export const DEFAULT_GEMINI_FLASH_MODEL = 'gemini-2.5-flash';
|
||||
export const DEFAULT_GEMINI_FLASH_LITE_MODEL = 'gemini-2.5-flash-lite';
|
||||
@@ -45,6 +47,7 @@ export const VALID_GEMINI_MODELS = new Set([
|
||||
PREVIEW_GEMINI_3_1_MODEL,
|
||||
PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL,
|
||||
PREVIEW_GEMINI_FLASH_MODEL,
|
||||
PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL,
|
||||
DEFAULT_GEMINI_MODEL,
|
||||
DEFAULT_GEMINI_FLASH_MODEL,
|
||||
DEFAULT_GEMINI_FLASH_LITE_MODEL,
|
||||
@@ -216,7 +219,8 @@ export function isPreviewModel(
|
||||
model === PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL ||
|
||||
model === PREVIEW_GEMINI_FLASH_MODEL ||
|
||||
model === PREVIEW_GEMINI_MODEL_AUTO ||
|
||||
model === GEMINI_MODEL_ALIAS_AUTO
|
||||
model === GEMINI_MODEL_ALIAS_AUTO ||
|
||||
model === PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user