diff --git a/packages/cli/src/ui/hooks/useSessionResume.ts b/packages/cli/src/ui/hooks/useSessionResume.ts index 055686773bd..d43cba8fecb 100644 --- a/packages/cli/src/ui/hooks/useSessionResume.ts +++ b/packages/cli/src/ui/hooks/useSessionResume.ts @@ -10,6 +10,7 @@ import { type Config, type ResumedSessionData, convertSessionToClientHistory, + uiTelemetryService, } from '@google/gemini-cli-core'; import type { Part } from '@google/genai'; import type { HistoryItemWithoutId } from '../types.js'; @@ -109,6 +110,8 @@ export function useSessionResume({ !hasLoadedResumedSession.current ) { hasLoadedResumedSession.current = true; + // Hydrate telemetry service with the resumed conversation to restore session ID and metrics + uiTelemetryService.hydrate(resumedSessionData.conversation); const historyData = convertSessionToHistoryFormats( resumedSessionData.conversation.messages, ); diff --git a/packages/core/src/config/config.test.ts b/packages/core/src/config/config.test.ts index a43921e1444..f000aea18d3 100644 --- a/packages/core/src/config/config.test.ts +++ b/packages/core/src/config/config.test.ts @@ -71,6 +71,7 @@ import { } from './models.js'; import { Storage } from './storage.js'; import type { AgentLoopContext } from './agent-loop-context.js'; +import type { ShellExecutionConfig } from '../services/shellExecutionService.js'; vi.mock('fs', async (importOriginal) => { const actual = await importOriginal(); @@ -304,6 +305,42 @@ describe('Server Config (config.ts)', () => { }); }); + describe('shell execution config', () => { + it('should preserve existing sandbox and background fields when updated', () => { + const config = new Config({ + ...baseParams, + shellBackgroundCompletionBehavior: 'notify', + }); + + const shellExecutionConfig = config.getShellExecutionConfig(); + + config.setShellExecutionConfig({ + terminalWidth: 123, + terminalHeight: 45, + pager: 'less', + showColor: true, + sanitizationConfig: shellExecutionConfig.sanitizationConfig, + sandboxManager: shellExecutionConfig.sandboxManager, + } as ShellExecutionConfig); + + const updatedShellExecutionConfig = config.getShellExecutionConfig(); + + expect(updatedShellExecutionConfig.terminalWidth).toBe(123); + expect(updatedShellExecutionConfig.terminalHeight).toBe(45); + expect(updatedShellExecutionConfig.pager).toBe('less'); + expect(updatedShellExecutionConfig.showColor).toBe(true); + expect(updatedShellExecutionConfig.sandboxConfig).toMatchObject({ + enabled: true, + command: 'docker', + image: 'gemini-cli-sandbox', + networkAccess: false, + }); + expect(updatedShellExecutionConfig.backgroundCompletionBehavior).toBe( + 'notify', + ); + }); + }); + beforeEach(() => { // Reset mocks if necessary vi.clearAllMocks(); diff --git a/packages/core/src/config/config.ts b/packages/core/src/config/config.ts index 2ef6fc26a8f..9e0ccf85d16 100644 --- a/packages/core/src/config/config.ts +++ b/packages/core/src/config/config.ts @@ -3334,17 +3334,38 @@ export class Config implements McpContext, AgentLoopContext { setShellExecutionConfig(config: ShellExecutionConfig): void { this.shellExecutionConfig = { + ...this.shellExecutionConfig, terminalWidth: config.terminalWidth ?? this.shellExecutionConfig.terminalWidth, terminalHeight: config.terminalHeight ?? this.shellExecutionConfig.terminalHeight, showColor: config.showColor ?? this.shellExecutionConfig.showColor, pager: config.pager ?? this.shellExecutionConfig.pager, + defaultFg: config.defaultFg ?? this.shellExecutionConfig.defaultFg, + defaultBg: config.defaultBg ?? this.shellExecutionConfig.defaultBg, sanitizationConfig: config.sanitizationConfig ?? this.shellExecutionConfig.sanitizationConfig, sandboxManager: config.sandboxManager ?? this.shellExecutionConfig.sandboxManager, + sandboxConfig: + config.sandboxConfig ?? this.shellExecutionConfig.sandboxConfig, + backgroundCompletionBehavior: + config.backgroundCompletionBehavior ?? + this.shellExecutionConfig.backgroundCompletionBehavior, + additionalPermissions: + config.additionalPermissions ?? + this.shellExecutionConfig.additionalPermissions, + disableDynamicLineTrimming: + config.disableDynamicLineTrimming ?? + this.shellExecutionConfig.disableDynamicLineTrimming, + scrollback: config.scrollback ?? this.shellExecutionConfig.scrollback, + maxSerializedLines: + config.maxSerializedLines ?? + this.shellExecutionConfig.maxSerializedLines, + originalCommand: + config.originalCommand ?? this.shellExecutionConfig.originalCommand, + sessionId: config.sessionId ?? this.shellExecutionConfig.sessionId, }; } getScreenReader(): boolean {