mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-06-27 03:37:27 -07:00
fix(patch): cherry-pick f08b4af to release/v0.45.2-pr-27749 to patch version v0.45.2 and create version 0.45.3 (#27769)
Co-authored-by: David Pierce <davidapierce@google.com> Co-authored-by: Gal Zahavi <38544478+galz10@users.noreply.github.com>
This commit is contained in:
@@ -12,7 +12,12 @@ import { MessageType } from '../types.js';
|
||||
|
||||
describe('helpCommand', () => {
|
||||
let mockContext: CommandContext;
|
||||
const originalEnv = { ...process.env };
|
||||
const originalPlatform = process.platform;
|
||||
const action = helpCommand.action;
|
||||
|
||||
if (!action) {
|
||||
throw new Error('Help command has no action');
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
mockContext = createMockCommandContext({
|
||||
@@ -23,16 +28,13 @@ describe('helpCommand', () => {
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
process.env = { ...originalEnv };
|
||||
Object.defineProperty(process, 'platform', { value: originalPlatform });
|
||||
vi.unstubAllEnvs();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should add a help message to the UI history', async () => {
|
||||
if (!helpCommand.action) {
|
||||
throw new Error('Help command has no action');
|
||||
}
|
||||
|
||||
await helpCommand.action(mockContext, '');
|
||||
it('should add a help message to the UI history by default', async () => {
|
||||
await action(mockContext, '');
|
||||
|
||||
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
@@ -47,4 +49,85 @@ describe('helpCommand', () => {
|
||||
expect(helpCommand.kind).toBe(CommandKind.BUILT_IN);
|
||||
expect(helpCommand.description).toBe('For help on gemini-cli');
|
||||
});
|
||||
|
||||
describe('Antigravity installer commands help', () => {
|
||||
it('should output macOS installation command on darwin platform', async () => {
|
||||
Object.defineProperty(process, 'platform', { value: 'darwin' });
|
||||
|
||||
await action(mockContext, 'install antigravity cli');
|
||||
|
||||
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
type: MessageType.INFO,
|
||||
text: `To install the Antigravity CLI on macOS, run the following command:\n\n'curl -fsSL https://antigravity.google/cli/install.sh | bash'`,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should output Linux installation command on linux platform', async () => {
|
||||
Object.defineProperty(process, 'platform', { value: 'linux' });
|
||||
|
||||
await action(mockContext, 'how do I install antigravity CLI');
|
||||
|
||||
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
type: MessageType.INFO,
|
||||
text: `To install the Antigravity CLI on Linux, run the following command:\n\n'curl -fsSL https://antigravity.google/cli/install.sh | bash'`,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should output Windows PowerShell installation command on win32 when PSModulePath is set', async () => {
|
||||
Object.defineProperty(process, 'platform', { value: 'win32' });
|
||||
vi.stubEnv('PSModulePath', 'C:\\some\\path');
|
||||
|
||||
await action(mockContext, 'how do I migrate to antigravity CLI');
|
||||
|
||||
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
type: MessageType.INFO,
|
||||
text: `To install the Antigravity CLI on Windows (PowerShell), run the following command:\n\n'irm https://antigravity.google/cli/install.ps1 | iex'`,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should output Windows CMD installation command on win32 when PSModulePath is not set', async () => {
|
||||
Object.defineProperty(process, 'platform', { value: 'win32' });
|
||||
vi.stubEnv('PSModulePath', '');
|
||||
|
||||
await action(mockContext, 'install antigravity cli');
|
||||
|
||||
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
type: MessageType.INFO,
|
||||
text: `To install the Antigravity CLI on Windows (Command Prompt), run the following command:\n\n'curl -fsSL https://antigravity.google/cli/install.cmd -o install.cmd && install.cmd && del install.cmd'`,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should learn more message on unsupported platform', async () => {
|
||||
Object.defineProperty(process, 'platform', { value: 'freebsd' });
|
||||
|
||||
await action(mockContext, 'install antigravity cli');
|
||||
|
||||
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
type: MessageType.INFO,
|
||||
text: 'Learn more about Antigravity CLI at https://antigravity.google/docs/cli-getting-started',
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should fall back to default help if query does not contain install or migrate', async () => {
|
||||
Object.defineProperty(process, 'platform', { value: 'darwin' });
|
||||
|
||||
await action(mockContext, 'antigravity cli');
|
||||
|
||||
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
type: MessageType.HELP,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,13 +6,36 @@
|
||||
|
||||
import { CommandKind, type SlashCommand } from './types.js';
|
||||
import { MessageType, type HistoryItemHelp } from '../types.js';
|
||||
import { getAntigravityInstallInfo } from '../utils/antigravityUtils.js';
|
||||
|
||||
export const helpCommand: SlashCommand = {
|
||||
name: 'help',
|
||||
kind: CommandKind.BUILT_IN,
|
||||
description: 'For help on gemini-cli',
|
||||
autoExecute: true,
|
||||
action: async (context) => {
|
||||
action: async (context, args) => {
|
||||
const lowerArgs = args?.toLowerCase() || '';
|
||||
const hasAntigravity = lowerArgs.includes('antigravity');
|
||||
const hasInstallOrMigrate =
|
||||
lowerArgs.includes('install') || lowerArgs.includes('migrate');
|
||||
|
||||
if (hasAntigravity && hasInstallOrMigrate) {
|
||||
const info = getAntigravityInstallInfo();
|
||||
|
||||
if (info) {
|
||||
context.ui.addItem({
|
||||
type: MessageType.INFO,
|
||||
text: `To install the Antigravity CLI on ${info.platformName}, run the following command:\n\n'${info.installCmd}'`,
|
||||
});
|
||||
} else {
|
||||
context.ui.addItem({
|
||||
type: MessageType.INFO,
|
||||
text: `Learn more about Antigravity CLI at https://antigravity.google/docs/cli-getting-started`,
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const helpItem: Omit<HistoryItemHelp, 'id'> = {
|
||||
type: MessageType.HELP,
|
||||
timestamp: new Date(),
|
||||
|
||||
@@ -10,12 +10,14 @@ import {
|
||||
expect,
|
||||
vi,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
type MockedFunction,
|
||||
} from 'vitest';
|
||||
import { renderHook } from '../../test-utils/render.js';
|
||||
import { useBanner, _clearSessionBannersForTest } from './useBanner.js';
|
||||
import { persistentState } from '../../utils/persistentState.js';
|
||||
import crypto from 'node:crypto';
|
||||
import chalk from 'chalk';
|
||||
|
||||
vi.mock('../../utils/persistentState.js', () => ({
|
||||
persistentState: {
|
||||
@@ -94,7 +96,9 @@ describe('useBanner', () => {
|
||||
|
||||
const { result } = await renderHook(() => useBanner(antigravityBannerData));
|
||||
|
||||
expect(result.current.bannerText).toBe('Antigravity is coming to town!');
|
||||
expect(result.current.bannerText).toContain(
|
||||
'Antigravity is coming to town!',
|
||||
);
|
||||
});
|
||||
|
||||
it('should increment the persistent count when banner is shown', async () => {
|
||||
@@ -137,4 +141,77 @@ describe('useBanner', () => {
|
||||
|
||||
expect(result.current.bannerText).toBe('Line1\nLine2');
|
||||
});
|
||||
|
||||
describe('Antigravity installation commands', () => {
|
||||
const originalPlatform = process.platform;
|
||||
|
||||
afterEach(() => {
|
||||
Object.defineProperty(process, 'platform', { value: originalPlatform });
|
||||
vi.unstubAllEnvs();
|
||||
});
|
||||
|
||||
it('should append macOS & Linux install command when on darwin', async () => {
|
||||
Object.defineProperty(process, 'platform', { value: 'darwin' });
|
||||
const data = { defaultText: 'Welcome to Antigravity!', warningText: '' };
|
||||
|
||||
const { result } = await renderHook(() => useBanner(data));
|
||||
|
||||
expect(result.current.bannerText).toBe(
|
||||
`Welcome to Antigravity!\n \nTo install run "${chalk.bold('curl -fsSL https://antigravity.google/cli/install.sh | bash')}"`,
|
||||
);
|
||||
});
|
||||
|
||||
it('should append macOS & Linux install command when on linux', async () => {
|
||||
Object.defineProperty(process, 'platform', { value: 'linux' });
|
||||
const data = { defaultText: 'Welcome to Antigravity!', warningText: '' };
|
||||
|
||||
const { result } = await renderHook(() => useBanner(data));
|
||||
|
||||
expect(result.current.bannerText).toBe(
|
||||
`Welcome to Antigravity!\n \nTo install run "${chalk.bold('curl -fsSL https://antigravity.google/cli/install.sh | bash')}"`,
|
||||
);
|
||||
});
|
||||
|
||||
it('should append Windows PowerShell install command when on win32 and PSModulePath is set', async () => {
|
||||
Object.defineProperty(process, 'platform', { value: 'win32' });
|
||||
vi.stubEnv('PSModulePath', 'C:\\some\\path');
|
||||
const data = { defaultText: 'Welcome to Antigravity!', warningText: '' };
|
||||
|
||||
const { result } = await renderHook(() => useBanner(data));
|
||||
|
||||
expect(result.current.bannerText).toBe(
|
||||
`Welcome to Antigravity!\n \nTo install run "${chalk.bold('irm https://antigravity.google/cli/install.ps1 | iex')}"`,
|
||||
);
|
||||
});
|
||||
|
||||
it('should append Windows CMD install command when on win32 and PSModulePath is not set', async () => {
|
||||
Object.defineProperty(process, 'platform', { value: 'win32' });
|
||||
vi.stubEnv('PSModulePath', '');
|
||||
const data = { defaultText: 'Welcome to Antigravity!', warningText: '' };
|
||||
|
||||
const { result } = await renderHook(() => useBanner(data));
|
||||
|
||||
expect(result.current.bannerText).toBe(
|
||||
`Welcome to Antigravity!\n \nTo install run "${chalk.bold('curl -fsSL https://antigravity.google/cli/install.cmd -o install.cmd && install.cmd && del install.cmd')}"`,
|
||||
);
|
||||
});
|
||||
|
||||
it('should not append install command if banner text does not contain Antigravity', async () => {
|
||||
Object.defineProperty(process, 'platform', { value: 'darwin' });
|
||||
const data = { defaultText: 'Regular Banner', warningText: '' };
|
||||
|
||||
const { result } = await renderHook(() => useBanner(data));
|
||||
|
||||
expect(result.current.bannerText).toBe('Regular Banner');
|
||||
});
|
||||
|
||||
it('should not append install command if process.platform is an unsupported platform', async () => {
|
||||
Object.defineProperty(process, 'platform', { value: 'freebsd' });
|
||||
const data = { defaultText: 'Welcome to Antigravity!', warningText: '' };
|
||||
|
||||
const { result } = await renderHook(() => useBanner(data));
|
||||
|
||||
expect(result.current.bannerText).toBe('Welcome to Antigravity!');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { persistentState } from '../../utils/persistentState.js';
|
||||
import crypto from 'node:crypto';
|
||||
import chalk from 'chalk';
|
||||
import { getAntigravityInstallInfo } from '../utils/antigravityUtils.js';
|
||||
|
||||
const DEFAULT_MAX_BANNER_SHOWN_COUNT = 5;
|
||||
|
||||
@@ -46,7 +48,14 @@ export function useBanner(bannerData: BannerData) {
|
||||
activeText.includes('Antigravity'));
|
||||
|
||||
const rawBannerText = showBanner ? activeText : '';
|
||||
const bannerText = rawBannerText.replace(/\\n/g, '\n');
|
||||
let bannerText = rawBannerText.replace(/\\n/g, '\n');
|
||||
|
||||
if (showBanner && activeText.includes('Antigravity')) {
|
||||
const info = getAntigravityInstallInfo();
|
||||
if (info) {
|
||||
bannerText += `\n \nTo install run "${chalk.bold(info.installCmd)}"`;
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (showBanner && activeText) {
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect, vi, afterEach } from 'vitest';
|
||||
import { getAntigravityInstallInfo } from './antigravityUtils.js';
|
||||
|
||||
describe('antigravityUtils', () => {
|
||||
const originalPlatform = process.platform;
|
||||
|
||||
afterEach(() => {
|
||||
Object.defineProperty(process, 'platform', { value: originalPlatform });
|
||||
vi.unstubAllEnvs();
|
||||
});
|
||||
|
||||
it('should return macOS installation info on darwin platform', () => {
|
||||
Object.defineProperty(process, 'platform', { value: 'darwin' });
|
||||
|
||||
const info = getAntigravityInstallInfo();
|
||||
|
||||
expect(info).toEqual({
|
||||
platformName: 'macOS',
|
||||
installCmd: 'curl -fsSL https://antigravity.google/cli/install.sh | bash',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return Linux installation info on linux platform', () => {
|
||||
Object.defineProperty(process, 'platform', { value: 'linux' });
|
||||
|
||||
const info = getAntigravityInstallInfo();
|
||||
|
||||
expect(info).toEqual({
|
||||
platformName: 'Linux',
|
||||
installCmd: 'curl -fsSL https://antigravity.google/cli/install.sh | bash',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return Windows PowerShell installation info on win32 when PSModulePath is set', () => {
|
||||
Object.defineProperty(process, 'platform', { value: 'win32' });
|
||||
vi.stubEnv('PSModulePath', 'C:\\some\\path');
|
||||
|
||||
const info = getAntigravityInstallInfo();
|
||||
|
||||
expect(info).toEqual({
|
||||
platformName: 'Windows (PowerShell)',
|
||||
installCmd: 'irm https://antigravity.google/cli/install.ps1 | iex',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return Windows CMD installation info on win32 when PSModulePath is not set', () => {
|
||||
Object.defineProperty(process, 'platform', { value: 'win32' });
|
||||
vi.stubEnv('PSModulePath', '');
|
||||
|
||||
const info = getAntigravityInstallInfo();
|
||||
|
||||
expect(info).toEqual({
|
||||
platformName: 'Windows (Command Prompt)',
|
||||
installCmd:
|
||||
'curl -fsSL https://antigravity.google/cli/install.cmd -o install.cmd && install.cmd && del install.cmd',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return null on unsupported platform', () => {
|
||||
Object.defineProperty(process, 'platform', { value: 'freebsd' });
|
||||
|
||||
const info = getAntigravityInstallInfo();
|
||||
|
||||
expect(info).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import process from 'node:process';
|
||||
|
||||
const ANTIGRAVITY_SH_INSTALL =
|
||||
'curl -fsSL https://antigravity.google/cli/install.sh | bash';
|
||||
|
||||
export interface AntigravityInstallInfo {
|
||||
platformName: string;
|
||||
installCmd: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the platform-specific installation details for the Antigravity CLI.
|
||||
* Returns null if the current platform is unsupported.
|
||||
*/
|
||||
export function getAntigravityInstallInfo(): AntigravityInstallInfo | null {
|
||||
if (process.platform === 'win32') {
|
||||
if (process.env['PSModulePath']) {
|
||||
return {
|
||||
platformName: 'Windows (PowerShell)',
|
||||
installCmd: 'irm https://antigravity.google/cli/install.ps1 | iex',
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
platformName: 'Windows (Command Prompt)',
|
||||
installCmd:
|
||||
'curl -fsSL https://antigravity.google/cli/install.cmd -o install.cmd && install.cmd && del install.cmd',
|
||||
};
|
||||
}
|
||||
} else if (process.platform === 'darwin') {
|
||||
return {
|
||||
platformName: 'macOS',
|
||||
installCmd: ANTIGRAVITY_SH_INSTALL,
|
||||
};
|
||||
} else if (process.platform === 'linux') {
|
||||
return {
|
||||
platformName: 'Linux',
|
||||
installCmd: ANTIGRAVITY_SH_INSTALL,
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user