mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
Run model availability check in the background to speed up startup (#4256)
This commit is contained in:
@@ -57,6 +57,7 @@ import {
|
|||||||
EditorType,
|
EditorType,
|
||||||
FlashFallbackEvent,
|
FlashFallbackEvent,
|
||||||
logFlashFallback,
|
logFlashFallback,
|
||||||
|
AuthType,
|
||||||
} from '@google/gemini-cli-core';
|
} from '@google/gemini-cli-core';
|
||||||
import { validateAuthMethod } from '../config/auth.js';
|
import { validateAuthMethod } from '../config/auth.js';
|
||||||
import { useLogger } from './hooks/useLogger.js';
|
import { useLogger } from './hooks/useLogger.js';
|
||||||
@@ -294,6 +295,10 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
|||||||
): Promise<boolean> => {
|
): Promise<boolean> => {
|
||||||
let message: string;
|
let message: string;
|
||||||
|
|
||||||
|
if (
|
||||||
|
config.getContentGeneratorConfig().authType ===
|
||||||
|
AuthType.LOGIN_WITH_GOOGLE
|
||||||
|
) {
|
||||||
// Use actual user tier if available, otherwise default to FREE tier behavior (safe default)
|
// Use actual user tier if available, otherwise default to FREE tier behavior (safe default)
|
||||||
const isPaidTier =
|
const isPaidTier =
|
||||||
userTier === UserTierId.LEGACY || userTier === UserTierId.STANDARD;
|
userTier === UserTierId.LEGACY || userTier === UserTierId.STANDARD;
|
||||||
@@ -352,6 +357,8 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
|||||||
setModelSwitchedFromQuotaError(true);
|
setModelSwitchedFromQuotaError(true);
|
||||||
// Set global quota error flag to prevent Flash model calls
|
// Set global quota error flag to prevent Flash model calls
|
||||||
config.setQuotaErrorOccurred(true);
|
config.setQuotaErrorOccurred(true);
|
||||||
|
}
|
||||||
|
|
||||||
// Switch model for future use but return false to stop current retry
|
// Switch model for future use but return false to stop current retry
|
||||||
config.setModel(fallbackModel);
|
config.setModel(fallbackModel);
|
||||||
logFlashFallback(
|
logFlashFallback(
|
||||||
|
|||||||
@@ -151,14 +151,12 @@ describe('Server Config (config.ts)', () => {
|
|||||||
apiKey: 'test-key',
|
apiKey: 'test-key',
|
||||||
};
|
};
|
||||||
|
|
||||||
(createContentGeneratorConfig as Mock).mockResolvedValue(
|
(createContentGeneratorConfig as Mock).mockReturnValue(mockContentConfig);
|
||||||
mockContentConfig,
|
|
||||||
);
|
|
||||||
|
|
||||||
await config.refreshAuth(authType);
|
await config.refreshAuth(authType);
|
||||||
|
|
||||||
expect(createContentGeneratorConfig).toHaveBeenCalledWith(
|
expect(createContentGeneratorConfig).toHaveBeenCalledWith(
|
||||||
MODEL, // Should be called with the original model 'gemini-pro'
|
config,
|
||||||
authType,
|
authType,
|
||||||
);
|
);
|
||||||
// Verify that contentGeneratorConfig is updated with the new model
|
// Verify that contentGeneratorConfig is updated with the new model
|
||||||
|
|||||||
@@ -274,8 +274,8 @@ export class Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async refreshAuth(authMethod: AuthType) {
|
async refreshAuth(authMethod: AuthType) {
|
||||||
this.contentGeneratorConfig = await createContentGeneratorConfig(
|
this.contentGeneratorConfig = createContentGeneratorConfig(
|
||||||
this.model,
|
this,
|
||||||
authMethod,
|
authMethod,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -64,12 +64,18 @@ describe('createContentGenerator', () => {
|
|||||||
|
|
||||||
describe('createContentGeneratorConfig', () => {
|
describe('createContentGeneratorConfig', () => {
|
||||||
const originalEnv = process.env;
|
const originalEnv = process.env;
|
||||||
|
const mockConfig = {
|
||||||
|
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||||
|
setModel: vi.fn(),
|
||||||
|
flashFallbackHandler: vi.fn(),
|
||||||
|
} as unknown as Config;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
// Reset modules to re-evaluate imports and environment variables
|
// Reset modules to re-evaluate imports and environment variables
|
||||||
vi.resetModules();
|
vi.resetModules();
|
||||||
// Restore process.env before each test
|
// Restore process.env before each test
|
||||||
process.env = { ...originalEnv };
|
process.env = { ...originalEnv };
|
||||||
|
vi.clearAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
@@ -80,7 +86,7 @@ describe('createContentGeneratorConfig', () => {
|
|||||||
it('should configure for Gemini using GEMINI_API_KEY when set', async () => {
|
it('should configure for Gemini using GEMINI_API_KEY when set', async () => {
|
||||||
process.env.GEMINI_API_KEY = 'env-gemini-key';
|
process.env.GEMINI_API_KEY = 'env-gemini-key';
|
||||||
const config = await createContentGeneratorConfig(
|
const config = await createContentGeneratorConfig(
|
||||||
undefined,
|
mockConfig,
|
||||||
AuthType.USE_GEMINI,
|
AuthType.USE_GEMINI,
|
||||||
);
|
);
|
||||||
expect(config.apiKey).toBe('env-gemini-key');
|
expect(config.apiKey).toBe('env-gemini-key');
|
||||||
@@ -90,7 +96,7 @@ describe('createContentGeneratorConfig', () => {
|
|||||||
it('should not configure for Gemini if GEMINI_API_KEY is empty', async () => {
|
it('should not configure for Gemini if GEMINI_API_KEY is empty', async () => {
|
||||||
process.env.GEMINI_API_KEY = '';
|
process.env.GEMINI_API_KEY = '';
|
||||||
const config = await createContentGeneratorConfig(
|
const config = await createContentGeneratorConfig(
|
||||||
undefined,
|
mockConfig,
|
||||||
AuthType.USE_GEMINI,
|
AuthType.USE_GEMINI,
|
||||||
);
|
);
|
||||||
expect(config.apiKey).toBeUndefined();
|
expect(config.apiKey).toBeUndefined();
|
||||||
@@ -100,7 +106,7 @@ describe('createContentGeneratorConfig', () => {
|
|||||||
it('should configure for Vertex AI using GOOGLE_API_KEY when set', async () => {
|
it('should configure for Vertex AI using GOOGLE_API_KEY when set', async () => {
|
||||||
process.env.GOOGLE_API_KEY = 'env-google-key';
|
process.env.GOOGLE_API_KEY = 'env-google-key';
|
||||||
const config = await createContentGeneratorConfig(
|
const config = await createContentGeneratorConfig(
|
||||||
undefined,
|
mockConfig,
|
||||||
AuthType.USE_VERTEX_AI,
|
AuthType.USE_VERTEX_AI,
|
||||||
);
|
);
|
||||||
expect(config.apiKey).toBe('env-google-key');
|
expect(config.apiKey).toBe('env-google-key');
|
||||||
@@ -111,7 +117,7 @@ describe('createContentGeneratorConfig', () => {
|
|||||||
process.env.GOOGLE_CLOUD_PROJECT = 'env-gcp-project';
|
process.env.GOOGLE_CLOUD_PROJECT = 'env-gcp-project';
|
||||||
process.env.GOOGLE_CLOUD_LOCATION = 'env-gcp-location';
|
process.env.GOOGLE_CLOUD_LOCATION = 'env-gcp-location';
|
||||||
const config = await createContentGeneratorConfig(
|
const config = await createContentGeneratorConfig(
|
||||||
undefined,
|
mockConfig,
|
||||||
AuthType.USE_VERTEX_AI,
|
AuthType.USE_VERTEX_AI,
|
||||||
);
|
);
|
||||||
expect(config.vertexai).toBe(true);
|
expect(config.vertexai).toBe(true);
|
||||||
@@ -123,7 +129,7 @@ describe('createContentGeneratorConfig', () => {
|
|||||||
process.env.GOOGLE_CLOUD_PROJECT = '';
|
process.env.GOOGLE_CLOUD_PROJECT = '';
|
||||||
process.env.GOOGLE_CLOUD_LOCATION = '';
|
process.env.GOOGLE_CLOUD_LOCATION = '';
|
||||||
const config = await createContentGeneratorConfig(
|
const config = await createContentGeneratorConfig(
|
||||||
undefined,
|
mockConfig,
|
||||||
AuthType.USE_VERTEX_AI,
|
AuthType.USE_VERTEX_AI,
|
||||||
);
|
);
|
||||||
expect(config.apiKey).toBeUndefined();
|
expect(config.apiKey).toBeUndefined();
|
||||||
|
|||||||
@@ -52,17 +52,17 @@ export type ContentGeneratorConfig = {
|
|||||||
authType?: AuthType | undefined;
|
authType?: AuthType | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function createContentGeneratorConfig(
|
export function createContentGeneratorConfig(
|
||||||
model: string | undefined,
|
config: Config,
|
||||||
authType: AuthType | undefined,
|
authType: AuthType | undefined,
|
||||||
): Promise<ContentGeneratorConfig> {
|
): ContentGeneratorConfig {
|
||||||
const geminiApiKey = process.env.GEMINI_API_KEY || undefined;
|
const geminiApiKey = process.env.GEMINI_API_KEY || undefined;
|
||||||
const googleApiKey = process.env.GOOGLE_API_KEY || undefined;
|
const googleApiKey = process.env.GOOGLE_API_KEY || undefined;
|
||||||
const googleCloudProject = process.env.GOOGLE_CLOUD_PROJECT || undefined;
|
const googleCloudProject = process.env.GOOGLE_CLOUD_PROJECT || undefined;
|
||||||
const googleCloudLocation = process.env.GOOGLE_CLOUD_LOCATION || undefined;
|
const googleCloudLocation = process.env.GOOGLE_CLOUD_LOCATION || undefined;
|
||||||
|
|
||||||
// Use runtime model from config if available, otherwise fallback to parameter or default
|
// Use runtime model from config if available, otherwise fallback to parameter or default
|
||||||
const effectiveModel = model || DEFAULT_GEMINI_MODEL;
|
const effectiveModel = config.getModel() || DEFAULT_GEMINI_MODEL;
|
||||||
|
|
||||||
const contentGeneratorConfig: ContentGeneratorConfig = {
|
const contentGeneratorConfig: ContentGeneratorConfig = {
|
||||||
model: effectiveModel,
|
model: effectiveModel,
|
||||||
@@ -80,10 +80,14 @@ export async function createContentGeneratorConfig(
|
|||||||
if (authType === AuthType.USE_GEMINI && geminiApiKey) {
|
if (authType === AuthType.USE_GEMINI && geminiApiKey) {
|
||||||
contentGeneratorConfig.apiKey = geminiApiKey;
|
contentGeneratorConfig.apiKey = geminiApiKey;
|
||||||
contentGeneratorConfig.vertexai = false;
|
contentGeneratorConfig.vertexai = false;
|
||||||
contentGeneratorConfig.model = await getEffectiveModel(
|
getEffectiveModel(
|
||||||
contentGeneratorConfig.apiKey,
|
contentGeneratorConfig.apiKey,
|
||||||
contentGeneratorConfig.model,
|
contentGeneratorConfig.model,
|
||||||
);
|
).then((newModel) => {
|
||||||
|
if (newModel !== contentGeneratorConfig.model) {
|
||||||
|
config.flashFallbackHandler?.(contentGeneratorConfig.model, newModel);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return contentGeneratorConfig;
|
return contentGeneratorConfig;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user