mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-20 18:14:29 -07:00
Send the model and CLI version with the user agent (#14865)
This commit is contained in:
committed by
GitHub
parent
d90356e8a3
commit
d2a6b30398
@@ -6,6 +6,7 @@
|
||||
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
import { ReleaseChannel, getReleaseChannel } from '../../utils/channel.js';
|
||||
import { getVersion } from '../../utils/version.js';
|
||||
|
||||
// Mock dependencies before importing the module under test
|
||||
vi.mock('../../utils/channel.js', async () => {
|
||||
@@ -16,6 +17,10 @@ vi.mock('../../utils/channel.js', async () => {
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock('../../utils/version.js', async () => ({
|
||||
getVersion: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('client_metadata', () => {
|
||||
const originalPlatform = process.platform;
|
||||
const originalArch = process.arch;
|
||||
@@ -29,6 +34,7 @@ describe('client_metadata', () => {
|
||||
await import('./client_metadata.js');
|
||||
// Provide a default mock implementation for each test
|
||||
vi.mocked(getReleaseChannel).mockResolvedValue(ReleaseChannel.STABLE);
|
||||
vi.mocked(getVersion).mockResolvedValue('0.0.0');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -64,24 +70,14 @@ describe('client_metadata', () => {
|
||||
});
|
||||
|
||||
describe('getClientMetadata', () => {
|
||||
it('should use CLI_VERSION for ideVersion if set', async () => {
|
||||
process.env['CLI_VERSION'] = '1.2.3';
|
||||
Object.defineProperty(process, 'version', { value: 'v18.0.0' });
|
||||
it('should use version from getCliVersion for ideVersion', async () => {
|
||||
vi.mocked(getVersion).mockResolvedValue('1.2.3');
|
||||
const { getClientMetadata } = await import('./client_metadata.js');
|
||||
|
||||
const metadata = await getClientMetadata();
|
||||
expect(metadata.ideVersion).toBe('1.2.3');
|
||||
});
|
||||
|
||||
it('should use process.version for ideVersion as a fallback', async () => {
|
||||
delete process.env['CLI_VERSION'];
|
||||
Object.defineProperty(process, 'version', { value: 'v20.0.0' });
|
||||
const { getClientMetadata } = await import('./client_metadata.js');
|
||||
|
||||
const metadata = await getClientMetadata();
|
||||
expect(metadata.ideVersion).toBe('v20.0.0');
|
||||
});
|
||||
|
||||
it('should call getReleaseChannel to get the update channel', async () => {
|
||||
vi.mocked(getReleaseChannel).mockResolvedValue(ReleaseChannel.NIGHTLY);
|
||||
const { getClientMetadata } = await import('./client_metadata.js');
|
||||
|
||||
@@ -8,6 +8,7 @@ import { getReleaseChannel } from '../../utils/channel.js';
|
||||
import type { ClientMetadata, ClientMetadataPlatform } from '../types.js';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import path from 'node:path';
|
||||
import { getVersion } from '../../utils/version.js';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
@@ -47,7 +48,7 @@ export async function getClientMetadata(): Promise<ClientMetadata> {
|
||||
clientMetadataPromise = (async () => ({
|
||||
ideName: 'IDE_UNSPECIFIED',
|
||||
pluginType: 'GEMINI',
|
||||
ideVersion: process.env['CLI_VERSION'] || process.version,
|
||||
ideVersion: await getVersion(),
|
||||
platform: getPlatform(),
|
||||
updateChannel: await getReleaseChannel(__dirname),
|
||||
}))();
|
||||
|
||||
@@ -27,7 +27,13 @@ vi.mock('./apiKeyCredentialStorage.js', () => ({
|
||||
|
||||
vi.mock('./fakeContentGenerator.js');
|
||||
|
||||
const mockConfig = {} as unknown as Config;
|
||||
const mockConfig = {
|
||||
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getProxy: vi.fn().mockReturnValue(undefined),
|
||||
getUsageStatisticsEnabled: vi.fn().mockReturnValue(true),
|
||||
isInFallbackMode: vi.fn().mockReturnValue(false),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
|
||||
describe('createContentGenerator', () => {
|
||||
beforeEach(() => {
|
||||
@@ -111,9 +117,16 @@ describe('createContentGenerator', () => {
|
||||
|
||||
it('should create a GoogleGenAI content generator', async () => {
|
||||
const mockConfig = {
|
||||
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getProxy: vi.fn().mockReturnValue(undefined),
|
||||
getUsageStatisticsEnabled: () => true,
|
||||
isInFallbackMode: vi.fn().mockReturnValue(false),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
|
||||
// Set a fixed version for testing
|
||||
vi.stubEnv('CLI_VERSION', '1.2.3');
|
||||
|
||||
const mockGenerator = {
|
||||
models: {},
|
||||
} as unknown as GoogleGenAI;
|
||||
@@ -130,7 +143,7 @@ describe('createContentGenerator', () => {
|
||||
vertexai: undefined,
|
||||
httpOptions: {
|
||||
headers: {
|
||||
'User-Agent': expect.any(String),
|
||||
'User-Agent': expect.stringContaining('GeminiCLI/1.2.3/gemini-pro'),
|
||||
'x-gemini-api-privileged-user-id': expect.any(String),
|
||||
},
|
||||
},
|
||||
@@ -176,7 +189,11 @@ describe('createContentGenerator', () => {
|
||||
|
||||
it('should include custom headers from GEMINI_CLI_CUSTOM_HEADERS for GoogleGenAI requests without inferring auth mechanism', async () => {
|
||||
const mockConfig = {
|
||||
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getProxy: vi.fn().mockReturnValue(undefined),
|
||||
getUsageStatisticsEnabled: () => false,
|
||||
isInFallbackMode: vi.fn().mockReturnValue(false),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
|
||||
const mockGenerator = {
|
||||
@@ -220,7 +237,11 @@ describe('createContentGenerator', () => {
|
||||
|
||||
it('should pass api key as Authorization Header when GEMINI_API_KEY_AUTH_MECHANISM is set to bearer', async () => {
|
||||
const mockConfig = {
|
||||
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getProxy: vi.fn().mockReturnValue(undefined),
|
||||
getUsageStatisticsEnabled: () => false,
|
||||
isInFallbackMode: vi.fn().mockReturnValue(false),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
|
||||
const mockGenerator = {
|
||||
@@ -251,7 +272,11 @@ describe('createContentGenerator', () => {
|
||||
|
||||
it('should not pass api key as Authorization Header when GEMINI_API_KEY_AUTH_MECHANISM is not set (default behavior)', async () => {
|
||||
const mockConfig = {
|
||||
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getProxy: vi.fn().mockReturnValue(undefined),
|
||||
getUsageStatisticsEnabled: () => false,
|
||||
isInFallbackMode: vi.fn().mockReturnValue(false),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
|
||||
const mockGenerator = {
|
||||
@@ -291,7 +316,10 @@ describe('createContentGenerator', () => {
|
||||
|
||||
it('should create a GoogleGenAI content generator with client install id logging disabled', async () => {
|
||||
const mockConfig = {
|
||||
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
getUsageStatisticsEnabled: () => false,
|
||||
isInFallbackMode: vi.fn().mockReturnValue(false),
|
||||
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
const mockGenerator = {
|
||||
models: {},
|
||||
|
||||
@@ -23,6 +23,7 @@ import { InstallationManager } from '../utils/installationManager.js';
|
||||
import { FakeContentGenerator } from './fakeContentGenerator.js';
|
||||
import { parseCustomHeaders } from '../utils/customHeaderUtils.js';
|
||||
import { RecordingContentGenerator } from './recordingContentGenerator.js';
|
||||
import { getVersion, getEffectiveModel } from '../../index.js';
|
||||
|
||||
/**
|
||||
* Interface abstracting the core functionalities for generating content and counting tokens.
|
||||
@@ -115,10 +116,15 @@ export async function createContentGenerator(
|
||||
if (gcConfig.fakeResponses) {
|
||||
return FakeContentGenerator.fromFile(gcConfig.fakeResponses);
|
||||
}
|
||||
const version = process.env['CLI_VERSION'] || process.version;
|
||||
const version = await getVersion();
|
||||
const model = getEffectiveModel(
|
||||
gcConfig.isInFallbackMode(),
|
||||
gcConfig.getModel(),
|
||||
gcConfig.getPreviewFeatures(),
|
||||
);
|
||||
const customHeadersEnv =
|
||||
process.env['GEMINI_CLI_CUSTOM_HEADERS'] || undefined;
|
||||
const userAgent = `GeminiCLI/${version} (${process.platform}; ${process.arch})`;
|
||||
const userAgent = `GeminiCLI/${version}/${model} (${process.platform}; ${process.arch})`;
|
||||
const customHeadersMap = parseCustomHeaders(customHeadersEnv);
|
||||
const apiKeyAuthMechanism =
|
||||
process.env['GEMINI_API_KEY_AUTH_MECHANISM'] || 'x-goog-api-key';
|
||||
|
||||
@@ -78,6 +78,7 @@ export * from './utils/debugLogger.js';
|
||||
export * from './utils/events.js';
|
||||
export * from './utils/extensionLoader.js';
|
||||
export * from './utils/package.js';
|
||||
export * from './utils/version.js';
|
||||
export * from './utils/checkpointUtils.js';
|
||||
|
||||
// Export services
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
import { getVersion } from './version.js';
|
||||
import { getPackageJson } from './package.js';
|
||||
|
||||
vi.mock('./package.js', () => ({
|
||||
getPackageJson: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('version', () => {
|
||||
const originalEnv = process.env;
|
||||
|
||||
beforeEach(() => {
|
||||
vi.resetModules();
|
||||
process.env = { ...originalEnv };
|
||||
vi.mocked(getPackageJson).mockResolvedValue({ version: '1.0.0' });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
process.env = originalEnv;
|
||||
});
|
||||
|
||||
it('should return CLI_VERSION from env if set', async () => {
|
||||
process.env['CLI_VERSION'] = '2.0.0';
|
||||
const version = await getVersion();
|
||||
expect(version).toBe('2.0.0');
|
||||
});
|
||||
|
||||
it('should return version from package.json if CLI_VERSION is not set', async () => {
|
||||
delete process.env['CLI_VERSION'];
|
||||
const version = await getVersion();
|
||||
expect(version).toBe('1.0.0');
|
||||
});
|
||||
|
||||
it('should return "unknown" if package.json is not found and CLI_VERSION is not set', async () => {
|
||||
delete process.env['CLI_VERSION'];
|
||||
vi.mocked(getPackageJson).mockResolvedValue(undefined);
|
||||
const version = await getVersion();
|
||||
expect(version).toBe('unknown');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { getPackageJson } from './package.js';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import path from 'node:path';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
export async function getVersion(): Promise<string> {
|
||||
const pkgJson = await getPackageJson(__dirname);
|
||||
return process.env['CLI_VERSION'] || pkgJson?.version || 'unknown';
|
||||
}
|
||||
Reference in New Issue
Block a user