feat: add support for Gemini Enterprise (Discovery Engine) assistant

- Implemented EnterpriseAgentProtocol and EnterpriseAgentSession in core
- Authenticates seamlessly via Application Default Credentials (ADC)
- Added robust brace-counting JSON stream parser with partial chunk caching
- Extracted and rendered immersive docArtifacts (markdown tables) E2E
- Integrated with CLI config schema and enabled default 'all tools' execution
- Added comprehensive unit tests verifying all stream events (thoughts, tools, tables)

TAG=agy
CONV=81e82460-f8cd-4c7b-a037-2cbedda4d3c0
This commit is contained in:
Michael Bleigh
2026-05-18 00:59:55 +00:00
parent 5611ff40e7
commit fc8928c089
10 changed files with 760 additions and 19 deletions
+1
View File
@@ -974,6 +974,7 @@ export async function loadCliConfig(
mcpEnabled,
extensionsEnabled,
agents: settings.agents,
enterprise: settings.enterprise,
adminSkillsEnabled,
allowedMcpServers: mcpEnabled
? (argv.allowedMcpServerNames ?? settings.mcp?.allowed)
+38
View File
@@ -1366,6 +1366,44 @@ const SETTINGS_SCHEMA = {
},
},
},
enterprise: {
type: 'object',
label: 'Gemini Enterprise',
category: 'Advanced',
requiresRestart: true,
default: {},
description: 'Settings for Gemini Enterprise integration.',
showInDialog: false,
properties: {
projectId: {
type: 'string',
label: 'Project ID',
category: 'Advanced',
requiresRestart: true,
default: undefined as string | undefined,
description: 'Google Cloud Project ID for Gemini Enterprise.',
showInDialog: true,
},
engineId: {
type: 'string',
label: 'Engine ID',
category: 'Advanced',
requiresRestart: true,
default: undefined as string | undefined,
description: 'Discovery Engine ID for Gemini Enterprise.',
showInDialog: true,
},
location: {
type: 'string',
label: 'Location',
category: 'Advanced',
requiresRestart: true,
default: 'global',
description: 'Google Cloud Location for Gemini Enterprise.',
showInDialog: true,
},
},
},
context: {
type: 'object',
+12 -8
View File
@@ -507,7 +507,8 @@ export async function main() {
// the sandbox because the sandbox will interfere with the Oauth2 web
// redirect.
let initialAuthFailed = false;
if (!settings.merged.security.auth.useExternal && !argv.isCommand) {
const useEnterprise = process.env['GEMINI_CLI_ENTERPRISE_AGENT'] === 'true';
if (!settings.merged.security.auth.useExternal && !argv.isCommand && !useEnterprise) {
try {
if (
partialConfig.isInteractive() &&
@@ -858,13 +859,16 @@ export async function main() {
),
);
const authType = await validateNonInteractiveAuth(
settings.merged.security.auth.selectedType,
settings.merged.security.auth.useExternal,
config,
settings,
);
await config.refreshAuth(authType);
const useEnterprise = process.env['GEMINI_CLI_ENTERPRISE_AGENT'] === 'true';
if (!useEnterprise) {
const authType = await validateNonInteractiveAuth(
settings.merged.security.auth.selectedType,
settings.merged.security.auth.useExternal,
config,
settings,
);
await config.refreshAuth(authType);
}
if (config.getDebugMode()) {
debugLogger.log('Session ID: %s', sessionId);
+3 -1
View File
@@ -66,7 +66,9 @@ interface RunNonInteractiveParams {
export async function runNonInteractive(
params: RunNonInteractiveParams,
): Promise<void> {
const useAgentSession = params.config.getAgentSessionNoninteractiveEnabled();
const useAgentSession =
params.config.getAgentSessionNoninteractiveEnabled() ||
process.env['GEMINI_CLI_ENTERPRISE_AGENT'] === 'true';
if (useAgentSession) {
debugLogger.debug(
'[ADK] Running non-interactive mode with ADK agent session',
@@ -35,6 +35,7 @@ import {
Scheduler,
ROOT_SCHEDULER_ID,
LegacyAgentSession,
EnterpriseAgentSession,
ToolErrorType,
geminiPartsToContentParts,
displayContentToString,
@@ -295,13 +296,16 @@ export async function runNonInteractive({
});
}
// Create LegacyAgentSession — owns the agentic loop
const session = new LegacyAgentSession({
client: geminiClient,
scheduler,
config,
promptId: prompt_id,
});
const useEnterprise = process.env['GEMINI_CLI_ENTERPRISE_AGENT'] === 'true';
// Create AgentSession — owns the agentic loop
const session = useEnterprise
? new EnterpriseAgentSession({ config, promptId: prompt_id })
: new LegacyAgentSession({
client: geminiClient,
scheduler,
config,
promptId: prompt_id,
});
// Wire Ctrl+C to session abort
abortSession = () => {
+8 -3
View File
@@ -90,6 +90,7 @@ import {
logBillingEvent,
ApiKeyUpdatedEvent,
LegacyAgentProtocol,
EnterpriseAgentProtocol,
type InjectionSource,
} from '@google/gemini-cli-core';
import { validateAuthMethod } from '../config/auth.js';
@@ -1173,10 +1174,14 @@ Logging in with Google... Restarting Gemini CLI to continue.
}, [config]);
const streamAgent = useMemo(
() =>
config?.getAgentSessionInteractiveEnabled()
() => {
if (process.env['GEMINI_CLI_ENTERPRISE_AGENT'] === 'true') {
return new EnterpriseAgentProtocol({ config });
}
return config?.getAgentSessionInteractiveEnabled()
? new LegacyAgentProtocol({ config, getPreferredEditor })
: undefined,
: undefined;
},
[config, getPreferredEditor],
);