Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
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
34 changes: 33 additions & 1 deletion core/src/utils/vertex_ai_utils.ts

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GOOGLE_GENAI_USE_VERTEXAI used all over the code source, please update all the references to use isEnterpriseModeEnabled instead

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — every read of GOOGLE_GENAI_USE_VERTEXAI now goes through isEnterpriseModeEnabled.

I moved the helper out of vertex_ai_utils.ts and exported it from core/src/utils/env_aware_utils.ts, right next to getBooleanEnvVar (this mirrors adk-python, where is_enterprise_mode_enabled and is_env_enabled both live in utils/env_utils.py). Converted call sites:

  • core/src/utils/vertex_ai_utils.tsgetExpressModeApiKey()
  • core/src/utils/variant_utils.tsgetGoogleLlmVariant()
  • core/src/models/google_llm.tsgeminiInitParams(), which ApigeeLlm also routes through

No GOOGLE_GENAI_USE_VERTEXAI read remains outside the helper. You were right that the first revision was incoherent: with only getExpressModeApiKey converted, GOOGLE_GENAI_USE_ENTERPRISE=true returned an express-mode key while getGoogleLlmVariant() still reported GEMINI_API and geminiInitParams() still set vertexai: false.

Two things I did differently than a literal sweep — please push back if you disagree:

  1. The deprecation warning is now emitted once per process. getGoogleLlmVariant() is reached from BaseTool.apiVariant on every request, so warning on each read would print a line per tool per request for everyone still on the legacy variable. Python's warnings.warn(..., DeprecationWarning) is deduplicated by the default filter, so once-per-process is the parity behaviour; it costs one module-level flag, and the helper's tests reload the module (and its logger) per test so the flag cannot leak between them.

  2. I did not touch the two places that write the variabledev/src/cli/cli_create.ts (the .env from adk create) and dev/src/cli/deploy/deploy_utils.ts (ENV GOOGLE_GENAI_USE_VERTEXAI=1 in the generated Dockerfile). They emit rather than read, so they can't use the helper, and renaming what they emit is not backwards compatible: the generated image installs @google/adk-devtools@latest but takes @google/adk from the user's copied package.json/node_modules, so the container can run a core that only understands the old name — and because geminiInitParams forwards the resolved value to the SDK as an explicit vertexai flag, the SDK's own GOOGLE_GENAI_USE_ENTERPRISE support can't cover for it. adk-python does emit the new name from its scaffolding, so I'm happy to follow suit — either in this PR, or as a follow-up once a release that reads the new variable is out, or by emitting both names. Your call.

Tests: new cases per call site in env_aware_utils_test.ts, variant_utils_test.ts, google_llm_test.ts and vertex_ai_utils_test.ts (13 in total, each verified to fail against the unmodified core/src), including warn-once on repeated reads. The four suites that touch these variables now also clear GOOGLE_GENAI_USE_ENTERPRISE in setup — since precedence is by presence, an ambient value of any kind would otherwise flip them.

Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,42 @@
*/

import {getBooleanEnvVar} from './env_aware_utils.js';
import {logger} from './logger.js';

const ENTERPRISE_MODE_ENV_VAR = 'GOOGLE_GENAI_USE_ENTERPRISE';
const DEPRECATED_ENTERPRISE_MODE_ENV_VAR = 'GOOGLE_GENAI_USE_VERTEXAI';

/**
* Returns whether Google GenAI enterprise mode is enabled.
*
* `GOOGLE_GENAI_USE_ENTERPRISE` takes precedence whenever it is set, even when
* it is set to a falsy value. `GOOGLE_GENAI_USE_VERTEXAI` is only consulted
* when `GOOGLE_GENAI_USE_ENTERPRISE` is absent, and using it logs a deprecation
* warning.
*/
function isEnterpriseModeEnabled(): boolean {
if (process.env?.[ENTERPRISE_MODE_ENV_VAR] !== undefined) {
return getBooleanEnvVar(ENTERPRISE_MODE_ENV_VAR);
}

if (process.env?.[DEPRECATED_ENTERPRISE_MODE_ENV_VAR] !== undefined) {
logger.warn(
`${DEPRECATED_ENTERPRISE_MODE_ENV_VAR} is deprecated, please use ` +
`${ENTERPRISE_MODE_ENV_VAR} instead`,
);
return getBooleanEnvVar(DEPRECATED_ENTERPRISE_MODE_ENV_VAR);
}

return false;
}

