Pass whole extensions rather than just context files (#10910)

Co-authored-by: Jake Macdonald <jakemac@google.com>
This commit is contained in:
Zack Birkenbuel
2025-10-20 16:15:23 -07:00
committed by GitHub
parent 995ae717cc
commit cc7e1472f9
35 changed files with 487 additions and 1193 deletions

View File

@@ -40,7 +40,6 @@ import {
} from '@google/gemini-cli-core';
import type { Settings } from './settings.js';
import { annotateActiveExtensions } from './extension.js';
import { getCliVersion } from '../utils/version.js';
import { loadSandboxConfig } from './sandboxConfig.js';
import { resolvePath } from '../utils/resolvePath.js';
@@ -48,7 +47,6 @@ import { appEvents } from '../utils/events.js';
import { isWorkspaceTrusted } from './trustedFolders.js';
import { createPolicyEngineConfig } from './policy.js';
import type { ExtensionEnablementManager } from './extensions/extensionEnablement.js';
export interface CliArgs {
query: string | undefined;
@@ -289,7 +287,7 @@ export async function loadHierarchicalGeminiMemory(
debugMode: boolean,
fileService: FileDiscoveryService,
settings: Settings,
extensionContextFilePaths: string[] = [],
extensions: GeminiCLIExtension[],
folderTrust: boolean,
memoryImportFormat: 'flat' | 'tree' = 'tree',
fileFilteringOptions?: FileFilteringOptions,
@@ -315,7 +313,7 @@ export async function loadHierarchicalGeminiMemory(
includeDirectoriesToReadGemini,
debugMode,
fileService,
extensionContextFilePaths,
extensions,
folderTrust,
memoryImportFormat,
fileFilteringOptions,
@@ -364,8 +362,7 @@ export function isDebugMode(argv: CliArgs): boolean {
export async function loadCliConfig(
settings: Settings,
extensions: GeminiCLIExtension[],
extensionEnablementManager: ExtensionEnablementManager,
allExtensions: GeminiCLIExtension[],
sessionId: string,
argv: CliArgs,
cwd: string = process.cwd(),
@@ -379,16 +376,6 @@ export async function loadCliConfig(
const folderTrust = settings.security?.folderTrust?.enabled ?? false;
const trustedFolder = isWorkspaceTrusted(settings)?.isTrusted ?? true;
const allExtensions = annotateActiveExtensions(
extensions,
cwd,
extensionEnablementManager,
);
const activeExtensions = extensions.filter(
(_, i) => allExtensions[i].isActive,
);
// Set the context filename in the server's memoryTool module BEFORE loading memory
// TODO(b/343434939): This is a bit of a hack. The contextFileName should ideally be passed
// directly to the Config constructor in core, and have core handle setGeminiMdFilename.
@@ -400,10 +387,6 @@ export async function loadCliConfig(
setServerGeminiMdFilename(getCurrentGeminiMdFilename());
}
const extensionContextFilePaths = activeExtensions.flatMap(
(e) => e.contextFiles,
);
const fileService = new FileDiscoveryService(cwd);
const fileFiltering = {
@@ -425,13 +408,13 @@ export async function loadCliConfig(
debugMode,
fileService,
settings,
extensionContextFilePaths,
allExtensions,
trustedFolder,
memoryImportFormat,
fileFiltering,
);
let mcpServers = mergeMcpServers(settings, activeExtensions);
let mcpServers = mergeMcpServers(settings, allExtensions);
const question = argv.promptInteractive || argv.prompt || '';
// Determine approval mode with backward compatibility
@@ -527,7 +510,7 @@ export async function loadCliConfig(
const excludeTools = mergeExcludeTools(
settings,
activeExtensions,
allExtensions,
extraExcludes.length > 0 ? extraExcludes : undefined,
);
const blockedMcpServers: Array<{ name: string; extensionName: string }> = [];
@@ -618,10 +601,10 @@ export async function loadCliConfig(
fileDiscoveryService: fileService,
bugCommand: settings.advanced?.bugCommand,
model: resolvedModel,
extensionContextFilePaths,
maxSessionTurns: settings.model?.maxSessionTurns ?? -1,
experimentalZedIntegration: argv.experimentalAcp || false,
listExtensions: argv.listExtensions || false,
enabledExtensions: argv.extensions,
extensions: allExtensions,
blockedMcpServers,
noBrowser: !!process.env['NO_BROWSER'],
@@ -668,7 +651,7 @@ function allowedMcpServers(
if (!isAllowed) {
blockedMcpServers.push({
name: key,
extensionName: server.extensionName || '',
extensionName: server.extension?.name || '',
});
}
return isAllowed;
@@ -678,7 +661,7 @@ function allowedMcpServers(
blockedMcpServers.push(
...Object.entries(mcpServers).map(([key, server]) => ({
name: key,
extensionName: server.extensionName || '',
extensionName: server.extension?.name || '',
})),
);
mcpServers = {};
@@ -689,6 +672,9 @@ function allowedMcpServers(
function mergeMcpServers(settings: Settings, extensions: GeminiCLIExtension[]) {
const mcpServers = { ...(settings.mcpServers || {}) };
for (const extension of extensions) {
if (!extension.isActive) {
continue;
}
Object.entries(extension.mcpServers || {}).forEach(([key, server]) => {
if (mcpServers[key]) {
debugLogger.warn(
@@ -698,7 +684,7 @@ function mergeMcpServers(settings: Settings, extensions: GeminiCLIExtension[]) {
}
mcpServers[key] = {
...server,
extensionName: extension.name,
extension,
};
});
}
@@ -715,6 +701,9 @@ function mergeExcludeTools(
...(extraExcludes || []),
]);
for (const extension of extensions) {
if (!extension.isActive) {
continue;
}
for (const tool of extension.excludeTools || []) {
allExcludeTools.add(tool);
}