Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions docs/changelogs/preview.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Preview release: v0.41.0-preview.0
# Preview release: v0.42.0-preview.1

Released: April 28, 2026
Released: May 05, 2026

Our preview release includes the latest, new, and experimental features. This
release may not be as stable as our [latest weekly release](latest.md).
Expand Down Expand Up @@ -28,6 +28,10 @@ npm install -g @google/gemini-cli@preview

## What's Changed

- fix(patch): cherry-pick 3627f47 to release/v0.42.0-preview.0-pr-26542 to patch
version v0.42.0-preview.0 and create version 0.42.0-preview.1 by
@gemini-cli-robot in
[#26544](https://github.com/google-gemini/gemini-cli/pull/26544)
- chore(release): bump version to 0.41.0-nightly.20260423.gaa05b4583 by
@gemini-cli-robot in
[#25847](https://github.com/google-gemini/gemini-cli/pull/25847)
Expand Down Expand Up @@ -118,4 +122,4 @@ npm install -g @google/gemini-cli@preview
[#26078](https://github.com/google-gemini/gemini-cli/pull/26078)

**Full Changelog**:
https://github.com/google-gemini/gemini-cli/compare/v0.40.0-preview.5...v0.41.0-preview.0
https://github.com/google-gemini/gemini-cli/compare/v0.40.0-preview.5...v0.42.0-preview.1
1 change: 1 addition & 0 deletions docs/ide-integration/ide-companion-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ creating a "discovery file."
}
}
```

- `port` (number, required): The port of the MCP server.
- `workspacePath` (string, required): A list of all open workspace root paths,
delimited by the OS-specific path separator (`:` for Linux/macOS, `;` for
Expand Down
10 changes: 4 additions & 6 deletions evals/auto_memory_modes.eval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,8 @@ async function expectSeedSessionEligible(
fixture: Fixture,
sessionId: string,
): Promise<void> {
const { buildSessionIndex } = await import(
'../packages/core/src/services/memoryService.js'
);
const { buildSessionIndex } =
await import('../packages/core/src/services/memoryService.js');
const { newSessionIds } = await buildSessionIndex(
path.join(fixture.projectTempDir, 'chats'),
{ runs: [] },
Expand Down Expand Up @@ -386,9 +385,8 @@ describe('Auto Memory inbox routing', () => {
autoMemoryEval(
'every memory patch lands in .inbox/<kind>/ for review and active files stay untouched',
async () => {
const { startMemoryService } = await import(
'../packages/core/src/services/memoryService.js'
);
const { startMemoryService } =
await import('../packages/core/src/services/memoryService.js');
const fixture = await createFixture();
evalState.sessionFilePath = await seedSession(
fixture,
Expand Down
5 changes: 2 additions & 3 deletions packages/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,8 @@ async function run() {
// --- Heavy Child Process ---
// Now we can safely import everything.
const { main } = await import('./src/gemini.js');
const { FatalError, writeToStderr } = await import(
'@google/gemini-cli-core'
);
const { FatalError, writeToStderr } =
await import('@google/gemini-cli-core');
const { runExitCleanup } = await import('./src/utils/cleanup.js');

main().catch(async (error: unknown) => {
Expand Down
5 changes: 2 additions & 3 deletions packages/cli/src/acp/acpSession.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -566,9 +566,8 @@ describe('Session', () => {
});

it('should send sessionUpdate when approval mode changes', async () => {
const { coreEvents, CoreEvent, ApprovalMode } = await import(
'@google/gemini-cli-core'
);
const { coreEvents, CoreEvent, ApprovalMode } =
await import('@google/gemini-cli-core');

coreEvents.emit(CoreEvent.ApprovalModeChanged, {
sessionId: 'session-1',
Expand Down
5 changes: 2 additions & 3 deletions packages/cli/src/commands/extensions/link.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ import { ExtensionManager } from '../../config/extension-manager.js';
import { loadSettings, type LoadedSettings } from '../../config/settings.js';

vi.mock('@google/gemini-cli-core', async (importOriginal) => {
const { mockCoreDebugLogger } = await import(
'../../test-utils/mockDebugLogger.js'
);
const { mockCoreDebugLogger } =
await import('../../test-utils/mockDebugLogger.js');
const actual =
await importOriginal<typeof import('@google/gemini-cli-core')>();
const mocked = mockCoreDebugLogger(actual, { stripAnsi: true });
Expand Down
5 changes: 2 additions & 3 deletions packages/cli/src/commands/extensions/list.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ import { ExtensionManager } from '../../config/extension-manager.js';
import { loadSettings, type LoadedSettings } from '../../config/settings.js';

vi.mock('@google/gemini-cli-core', async (importOriginal) => {
const { mockCoreDebugLogger } = await import(
'../../test-utils/mockDebugLogger.js'
);
const { mockCoreDebugLogger } =
await import('../../test-utils/mockDebugLogger.js');
const actual =
await importOriginal<typeof import('@google/gemini-cli-core')>();
const mocked = mockCoreDebugLogger(actual, { stripAnsi: false });
Expand Down
5 changes: 2 additions & 3 deletions packages/cli/src/commands/gemma/logs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ import { getLogFilePath } from './constants.js';
import { logsCommand, readLastLines } from './logs.js';

vi.mock('@google/gemini-cli-core', async (importOriginal) => {
const { mockCoreDebugLogger } = await import(
'../../test-utils/mockDebugLogger.js'
);
const { mockCoreDebugLogger } =
await import('../../test-utils/mockDebugLogger.js');
return mockCoreDebugLogger(
await importOriginal<typeof import('@google/gemini-cli-core')>(),
{
Expand Down
5 changes: 2 additions & 3 deletions packages/cli/src/commands/gemma/stop.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ const mockReadServerProcessInfo = vi.hoisted(() => vi.fn());
const mockResolveGemmaConfig = vi.hoisted(() => vi.fn());

vi.mock('@google/gemini-cli-core', async (importOriginal) => {
const { mockCoreDebugLogger } = await import(
'../../test-utils/mockDebugLogger.js'
);
const { mockCoreDebugLogger } =
await import('../../test-utils/mockDebugLogger.js');
return mockCoreDebugLogger(
await importOriginal<typeof import('@google/gemini-cli-core')>(),
{
Expand Down
5 changes: 2 additions & 3 deletions packages/cli/src/commands/skills/disable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ import {
} from '../../config/settings.js';

const { emitConsoleLog, debugLogger } = await vi.hoisted(async () => {
const { createMockDebugLogger } = await import(
'../../test-utils/mockDebugLogger.js'
);
const { createMockDebugLogger } =
await import('../../test-utils/mockDebugLogger.js');
return createMockDebugLogger({ stripAnsi: true });
});

Expand Down
5 changes: 2 additions & 3 deletions packages/cli/src/commands/skills/enable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ import {
} from '../../config/settings.js';

const { emitConsoleLog, debugLogger } = await vi.hoisted(async () => {
const { createMockDebugLogger } = await import(
'../../test-utils/mockDebugLogger.js'
);
const { createMockDebugLogger } =
await import('../../test-utils/mockDebugLogger.js');
return createMockDebugLogger({ stripAnsi: true });
});

Expand Down
5 changes: 2 additions & 3 deletions packages/cli/src/commands/skills/install.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ vi.mock('../../config/extensions/consent.js', () => ({
}));

const { debugLogger, emitConsoleLog } = await vi.hoisted(async () => {
const { createMockDebugLogger } = await import(
'../../test-utils/mockDebugLogger.js'
);
const { createMockDebugLogger } =
await import('../../test-utils/mockDebugLogger.js');
return createMockDebugLogger({ stripAnsi: true });
});

Expand Down
5 changes: 2 additions & 3 deletions packages/cli/src/commands/skills/link.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ vi.mock('../../utils/skillUtils.js', () => ({
}));

const { debugLogger } = await vi.hoisted(async () => {
const { createMockDebugLogger } = await import(
'../../test-utils/mockDebugLogger.js'
);
const { createMockDebugLogger } =
await import('../../test-utils/mockDebugLogger.js');
return createMockDebugLogger({ stripAnsi: false });
});

Expand Down
5 changes: 2 additions & 3 deletions packages/cli/src/commands/skills/list.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ import { loadCliConfig } from '../../config/config.js';
import chalk from 'chalk';

vi.mock('@google/gemini-cli-core', async (importOriginal) => {
const { mockCoreDebugLogger } = await import(
'../../test-utils/mockDebugLogger.js'
);
const { mockCoreDebugLogger } =
await import('../../test-utils/mockDebugLogger.js');
return mockCoreDebugLogger(
await importOriginal<typeof import('@google/gemini-cli-core')>(),
{
Expand Down
5 changes: 2 additions & 3 deletions packages/cli/src/commands/skills/uninstall.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ vi.mock('../../utils/skillUtils.js', () => ({
}));

const { debugLogger, emitConsoleLog } = await vi.hoisted(async () => {
const { createMockDebugLogger } = await import(
'../../test-utils/mockDebugLogger.js'
);
const { createMockDebugLogger } =
await import('../../test-utils/mockDebugLogger.js');
return createMockDebugLogger({ stripAnsi: true });
});

Expand Down
5 changes: 2 additions & 3 deletions packages/cli/src/config/extension-manager-hydration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,9 +300,8 @@ System using model: \${MODEL_NAME}
});
expect(extension.skills![0].body).toContain('Value is: first');

const { updateSetting, ExtensionSettingScope } = await import(
'./extensions/extensionSettings.js'
);
const { updateSetting, ExtensionSettingScope } =
await import('./extensions/extensionSettings.js');
const extensionConfig =
await extensionManager.loadExtensionConfig(extensionPath);

Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/config/extension-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,8 @@ Would you like to attempt to install via "git clone" instead?`,
const previousSkills = previous?.skills ?? [];
const isMigrating = Boolean(
previous &&
previous.installMetadata &&
previous.installMetadata.source !== installMetadata.source,
previous.installMetadata &&
previous.installMetadata.source !== installMetadata.source,
);

await maybeRequestConsentOrFail(
Expand Down
5 changes: 2 additions & 3 deletions packages/cli/src/gemini.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -938,9 +938,8 @@ describe('gemini.tsx main function kitty protocol', () => {
});

it.skip('should log error when cleanupExpiredSessions fails', async () => {
const { cleanupExpiredSessions } = await import(
'./utils/sessionCleanup.js'
);
const { cleanupExpiredSessions } =
await import('./utils/sessionCleanup.js');
vi.mocked(cleanupExpiredSessions).mockRejectedValue(
new Error('Cleanup failed'),
);
Expand Down
5 changes: 2 additions & 3 deletions packages/cli/src/gemini.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -552,9 +552,8 @@ export async function main() {
adminControlsListner.setConfig(config);

if (config.isInteractive() && settings.merged.general.devtools) {
const { setupInitialActivityLogger } = await import(
'./utils/devtoolsService.js'
);
const { setupInitialActivityLogger } =
await import('./utils/devtoolsService.js');
setupInitialActivityLogger(config);
}

Expand Down
20 changes: 8 additions & 12 deletions packages/cli/src/gemini_cleanup.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,8 @@ describe('gemini.tsx main function cleanup', () => {
});

it.skip('should log error when cleanupExpiredSessions fails', async () => {
const { loadCliConfig, parseArguments } = await import(
'./config/config.js'
);
const { loadCliConfig, parseArguments } =
await import('./config/config.js');
const { loadSettings } = await import('./config/settings.js');
cleanupMockState.shouldThrow = true;
cleanupMockState.called = false;
Expand Down Expand Up @@ -272,9 +271,8 @@ describe('gemini.tsx main function cleanup', () => {
});

it('should register SessionEnd hook exactly once in non-interactive mode', async () => {
const { loadCliConfig, parseArguments } = await import(
'./config/config.js'
);
const { loadCliConfig, parseArguments } =
await import('./config/config.js');
const { registerCleanup } = await import('./utils/cleanup.js');

const mockHookSystem = {
Expand Down Expand Up @@ -310,9 +308,8 @@ describe('gemini.tsx main function cleanup', () => {
it('should not register ConsolePatcher cleanup in ACP mode', async () => {
const { registerCleanup } = await import('./utils/cleanup.js');
const { ConsolePatcher } = await import('./ui/utils/ConsolePatcher.js');
const { loadCliConfig, parseArguments } = await import(
'./config/config.js'
);
const { loadCliConfig, parseArguments } =
await import('./config/config.js');
const { loadSettings } = await import('./config/settings.js');

vi.mocked(parseArguments).mockResolvedValue({
Expand Down Expand Up @@ -364,9 +361,8 @@ describe('gemini.tsx main function cleanup', () => {
it('should register ConsolePatcher cleanup in non-ACP mode', async () => {
const { registerCleanup } = await import('./utils/cleanup.js');
const { ConsolePatcher } = await import('./ui/utils/ConsolePatcher.js');
const { loadCliConfig, parseArguments } = await import(
'./config/config.js'
);
const { loadCliConfig, parseArguments } =
await import('./config/config.js');
const { loadSettings } = await import('./config/settings.js');

vi.mocked(parseArguments).mockResolvedValue({
Expand Down
25 changes: 10 additions & 15 deletions packages/cli/src/nonInteractiveCli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,8 @@ describe('runNonInteractive', () => {
computeMergedSettings: vi.fn(),
} as unknown as LoadedSettings;

const { handleAtCommand } = await import(
'./ui/hooks/atCommandProcessor.js'
);
const { handleAtCommand } =
await import('./ui/hooks/atCommandProcessor.js');
vi.mocked(handleAtCommand).mockImplementation(async ({ query }) => ({
processedQuery: [{ text: query }],
}));
Expand Down Expand Up @@ -636,9 +635,8 @@ describe('runNonInteractive', () => {

it('should preprocess @include commands before sending to the model', async () => {
// 1. Mock the imported atCommandProcessor
const { handleAtCommand } = await import(
'./ui/hooks/atCommandProcessor.js'
);
const { handleAtCommand } =
await import('./ui/hooks/atCommandProcessor.js');
const mockHandleAtCommand = vi.mocked(handleAtCommand);

// 2. Define the raw input and the expected processed output
Expand Down Expand Up @@ -991,9 +989,8 @@ describe('runNonInteractive', () => {
});

it('should handle slash commands', async () => {
const nonInteractiveCliCommands = await import(
'./nonInteractiveCliCommands.js'
);
const nonInteractiveCliCommands =
await import('./nonInteractiveCliCommands.js');
const handleSlashCommandSpy = vi.spyOn(
nonInteractiveCliCommands,
'handleSlashCommand',
Expand Down Expand Up @@ -1271,13 +1268,11 @@ describe('runNonInteractive', () => {

it('should instantiate CommandService with correct loaders for slash commands', async () => {
// This test indirectly checks that handleSlashCommand is using the right loaders.
const { FileCommandLoader } = await import(
'./services/FileCommandLoader.js'
);
const { FileCommandLoader } =
await import('./services/FileCommandLoader.js');
const { McpPromptLoader } = await import('./services/McpPromptLoader.js');
const { BuiltinCommandLoader } = await import(
'./services/BuiltinCommandLoader.js'
);
const { BuiltinCommandLoader } =
await import('./services/BuiltinCommandLoader.js');
mockGetCommands.mockReturnValue([]); // No commands found, so it will fall through
const events: ServerGeminiStreamEvent[] = [
{ type: GeminiEventType.Content, value: 'Acknowledged' },
Expand Down
5 changes: 2 additions & 3 deletions packages/cli/src/nonInteractiveCli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,8 @@ export async function runNonInteractive(
});

if (process.env['GEMINI_CLI_ACTIVITY_LOG_TARGET']) {
const { setupInitialActivityLogger } = await import(
'./utils/devtoolsService.js'
);
const { setupInitialActivityLogger } =
await import('./utils/devtoolsService.js');
setupInitialActivityLogger(config);
}

Expand Down
Loading
Loading