fix(cli): resolve devtools build issues and update third-party notices

This commit is contained in:
Alisa Novikova
2026-02-19 16:23:16 -08:00
parent f1c0a695f8
commit 4a599db2bf
45 changed files with 5353 additions and 2960 deletions
+2 -4
View File
@@ -28,8 +28,7 @@ interface FrontmatterBaseAgentDefinition {
display_name?: string;
}
interface FrontmatterLocalAgentDefinition
extends FrontmatterBaseAgentDefinition {
interface FrontmatterLocalAgentDefinition extends FrontmatterBaseAgentDefinition {
kind: 'local';
description: string;
tools?: string[];
@@ -57,8 +56,7 @@ interface FrontmatterAuthConfig {
password?: string;
}
interface FrontmatterRemoteAgentDefinition
extends FrontmatterBaseAgentDefinition {
interface FrontmatterRemoteAgentDefinition extends FrontmatterBaseAgentDefinition {
kind: 'remote';
description?: string;
agent_card_url: string;
+6 -9
View File
@@ -1374,9 +1374,8 @@ describe('oauth2', () => {
});
it('should save credentials using OAuthCredentialStorage during web login', async () => {
const { OAuthCredentialStorage } = await import(
'./oauth-credential-storage.js'
);
const { OAuthCredentialStorage } =
await import('./oauth-credential-storage.js');
const mockAuthUrl = 'https://example.com/auth';
const mockCode = 'test-code';
const mockState = 'test-state';
@@ -1476,9 +1475,8 @@ describe('oauth2', () => {
});
it('should load credentials using OAuthCredentialStorage and not from file', async () => {
const { OAuthCredentialStorage } = await import(
'./oauth-credential-storage.js'
);
const { OAuthCredentialStorage } =
await import('./oauth-credential-storage.js');
const cachedCreds = { refresh_token: 'cached-encrypted-token' };
vi.mocked(OAuthCredentialStorage.loadCredentials).mockResolvedValue(
cachedCreds,
@@ -1514,9 +1512,8 @@ describe('oauth2', () => {
});
it('should clear credentials using OAuthCredentialStorage', async () => {
const { OAuthCredentialStorage } = await import(
'./oauth-credential-storage.js'
);
const { OAuthCredentialStorage } =
await import('./oauth-credential-storage.js');
// Create a dummy unencrypted credential file. It should not be deleted.
const credsPath = path.join(tempHomeDir, GEMINI_DIR, 'oauth_creds.json');
+4 -6
View File
@@ -304,9 +304,8 @@ describe('Server Config (config.ts)', () => {
// interactive defaults to false
});
const { McpClientManager } = await import(
'../tools/mcp-client-manager.js'
);
const { McpClientManager } =
await import('../tools/mcp-client-manager.js');
let mcpStarted = false;
vi.mocked(McpClientManager).mockImplementation(
@@ -333,9 +332,8 @@ describe('Server Config (config.ts)', () => {
interactive: true,
});
const { McpClientManager } = await import(
'../tools/mcp-client-manager.js'
);
const { McpClientManager } =
await import('../tools/mcp-client-manager.js');
let mcpStarted = false;
let resolveMcp: (value: unknown) => void;
const mcpPromise = new Promise((resolve) => {
+2 -3
View File
@@ -1636,9 +1636,8 @@ export class Config {
if (this.experimentalJitContext && this.contextManager) {
await this.contextManager.refresh();
} else {
const { refreshServerHierarchicalMemory } = await import(
'../utils/memoryDiscovery.js'
);
const { refreshServerHierarchicalMemory } =
await import('../utils/memoryDiscovery.js');
await refreshServerHierarchicalMemory(this);
}
if (this.geminiClient?.isInitialized()) {
+12 -18
View File
@@ -1159,9 +1159,8 @@ ${JSON.stringify(
true,
);
// Get the mocked checkNextSpeaker function and configure it to trigger infinite loop
const { checkNextSpeaker } = await import(
'../utils/nextSpeakerChecker.js'
);
const { checkNextSpeaker } =
await import('../utils/nextSpeakerChecker.js');
const mockCheckNextSpeaker = vi.mocked(checkNextSpeaker);
mockCheckNextSpeaker.mockResolvedValue({
next_speaker: 'model',
@@ -1283,9 +1282,8 @@ ${JSON.stringify(
// someone tries to bypass it by calling with a very large turns value
// Get the mocked checkNextSpeaker function and configure it to trigger infinite loop
const { checkNextSpeaker } = await import(
'../utils/nextSpeakerChecker.js'
);
const { checkNextSpeaker } =
await import('../utils/nextSpeakerChecker.js');
const mockCheckNextSpeaker = vi.mocked(checkNextSpeaker);
mockCheckNextSpeaker.mockResolvedValue({
next_speaker: 'model',
@@ -2791,9 +2789,8 @@ ${JSON.stringify(
it('should not call checkNextSpeaker when turn.run() yields an error', async () => {
// Arrange
const { checkNextSpeaker } = await import(
'../utils/nextSpeakerChecker.js'
);
const { checkNextSpeaker } =
await import('../utils/nextSpeakerChecker.js');
const mockCheckNextSpeaker = vi.mocked(checkNextSpeaker);
const mockStream = (async function* () {
@@ -2828,9 +2825,8 @@ ${JSON.stringify(
it('should not call checkNextSpeaker when turn.run() yields a value then an error', async () => {
// Arrange
const { checkNextSpeaker } = await import(
'../utils/nextSpeakerChecker.js'
);
const { checkNextSpeaker } =
await import('../utils/nextSpeakerChecker.js');
const mockCheckNextSpeaker = vi.mocked(checkNextSpeaker);
const mockStream = (async function* () {
@@ -2995,9 +2991,8 @@ ${JSON.stringify(
});
it('should fire BeforeAgent once and AfterAgent once even with recursion', async () => {
const { checkNextSpeaker } = await import(
'../utils/nextSpeakerChecker.js'
);
const { checkNextSpeaker } =
await import('../utils/nextSpeakerChecker.js');
vi.mocked(checkNextSpeaker)
.mockResolvedValueOnce({ next_speaker: 'model', reasoning: 'more' })
.mockResolvedValueOnce(null);
@@ -3035,9 +3030,8 @@ ${JSON.stringify(
});
it('should use original request in AfterAgent hook even when continuation happened', async () => {
const { checkNextSpeaker } = await import(
'../utils/nextSpeakerChecker.js'
);
const { checkNextSpeaker } =
await import('../utils/nextSpeakerChecker.js');
vi.mocked(checkNextSpeaker)
.mockResolvedValueOnce({ next_speaker: 'model', reasoning: 'more' })
.mockResolvedValueOnce(null);
@@ -27,9 +27,8 @@ export class HybridTokenStorage extends BaseTokenStorage {
if (!forceFileStorage) {
try {
const { KeychainTokenStorage } = await import(
'./keychain-token-storage.js'
);
const { KeychainTokenStorage } =
await import('./keychain-token-storage.js');
const keychainStorage = new KeychainTokenStorage(this.serviceName);
const isAvailable = await keychainStorage.isAvailable();
@@ -49,9 +49,8 @@ describe('KeychainTokenStorage', () => {
vi.resetAllMocks();
// Reset the internal state of the keychain-token-storage module
vi.resetModules();
const { KeychainTokenStorage } = await import(
'./keychain-token-storage.js'
);
const { KeychainTokenStorage } =
await import('./keychain-token-storage.js');
storage = new KeychainTokenStorage(mockServiceName);
});
+6 -9
View File
@@ -497,9 +497,8 @@ describe('createPolicyEngineConfig', () => {
stat: mockStat,
}));
vi.resetModules();
const { createPolicyEngineConfig: createConfig } = await import(
'./config.js'
);
const { createPolicyEngineConfig: createConfig } =
await import('./config.js');
const config = await createConfig(
settings,
@@ -580,9 +579,8 @@ describe('createPolicyEngineConfig', () => {
it('should have YOLO allow-all rule beat write tool rules in YOLO mode', async () => {
vi.resetModules();
vi.doUnmock('node:fs/promises');
const { createPolicyEngineConfig: createConfig } = await import(
'./config.js'
);
const { createPolicyEngineConfig: createConfig } =
await import('./config.js');
// Re-mock Storage after resetModules because it was reloaded
const { Storage: FreshStorage } = await import('../config/storage.js');
vi.spyOn(FreshStorage, 'getUserPoliciesDir').mockReturnValue(
@@ -988,9 +986,8 @@ name = "invalid-name"
it('should have default ASK_USER rule for discovered tools', async () => {
vi.resetModules();
vi.doUnmock('node:fs/promises');
const { createPolicyEngineConfig: createConfig } = await import(
'./config.js'
);
const { createPolicyEngineConfig: createConfig } =
await import('./config.js');
// Re-mock Storage after resetModules because it was reloaded
const { Storage: FreshStorage } = await import('../config/storage.js');
vi.spyOn(FreshStorage, 'getUserPoliciesDir').mockReturnValue(
@@ -66,9 +66,8 @@ describe('sessionSummaryUtils', () => {
mockGenerateSummary = vi.fn().mockResolvedValue('Add dark mode to the app');
// Import the mocked module to access the constructor
const { SessionSummaryService } = await import(
'./sessionSummaryService.js'
);
const { SessionSummaryService } =
await import('./sessionSummaryService.js');
(
SessionSummaryService as unknown as ReturnType<typeof vi.fn>
).mockImplementation(() => ({
@@ -1475,9 +1475,8 @@ describe('ShellExecutionService environment variables', () => {
vi.stubEnv('GEMINI_CLI_TEST_VAR', 'test-value'); // A test var that should be kept
vi.resetModules();
const { ShellExecutionService } = await import(
'./shellExecutionService.js'
);
const { ShellExecutionService } =
await import('./shellExecutionService.js');
// Test pty path
await ShellExecutionService.execute(
@@ -1534,9 +1533,8 @@ describe('ShellExecutionService environment variables', () => {
vi.stubEnv('GEMINI_CLI_TEST_VAR', 'test-value'); // A test var that should be kept
vi.resetModules();
const { ShellExecutionService } = await import(
'./shellExecutionService.js'
);
const { ShellExecutionService } =
await import('./shellExecutionService.js');
// Test pty path
await ShellExecutionService.execute(
@@ -1590,9 +1588,8 @@ describe('ShellExecutionService environment variables', () => {
vi.stubEnv('GITHUB_SHA', '');
vi.stubEnv('SURFACE', '');
vi.resetModules();
const { ShellExecutionService } = await import(
'./shellExecutionService.js'
);
const { ShellExecutionService } =
await import('./shellExecutionService.js');
// Test pty path
await ShellExecutionService.execute(
+3 -2
View File
@@ -22,8 +22,9 @@ import { debugLogger } from '../utils/debugLogger.js';
/**
* A declarative tool that supports a modify operation.
*/
export interface ModifiableDeclarativeTool<TParams extends object>
extends DeclarativeTool<TParams, ToolResult> {
export interface ModifiableDeclarativeTool<
TParams extends object,
> extends DeclarativeTool<TParams, ToolResult> {
getModifyContext(abortSignal: AbortSignal): ModifyContext<TParams>;
}
+2 -4
View File
@@ -83,8 +83,7 @@ export interface PolicyUpdateOptions {
export abstract class BaseToolInvocation<
TParams extends object,
TResult extends ToolResult,
> implements ToolInvocation<TParams, TResult>
{
> implements ToolInvocation<TParams, TResult> {
constructor(
readonly params: TParams,
protected readonly messageBus: MessageBus,
@@ -353,8 +352,7 @@ export interface ToolBuilder<
export abstract class DeclarativeTool<
TParams extends object,
TResult extends ToolResult,
> implements ToolBuilder<TParams, TResult>
{
> implements ToolBuilder<TParams, TResult> {
constructor(
readonly name: string,
readonly displayName: string,
+2 -1
View File
@@ -916,7 +916,8 @@ describe('WriteFileTool', () => {
const content = 'test content';
let existsSyncSpy: // eslint-disable-next-line @typescript-eslint/no-explicit-any
ReturnType<typeof vi.spyOn<any, 'existsSync'>> | undefined = undefined;
ReturnType<typeof vi.spyOn<any, 'existsSync'>> | undefined =
undefined;
try {
if (mockFsExistsSync) {