Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 2 additions & 2 deletions packages/cli/src/gemini.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -519,10 +519,10 @@ export async function main() {
adminControlsListner.setConfig(config);

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

// Register config for telemetry shutdown
Expand Down
34 changes: 33 additions & 1 deletion packages/cli/src/ui/AppContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1492,7 +1492,37 @@ Logging in with Google... Restarting Gemini CLI to continue.
}

if (keyMatchers[Command.SHOW_ERROR_DETAILS](key)) {
setShowErrorDetails((prev) => !prev);
if (settings.merged.general.devtools) {
void (async () => {
try {
const { startDevToolsServer } = await import(
'../utils/devtoolsService.js'
);
const { openBrowserSecurely } = await import(
'@google/gemini-cli-core'
);
const url = await startDevToolsServer(config);
try {
await openBrowserSecurely(url);
} catch (e) {
setShowErrorDetails(true);
historyManager.addItem(
{
type: MessageType.INFO,
text: `Failed to open browser. DevTools available at: ${url}`,
},
Date.now(),
);
debugLogger.warn('Failed to open browser securely:', e);
}
} catch (e) {
setShowErrorDetails(true);
debugLogger.error('Failed to start DevTools server:', e);
}
})();
} else {
setShowErrorDetails((prev) => !prev);
}
return true;
} else if (keyMatchers[Command.SUSPEND_APP](key)) {
const undoMessage = isITerm2()
Expand Down Expand Up @@ -1619,6 +1649,8 @@ Logging in with Google... Restarting Gemini CLI to continue.
lastOutputTimeRef,
tabFocusTimeoutRef,
handleWarning,
historyManager,
settings.merged.general.devtools,
],
);

Expand Down
1 change: 1 addition & 0 deletions packages/cli/src/ui/hooks/slashCommandProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,7 @@ export const useSlashCommandProcessor = (
setIsProcessing,
setConfirmationRequest,
setCustomDialog,
setPendingItem,
],
);

Expand Down
61 changes: 61 additions & 0 deletions packages/cli/src/utils/activityLogger.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import { describe, it, expect, beforeEach } from 'vitest';
import { ActivityLogger, type NetworkLog } from './activityLogger.js';
import type { ConsoleLogPayload } from '@google/gemini-cli-core';

describe('ActivityLogger', () => {
let logger: ActivityLogger;

beforeEach(() => {
// Reset singleton instance if necessary or just get it
logger = ActivityLogger.getInstance();
// Manually reset buffers for testing
// @ts-expect-error - accessing private member for test
logger.networkBuffer = [];
// @ts-expect-error - accessing private member for test
logger.consoleBuffer = [];
});

it('buffers only the last 10 network requests', () => {
for (let i = 0; i < 15; i++) {
const log: NetworkLog = {
id: `req-${i}`,
timestamp: i,
method: 'GET',
url: 'http://example.com',
headers: {},
};
// @ts-expect-error - accessing private member for test
logger.safeEmitNetwork(log);
}

const logs = logger.getBufferedLogs();
expect(logs.network.length).toBe(10);
expect(logs.network[0].id).toBe('req-5');
expect(logs.network[9].id).toBe('req-14');
});

it('buffers only the last 10 console logs', () => {
for (let i = 0; i < 15; i++) {
const log: ConsoleLogPayload = { content: `log-${i}`, type: 'log' };
logger.logConsole(log);
}

const logs = logger.getBufferedLogs();
expect(logs.console.length).toBe(10);
expect(logs.console[0].content).toBe('log-5');
expect(logs.console[9].content).toBe('log-14');
});

it('clears buffers after retrieval', () => {
logger.logConsole({ content: 'test', type: 'log' });
logger.getBufferedLogs();
const logs = logger.getBufferedLogs();
expect(logs.console.length).toBe(0);
});
});
Loading
Loading