/**
* Validates and returns the API key for Express Mode.
*
* The key is only returned when enterprise mode is enabled via
* `GOOGLE_GENAI_USE_ENTERPRISE` (or the deprecated
* `GOOGLE_GENAI_USE_VERTEXAI`).
*
* @param project The project id.
* @param location The location.
* @param expressModeApiKey The API key for Express Mode.
Expand All @@ -26,7 +58,7 @@ export function getExpressModeApiKey(
);
}

if (getBooleanEnvVar('GOOGLE_GENAI_USE_VERTEXAI')) {
if (isEnterpriseModeEnabled()) {
return expressModeApiKey || process.env.GOOGLE_API_KEY;
}

Expand Down
56 changes: 52 additions & 4 deletions core/test/utils/vertex_ai_utils_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,34 @@
* SPDX-License-Identifier: Apache-2.0
*/

import {afterEach, beforeEach, describe, expect, it} from 'vitest';
import {
afterEach,
beforeEach,
describe,
expect,
it,
vi,
type MockInstance,
} from 'vitest';
import {logger} from '../../src/utils/logger.js';
import {getExpressModeApiKey} from '../../src/utils/vertex_ai_utils.js';

describe('vertex_ai_utils', () => {
describe('getExpressModeApiKey', () => {
const originalEnv = process.env;
let warnSpy: MockInstance<typeof logger.warn>;

beforeEach(() => {
process.env = {...originalEnv};
delete process.env['GOOGLE_GENAI_USE_ENTERPRISE'];
delete process.env['GOOGLE_GENAI_USE_VERTEXAI'];
delete process.env['GOOGLE_API_KEY'];
warnSpy = vi.spyOn(logger, 'warn').mockImplementation(() => {});
});

afterEach(() => {
process.env = originalEnv;
vi.restoreAllMocks();
});

it('should throw when both project and expressModeApiKey are provided', () => {
Expand All @@ -37,16 +52,19 @@ describe('vertex_ai_utils', () => {
).toThrow();
});

it('should return undefined when GOOGLE_GENAI_USE_VERTEXAI is not set', () => {
delete process.env['GOOGLE_GENAI_USE_VERTEXAI'];
it('should return undefined and not warn when neither enterprise mode variable is set', () => {
process.env['GOOGLE_API_KEY'] = 'env-api-key';
const result = getExpressModeApiKey();
expect(result).toBeUndefined();
expect(warnSpy).not.toHaveBeenCalled();
});

it('should return undefined when GOOGLE_GENAI_USE_VERTEXAI is false', () => {
process.env['GOOGLE_GENAI_USE_VERTEXAI'] = 'false';
process.env['GOOGLE_API_KEY'] = 'env-api-key';
const result = getExpressModeApiKey();
expect(result).toBeUndefined();
expect(warnSpy).toHaveBeenCalledOnce();
});

it('should return expressModeApiKey when GOOGLE_GENAI_USE_VERTEXAI is true', () => {
Expand All @@ -60,13 +78,43 @@ describe('vertex_ai_utils', () => {
process.env['GOOGLE_API_KEY'] = 'env-api-key';
const result = getExpressModeApiKey();
expect(result).toBe('env-api-key');
expect(warnSpy).toHaveBeenCalledOnce();
expect(warnSpy).toHaveBeenCalledWith(
expect.stringContaining(
'GOOGLE_GENAI_USE_VERTEXAI is deprecated, please use ' +
'GOOGLE_GENAI_USE_ENTERPRISE',
),
);
});

it('should return undefined when GOOGLE_GENAI_USE_VERTEXAI is true but no key available', () => {
process.env['GOOGLE_GENAI_USE_VERTEXAI'] = 'true';
delete process.env['GOOGLE_API_KEY'];
const result = getExpressModeApiKey();
expect(result).toBeUndefined();
});

it('should return expressModeApiKey when GOOGLE_GENAI_USE_ENTERPRISE is true', () => {
process.env['GOOGLE_GENAI_USE_ENTERPRISE'] = 'true';
const result = getExpressModeApiKey(undefined, undefined, 'my-api-key');
expect(result).toBe('my-api-key');
});

it('should prefer an enabled GOOGLE_GENAI_USE_ENTERPRISE over GOOGLE_GENAI_USE_VERTEXAI', () => {
process.env['GOOGLE_GENAI_USE_ENTERPRISE'] = 'true';
process.env['GOOGLE_GENAI_USE_VERTEXAI'] = 'false';
process.env['GOOGLE_API_KEY'] = 'env-api-key';
const result = getExpressModeApiKey();
expect(result).toBe('env-api-key');
expect(warnSpy).not.toHaveBeenCalled();
});

it('should not fall back to GOOGLE_GENAI_USE_VERTEXAI when GOOGLE_GENAI_USE_ENTERPRISE is set but disabled', () => {
process.env['GOOGLE_GENAI_USE_ENTERPRISE'] = '';
process.env['GOOGLE_GENAI_USE_VERTEXAI'] = 'true';
process.env['GOOGLE_API_KEY'] = 'env-api-key';
const result = getExpressModeApiKey();
expect(result).toBeUndefined();
expect(warnSpy).not.toHaveBeenCalled();
});
});
});
Loading