Compare commits

...

9 Commits

38 changed files with 198 additions and 185 deletions
+2 -2
View File
@@ -55,7 +55,7 @@ describe.skip('ACP Environment and Auth', () => {
const bundlePath = join(import.meta.dirname, '..', 'bundle/gemini.js');
child = spawn('node', [bundlePath, '--experimental-acp'], {
child = spawn('node', [bundlePath, '--acp'], {
cwd: rig.homeDir!,
stdio: ['pipe', 'pipe', 'inherit'],
env: {
@@ -120,7 +120,7 @@ describe.skip('ACP Environment and Auth', () => {
const bundlePath = join(import.meta.dirname, '..', 'bundle/gemini.js');
child = spawn('node', [bundlePath, '--experimental-acp'], {
child = spawn('node', [bundlePath, '--acp'], {
cwd: rig.homeDir!,
stdio: ['pipe', 'pipe', 'inherit'],
env: {
+1 -1
View File
@@ -58,7 +58,7 @@ describe('ACP telemetry', () => {
'node',
[
bundlePath,
'--experimental-acp',
'--acp',
'--fake-responses',
join(rig.testDir!, 'fake-responses.json'),
],
+9 -9
View File
@@ -1,12 +1,12 @@
{
"name": "@google/gemini-cli",
"version": "0.33.0-nightly.20260228.1ca5c05d0",
"version": "0.33.0-preview.4",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@google/gemini-cli",
"version": "0.33.0-nightly.20260228.1ca5c05d0",
"version": "0.33.0-preview.4",
"workspaces": [
"packages/*"
],
@@ -17303,7 +17303,7 @@
},
"packages/a2a-server": {
"name": "@google/gemini-cli-a2a-server",
"version": "0.33.0-nightly.20260228.1ca5c05d0",
"version": "0.33.0-preview.4",
"dependencies": {
"@a2a-js/sdk": "^0.3.8",
"@google-cloud/storage": "^7.16.0",
@@ -17361,7 +17361,7 @@
},
"packages/cli": {
"name": "@google/gemini-cli",
"version": "0.33.0-nightly.20260228.1ca5c05d0",
"version": "0.33.0-preview.4",
"license": "Apache-2.0",
"dependencies": {
"@agentclientprotocol/sdk": "^0.12.0",
@@ -17444,7 +17444,7 @@
},
"packages/core": {
"name": "@google/gemini-cli-core",
"version": "0.33.0-nightly.20260228.1ca5c05d0",
"version": "0.33.0-preview.4",
"license": "Apache-2.0",
"dependencies": {
"@a2a-js/sdk": "^0.3.8",
@@ -17709,7 +17709,7 @@
},
"packages/devtools": {
"name": "@google/gemini-cli-devtools",
"version": "0.33.0-nightly.20260228.1ca5c05d0",
"version": "0.33.0-preview.4",
"license": "Apache-2.0",
"dependencies": {
"ws": "^8.16.0"
@@ -17724,7 +17724,7 @@
},
"packages/sdk": {
"name": "@google/gemini-cli-sdk",
"version": "0.33.0-nightly.20260228.1ca5c05d0",
"version": "0.33.0-preview.4",
"license": "Apache-2.0",
"dependencies": {
"@google/gemini-cli-core": "file:../core",
@@ -17741,7 +17741,7 @@
},
"packages/test-utils": {
"name": "@google/gemini-cli-test-utils",
"version": "0.33.0-nightly.20260228.1ca5c05d0",
"version": "0.33.0-preview.4",
"license": "Apache-2.0",
"dependencies": {
"@google/gemini-cli-core": "file:../core",
@@ -17758,7 +17758,7 @@
},
"packages/vscode-ide-companion": {
"name": "gemini-cli-vscode-ide-companion",
"version": "0.33.0-nightly.20260228.1ca5c05d0",
"version": "0.33.0-preview.4",
"license": "LICENSE",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.23.0",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@google/gemini-cli",
"version": "0.33.0-nightly.20260228.1ca5c05d0",
"version": "0.33.0-preview.4",
"engines": {
"node": ">=20.0.0"
},
@@ -14,7 +14,7 @@
"url": "git+https://github.com/google-gemini/gemini-cli.git"
},
"config": {
"sandboxImageUri": "us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.33.0-nightly.20260228.1ca5c05d0"
"sandboxImageUri": "us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.33.0-preview.4"
},
"scripts": {
"start": "cross-env NODE_ENV=development node scripts/start.js",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@google/gemini-cli-a2a-server",
"version": "0.33.0-nightly.20260228.1ca5c05d0",
"version": "0.33.0-preview.4",
"description": "Gemini CLI A2A Server",
"repository": {
"type": "git",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@google/gemini-cli",
"version": "0.33.0-nightly.20260228.1ca5c05d0",
"version": "0.33.0-preview.4",
"description": "Gemini CLI",
"license": "Apache-2.0",
"repository": {
@@ -26,7 +26,7 @@
"dist"
],
"config": {
"sandboxImageUri": "us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.33.0-nightly.20260228.1ca5c05d0"
"sandboxImageUri": "us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.33.0-preview.4"
},
"dependencies": {
"@agentclientprotocol/sdk": "^0.12.0",
@@ -14,7 +14,7 @@ import {
type Mock,
type Mocked,
} from 'vitest';
import { GeminiAgent, Session } from './zedIntegration.js';
import { GeminiAgent, Session } from './acpClient.js';
import type { CommandHandler } from './commandHandler.js';
import * as acp from '@agentclientprotocol/sdk';
import {
@@ -208,7 +208,16 @@ describe('GeminiAgent', () => {
});
expect(response.protocolVersion).toBe(acp.PROTOCOL_VERSION);
expect(response.authMethods).toHaveLength(3);
expect(response.authMethods).toHaveLength(4);
const gatewayAuth = response.authMethods?.find(
(m) => m.id === AuthType.GATEWAY,
);
expect(gatewayAuth?._meta).toEqual({
gateway: {
protocol: 'google',
restartRequired: 'false',
},
});
const geminiAuth = response.authMethods?.find(
(m) => m.id === AuthType.USE_GEMINI,
);
@@ -228,6 +237,8 @@ describe('GeminiAgent', () => {
expect(mockConfig.refreshAuth).toHaveBeenCalledWith(
AuthType.LOGIN_WITH_GOOGLE,
undefined,
undefined,
undefined,
);
expect(mockSettings.setValue).toHaveBeenCalledWith(
SettingScope.User,
@@ -247,6 +258,8 @@ describe('GeminiAgent', () => {
expect(mockConfig.refreshAuth).toHaveBeenCalledWith(
AuthType.USE_GEMINI,
'test-api-key',
undefined,
undefined,
);
expect(mockSettings.setValue).toHaveBeenCalledWith(
SettingScope.User,
@@ -255,6 +268,45 @@ describe('GeminiAgent', () => {
);
});
it('should authenticate correctly with gateway method', async () => {
await agent.authenticate({
methodId: AuthType.GATEWAY,
_meta: {
gateway: {
baseUrl: 'https://example.com',
headers: { Authorization: 'Bearer token' },
},
},
} as unknown as acp.AuthenticateRequest);
expect(mockConfig.refreshAuth).toHaveBeenCalledWith(
AuthType.GATEWAY,
undefined,
'https://example.com',
{ Authorization: 'Bearer token' },
);
expect(mockSettings.setValue).toHaveBeenCalledWith(
SettingScope.User,
'security.auth.selectedType',
AuthType.GATEWAY,
);
});
it('should throw acp.RequestError when gateway payload is malformed', async () => {
await expect(
agent.authenticate({
methodId: AuthType.GATEWAY,
_meta: {
gateway: {
// Invalid baseUrl
baseUrl: 123,
headers: { Authorization: 'Bearer token' },
},
},
} as unknown as acp.AuthenticateRequest),
).rejects.toThrow(/Malformed gateway payload/);
});
it('should create a new session', async () => {
vi.useFakeTimers();
mockConfig.getContentGeneratorConfig = vi.fn().mockReturnValue({
@@ -70,7 +70,7 @@ import { runExitCleanup } from '../utils/cleanup.js';
import { SessionSelector } from '../utils/sessionUtils.js';
import { CommandHandler } from './commandHandler.js';
export async function runZedIntegration(
export async function runAcpClient(
config: Config,
settings: LoadedSettings,
argv: CliArgs,
@@ -98,6 +98,8 @@ export class GeminiAgent {
private sessions: Map<string, Session> = new Map();
private clientCapabilities: acp.ClientCapabilities | undefined;
private apiKey: string | undefined;
private baseUrl: string | undefined;
private customHeaders: Record<string, string> | undefined;
constructor(
private config: Config,
@@ -131,6 +133,17 @@ export class GeminiAgent {
name: 'Vertex AI',
description: 'Use an API key with Vertex AI GenAI API',
},
{
id: AuthType.GATEWAY,
name: 'AI API Gateway',
description: 'Use a custom AI API Gateway',
_meta: {
gateway: {
protocol: 'google',
restartRequired: 'false',
},
},
},
];
await this.config.initialize();
@@ -179,7 +192,38 @@ export class GeminiAgent {
if (apiKey) {
this.apiKey = apiKey;
}
await this.config.refreshAuth(method, apiKey ?? this.apiKey);
// Extract gateway details if present
const gatewaySchema = z.object({
baseUrl: z.string().optional(),
headers: z.record(z.string()).optional(),
});
let baseUrl: string | undefined;
let headers: Record<string, string> | undefined;
if (meta?.['gateway']) {
const result = gatewaySchema.safeParse(meta['gateway']);
if (result.success) {
baseUrl = result.data.baseUrl;
headers = result.data.headers;
} else {
throw new acp.RequestError(
-32602,
`Malformed gateway payload: ${result.error.message}`,
);
}
}
this.baseUrl = baseUrl;
this.customHeaders = headers;
await this.config.refreshAuth(
method,
apiKey ?? this.apiKey,
baseUrl,
headers,
);
} catch (e) {
throw new acp.RequestError(-32000, getAcpErrorMessage(e));
}
@@ -209,7 +253,12 @@ export class GeminiAgent {
let isAuthenticated = false;
let authErrorMessage = '';
try {
await config.refreshAuth(authType, this.apiKey);
await config.refreshAuth(
authType,
this.apiKey,
this.baseUrl,
this.customHeaders,
);
isAuthenticated = true;
// Extra validation for Gemini API key
@@ -371,7 +420,12 @@ export class GeminiAgent {
// This satisfies the security requirement to verify the user before executing
// potentially unsafe server definitions.
try {
await config.refreshAuth(selectedAuthType, this.apiKey);
await config.refreshAuth(
selectedAuthType,
this.apiKey,
this.baseUrl,
this.customHeaders,
);
} catch (e) {
debugLogger.error(`Authentication failed: ${e}`);
throw acp.RequestError.authRequired();
@@ -13,7 +13,7 @@ import {
type Mocked,
type Mock,
} from 'vitest';
import { GeminiAgent } from './zedIntegration.js';
import { GeminiAgent } from './acpClient.js';
import * as acp from '@agentclientprotocol/sdk';
import {
ApprovalMode,
+11 -3
View File
@@ -81,7 +81,8 @@ export interface CliArgs {
policy: string[] | undefined;
allowedMcpServerNames: string[] | undefined;
allowedTools: string[] | undefined;
experimentalAcp: boolean | undefined;
acp?: boolean;
experimentalAcp?: boolean;
extensions: string[] | undefined;
listExtensions: boolean | undefined;
resume: string | typeof RESUME_LATEST | undefined;
@@ -177,10 +178,15 @@ export async function parseArguments(
.filter(Boolean),
),
})
.option('experimental-acp', {
.option('acp', {
type: 'boolean',
description: 'Starts the agent in ACP mode',
})
.option('experimental-acp', {
type: 'boolean',
description:
'Starts the agent in ACP mode (deprecated, use --acp instead)',
})
.option('allowed-mcp-server-names', {
type: 'array',
string: true,
@@ -632,6 +638,7 @@ export async function loadCliConfig(
// -i/--prompt-interactive forces interactive mode with an initial prompt
const interactive =
!!argv.promptInteractive ||
!!argv.acp ||
!!argv.experimentalAcp ||
(!isHeadlessMode({ prompt: argv.prompt, query: argv.query }) &&
!argv.isCommand);
@@ -758,6 +765,7 @@ export async function loadCliConfig(
}
return new Config({
acpMode: !!argv.acp || !!argv.experimentalAcp,
sessionId,
clientVersion: await getVersion(),
embeddingModel: DEFAULT_GEMINI_EMBEDDING_MODEL,
@@ -821,7 +829,7 @@ export async function loadCliConfig(
bugCommand: settings.advanced?.bugCommand,
model: resolvedModel,
maxSessionTurns: settings.model?.maxSessionTurns,
experimentalZedIntegration: argv.experimentalAcp || false,
listExtensions: argv.listExtensions || false,
listSessions: argv.listSessions || false,
deleteSession: argv.deleteSession,
+3 -3
View File
@@ -79,7 +79,7 @@ import {
type InitializationResult,
} from './core/initializer.js';
import { validateAuthMethod } from './config/auth.js';
import { runZedIntegration } from './zed-integration/zedIntegration.js';
import { runAcpClient } from './acp/acpClient.js';
import { validateNonInteractiveAuth } from './validateNonInterActiveAuth.js';
import { checkForUpdates } from './ui/utils/updateCheck.js';
import { handleAutoUpdate } from './utils/handleAutoUpdate.js';
@@ -672,8 +672,8 @@ export async function main() {
await getOauthClient(settings.merged.security.auth.selectedType, config);
}
if (config.getExperimentalZedIntegration()) {
return runZedIntegration(config, settings, argv);
if (config.getAcpMode()) {
return runAcpClient(config, settings, argv);
}
let input = config.getQuestion();
+2 -2
View File
@@ -179,7 +179,7 @@ describe('gemini.tsx main function cleanup', () => {
vi.restoreAllMocks();
});
it('should log error when cleanupExpiredSessions fails', async () => {
it.skip('should log error when cleanupExpiredSessions fails', async () => {
const { loadCliConfig, parseArguments } = await import(
'./config/config.js'
);
@@ -216,7 +216,7 @@ describe('gemini.tsx main function cleanup', () => {
getMcpServers: () => ({}),
getMcpClientManager: vi.fn(),
getIdeMode: vi.fn(() => false),
getExperimentalZedIntegration: vi.fn(() => true),
getAcpMode: vi.fn(() => true),
getScreenReader: vi.fn(() => false),
getGeminiMdFileCount: vi.fn(() => 0),
getProjectRoot: vi.fn(() => '/'),
+1 -1
View File
@@ -42,7 +42,7 @@ export const createMockConfig = (overrides: Partial<Config> = {}): Config =>
setSessionId: vi.fn(),
getSessionId: vi.fn().mockReturnValue('mock-session-id'),
getContentGeneratorConfig: vi.fn(() => ({ authType: 'google' })),
getExperimentalZedIntegration: vi.fn(() => false),
getAcpMode: vi.fn(() => false),
isBrowserLaunchSuppressed: vi.fn(() => false),
setRemoteAdminSettings: vi.fn(),
isYoloModeDisabled: vi.fn(() => false),
-130
View File
@@ -2544,136 +2544,6 @@ describe('AppContainer State Management', () => {
});
});
describe('Expansion Persistence', () => {
let rerender: () => void;
let unmount: () => void;
let stdin: ReturnType<typeof render>['stdin'];
const setupExpansionPersistenceTest = async (
HighPriorityChild?: React.FC,
) => {
const getTree = () => (
<SettingsContext.Provider value={mockSettings}>
<KeypressProvider config={mockConfig}>
<OverflowProvider>
<AppContainer
config={mockConfig}
version="1.0.0"
initializationResult={mockInitResult}
/>
{HighPriorityChild && <HighPriorityChild />}
</OverflowProvider>
</KeypressProvider>
</SettingsContext.Provider>
);
const renderResult = render(getTree());
stdin = renderResult.stdin;
await act(async () => {
vi.advanceTimersByTime(100);
});
rerender = () => renderResult.rerender(getTree());
unmount = () => renderResult.unmount();
};
const writeStdin = async (sequence: string) => {
await act(async () => {
stdin.write(sequence);
// Advance timers to allow escape sequence parsing and broadcasting
vi.advanceTimersByTime(100);
});
rerender();
};
beforeEach(() => {
vi.useFakeTimers();
});
afterEach(() => {
vi.useRealTimers();
vi.restoreAllMocks();
});
it('should reset expansion when a key is NOT handled by anyone', async () => {
await setupExpansionPersistenceTest();
// Expand first
act(() => capturedUIActions.setConstrainHeight(false));
rerender();
expect(capturedUIState.constrainHeight).toBe(false);
// Press a random key that no one handles (hits Low priority fallback)
await writeStdin('x');
// Should be reset to true (collapsed)
expect(capturedUIState.constrainHeight).toBe(true);
unmount();
});
it('should toggle expansion when Ctrl+O is pressed', async () => {
await setupExpansionPersistenceTest();
// Initial state is collapsed
expect(capturedUIState.constrainHeight).toBe(true);
// Press Ctrl+O to expand (Ctrl+O is sequence \x0f)
await writeStdin('\x0f');
expect(capturedUIState.constrainHeight).toBe(false);
// Press Ctrl+O again to collapse
await writeStdin('\x0f');
expect(capturedUIState.constrainHeight).toBe(true);
unmount();
});
it('should NOT collapse when a high-priority component handles the key (e.g., up/down arrows)', async () => {
const NavigationHandler = () => {
// use real useKeypress
useKeypress(
(key: Key) => {
if (key.name === 'up' || key.name === 'down') {
return true; // Handle navigation
}
return false;
},
{ isActive: true, priority: true }, // High priority
);
return null;
};
await setupExpansionPersistenceTest(NavigationHandler);
// Expand first
act(() => capturedUIActions.setConstrainHeight(false));
rerender();
expect(capturedUIState.constrainHeight).toBe(false);
// 1. Simulate Up arrow (handled by high priority child)
// CSI A is Up arrow
await writeStdin('\u001b[A');
// Should STILL be expanded
expect(capturedUIState.constrainHeight).toBe(false);
// 2. Simulate Down arrow (handled by high priority child)
// CSI B is Down arrow
await writeStdin('\u001b[B');
// Should STILL be expanded
expect(capturedUIState.constrainHeight).toBe(false);
// 3. Sanity check: press an unhandled key
await writeStdin('x');
// Should finally collapse
expect(capturedUIState.constrainHeight).toBe(true);
unmount();
});
});
describe('Shortcuts Help Visibility', () => {
let handleGlobalKeypress: (key: Key) => boolean;
let mockedUseKeypress: Mock;
+1 -4
View File
@@ -1873,10 +1873,7 @@ Logging in with Google... Restarting Gemini CLI to continue.
],
);
useKeypress(handleGlobalKeypress, {
isActive: true,
priority: KeypressPriority.Low,
});
useKeypress(handleGlobalKeypress, { isActive: true, priority: true });
useKeypress(
() => {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@google/gemini-cli-core",
"version": "0.33.0-nightly.20260228.1ca5c05d0",
"version": "0.33.0-preview.4",
"description": "Gemini CLI Core",
"license": "Apache-2.0",
"repository": {
+2 -1
View File
@@ -95,7 +95,8 @@ const mockConfig = {
getNoBrowser: () => false,
getProxy: () => 'http://test.proxy.com:8080',
isBrowserLaunchSuppressed: () => false,
getExperimentalZedIntegration: () => false,
getAcpMode: () => false,
isInteractive: () => true,
} as unknown as Config;
// Mock fetch globally
+2 -2
View File
@@ -271,8 +271,8 @@ async function initOauthClient(
await triggerPostAuthCallbacks(client.credentials);
} else {
// In Zed integration, we skip the interactive consent and directly open the browser
if (!config.getExperimentalZedIntegration()) {
// In ACP mode, we skip the interactive consent and directly open the browser
if (!config.getAcpMode()) {
const userConsent = await getConsentForOauth('');
if (!userConsent) {
throw new FatalCancellationError('Authentication cancelled by user.');
+2
View File
@@ -500,6 +500,8 @@ describe('Server Config (config.ts)', () => {
config,
authType,
undefined,
undefined,
undefined,
);
// Verify that contentGeneratorConfig is updated
expect(config.getContentGeneratorConfig()).toEqual(mockContentConfig);
+14 -8
View File
@@ -503,7 +503,7 @@ export interface ConfigParameters {
model: string;
disableLoopDetection?: boolean;
maxSessionTurns?: number;
experimentalZedIntegration?: boolean;
acpMode?: boolean;
listSessions?: boolean;
deleteSession?: string;
listExtensions?: boolean;
@@ -699,7 +699,7 @@ export class Config implements McpContext {
private readonly summarizeToolOutput:
| Record<string, SummarizeToolOutputSettings>
| undefined;
private readonly experimentalZedIntegration: boolean = false;
private readonly acpMode: boolean = false;
private readonly loadMemoryFromIncludeDirectories: boolean = false;
private readonly includeDirectoryTree: boolean = true;
private readonly importFormat: 'tree' | 'flat';
@@ -894,8 +894,7 @@ export class Config implements McpContext {
DEFAULT_PROTECT_LATEST_TURN,
};
this.maxSessionTurns = params.maxSessionTurns ?? -1;
this.experimentalZedIntegration =
params.experimentalZedIntegration ?? false;
this.acpMode = params.acpMode ?? false;
this.listSessions = params.listSessions ?? false;
this.deleteSession = params.deleteSession;
this.listExtensions = params.listExtensions ?? false;
@@ -1148,7 +1147,7 @@ export class Config implements McpContext {
}
});
if (!this.interactive || this.experimentalZedIntegration) {
if (!this.interactive || this.acpMode) {
await this.mcpInitializationPromise;
}
@@ -1191,7 +1190,12 @@ export class Config implements McpContext {
return this.contentGenerator;
}
async refreshAuth(authMethod: AuthType, apiKey?: string) {
async refreshAuth(
authMethod: AuthType,
apiKey?: string,
baseUrl?: string,
customHeaders?: Record<string, string>,
) {
// Reset availability service when switching auth
this.modelAvailabilityService.reset();
@@ -1218,6 +1222,8 @@ export class Config implements McpContext {
this,
authMethod,
apiKey,
baseUrl,
customHeaders,
);
this.contentGenerator = await createContentGenerator(
newContentGeneratorConfig,
@@ -2205,8 +2211,8 @@ export class Config implements McpContext {
return this.usageStatisticsEnabled;
}
getExperimentalZedIntegration(): boolean {
return this.experimentalZedIntegration;
getAcpMode(): boolean {
return this.acpMode;
}
async waitForMcpInit(): Promise<void> {
+20 -2
View File
@@ -59,6 +59,7 @@ export enum AuthType {
USE_VERTEX_AI = 'vertex-ai',
LEGACY_CLOUD_SHELL = 'cloud-shell',
COMPUTE_ADC = 'compute-default-credentials',
GATEWAY = 'gateway',
}
/**
@@ -93,12 +94,16 @@ export type ContentGeneratorConfig = {
vertexai?: boolean;
authType?: AuthType;
proxy?: string;
baseUrl?: string;
customHeaders?: Record<string, string>;
};
export async function createContentGeneratorConfig(
config: Config,
authType: AuthType | undefined,
apiKey?: string,
baseUrl?: string,
customHeaders?: Record<string, string>,
): Promise<ContentGeneratorConfig> {
const geminiApiKey =
apiKey ||
@@ -115,6 +120,8 @@ export async function createContentGeneratorConfig(
const contentGeneratorConfig: ContentGeneratorConfig = {
authType,
proxy: config?.getProxy(),
baseUrl,
customHeaders,
};
// If we are using Google auth or we are in Cloud Shell, there is nothing else to validate for now
@@ -203,9 +210,13 @@ export async function createContentGenerator(
if (
config.authType === AuthType.USE_GEMINI ||
config.authType === AuthType.USE_VERTEX_AI
config.authType === AuthType.USE_VERTEX_AI ||
config.authType === AuthType.GATEWAY
) {
let headers: Record<string, string> = { ...baseHeaders };
if (config.customHeaders) {
headers = { ...headers, ...config.customHeaders };
}
if (gcConfig?.getUsageStatisticsEnabled()) {
const installationManager = new InstallationManager();
const installationId = installationManager.getInstallationId();
@@ -214,7 +225,14 @@ export async function createContentGenerator(
'x-gemini-api-privileged-user-id': `${installationId}`,
};
}
const httpOptions = { headers };
const httpOptions: {
baseUrl?: string;
headers: Record<string, string>;
} = { headers };
if (config.baseUrl) {
httpOptions.baseUrl = config.baseUrl;
}
const googleGenAI = new GoogleGenAI({
apiKey: config.apiKey === '' ? undefined : config.apiKey,
@@ -51,3 +51,8 @@ priority = 50
toolName = "google_web_search"
decision = "allow"
priority = 50
[[rule]]
toolName = ["codebase_investigator", "cli_help"]
decision = "allow"
priority = 50
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@google/gemini-cli-devtools",
"version": "0.33.0-nightly.20260228.1ca5c05d0",
"version": "0.33.0-preview.4",
"license": "Apache-2.0",
"type": "module",
"main": "dist/src/index.js",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@google/gemini-cli-sdk",
"version": "0.33.0-nightly.20260228.1ca5c05d0",
"version": "0.33.0-preview.4",
"description": "Gemini CLI SDK",
"license": "Apache-2.0",
"repository": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@google/gemini-cli-test-utils",
"version": "0.33.0-nightly.20260228.1ca5c05d0",
"version": "0.33.0-preview.4",
"private": true,
"main": "src/index.ts",
"license": "Apache-2.0",
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "gemini-cli-vscode-ide-companion",
"displayName": "Gemini CLI Companion",
"description": "Enable Gemini CLI with direct access to your IDE workspace.",
"version": "0.33.0-nightly.20260228.1ca5c05d0",
"version": "0.33.0-preview.4",
"publisher": "google",
"icon": "assets/icon.png",
"repository": {