From dfec94869b7fab7201f567bf790c160eddcb7114 Mon Sep 17 00:00:00 2001 From: Dev Randalpura Date: Fri, 8 May 2026 12:55:51 -0400 Subject: [PATCH] fix(ui): added quotes around session id in resume tip (#26669) --- .../components/SessionSummaryDisplay.test.tsx | 17 +++++++++++------ .../src/ui/components/SessionSummaryDisplay.tsx | 16 +++++++++++++--- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/packages/cli/src/ui/components/SessionSummaryDisplay.test.tsx b/packages/cli/src/ui/components/SessionSummaryDisplay.test.tsx index 3902f918f7..9de9e1385b 100644 --- a/packages/cli/src/ui/components/SessionSummaryDisplay.test.tsx +++ b/packages/cli/src/ui/components/SessionSummaryDisplay.test.tsx @@ -13,6 +13,7 @@ import { type SessionMetrics } from '../contexts/SessionContext.js'; import { ToolCallDecision, getShellConfiguration, + isWindows, type WorktreeSettings, } from '@google/gemini-cli-core'; @@ -22,6 +23,7 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => { return { ...actual, getShellConfiguration: vi.fn(), + isWindows: vi.fn(), }; }); @@ -44,6 +46,7 @@ vi.mock('../contexts/ConfigContext.js', async (importOriginal) => { }); const getShellConfigurationMock = vi.mocked(getShellConfiguration); +const isWindowsMock = vi.mocked(isWindows); const useSessionStatsMock = vi.mocked(SessionContext.useSessionStats); const renderWithMockedStats = async ( @@ -106,6 +109,7 @@ describe('', () => { argsPrefix: ['-c'], shell: 'bash', }); + isWindowsMock.mockReturnValue(false); }); it('renders the summary display with a title', async () => { @@ -149,7 +153,7 @@ describe('', () => { ); const output = lastFrame(); - // Standard UUID characters should not be escaped/quoted by default for bash. + // Standard UUID characters are NOT wrapped in double quotes on non-Windows. expect(output).toContain('gemini --resume 1234-abcd-5678-efgh'); unmount(); }); @@ -167,7 +171,8 @@ describe('', () => { unmount(); }); - it('renders a standard UUID-formatted session ID in the footer (powershell)', async () => { + it('renders a standard UUID-formatted session ID in the footer (powershell) on Windows', async () => { + isWindowsMock.mockReturnValue(true); getShellConfigurationMock.mockReturnValue({ executable: 'powershell.exe', argsPrefix: ['-NoProfile', '-Command'], @@ -181,9 +186,8 @@ describe('', () => { ); const output = lastFrame(); - // PowerShell doesn't wraps UUID in single quotes because - // it contains no special characters. - expect(output).toContain('gemini --resume 1234-abcd-5678-efgh'); + // PowerShell doesn't wrap UUID in quotes by default, but we wrap it in double quotes on Windows. + expect(output).toContain('gemini --resume "1234-abcd-5678-efgh"'); unmount(); }); @@ -201,7 +205,8 @@ describe('', () => { ); const output = lastFrame(); - // PowerShell wraps in single quotes and escapes internal single quotes by doubling them + // PowerShell wraps in single quotes and escapes internal single quotes by doubling them. + // Since it's already quoted, we don't add redundant double quotes. expect(output).toContain("gemini --resume '''; rm -rf / #'"); unmount(); }); diff --git a/packages/cli/src/ui/components/SessionSummaryDisplay.tsx b/packages/cli/src/ui/components/SessionSummaryDisplay.tsx index 7313949a9c..55ef50c746 100644 --- a/packages/cli/src/ui/components/SessionSummaryDisplay.tsx +++ b/packages/cli/src/ui/components/SessionSummaryDisplay.tsx @@ -8,7 +8,11 @@ import type React from 'react'; import { StatsDisplay } from './StatsDisplay.js'; import { useSessionStats } from '../contexts/SessionContext.js'; import { useConfig } from '../contexts/ConfigContext.js'; -import { escapeShellArg, getShellConfiguration } from '@google/gemini-cli-core'; +import { + escapeShellArg, + getShellConfiguration, + isWindows, +} from '@google/gemini-cli-core'; interface SessionSummaryDisplayProps { duration: string; @@ -24,11 +28,17 @@ export const SessionSummaryDisplay: React.FC = ({ const worktreeSettings = config.getWorktreeSettings(); const escapedSessionId = escapeShellArg(stats.sessionId, shell); - let footer = `To resume this session: gemini --resume ${escapedSessionId}`; + const footerSessionId = + isWindows() && + !escapedSessionId.startsWith('"') && + !escapedSessionId.startsWith("'") + ? `"${escapedSessionId}"` + : escapedSessionId; + let footer = `To resume this session: gemini --resume ${footerSessionId}`; if (worktreeSettings) { footer = - `To resume work in this worktree: cd ${escapeShellArg(worktreeSettings.path, shell)} && gemini --resume ${escapedSessionId}\n` + + `To resume work in this worktree: cd ${escapeShellArg(worktreeSettings.path, shell)} && gemini --resume ${footerSessionId}\n` + `To remove manually: git worktree remove ${escapeShellArg(worktreeSettings.path, shell)}`; }