diff options
| author | Richie Foreman <[email protected]> | 2025-08-17 12:43:21 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-08-17 16:43:21 +0000 |
| commit | 2998f27f703282359f6389d1c2d8758fc6a14955 (patch) | |
| tree | a7e3ff7f969c44e61ab27240cdd615e291b6deae /packages/core/src | |
| parent | ec1fa954d18ec9abab3ce669536dd24559a499f1 (diff) | |
chore(compiler): Enable strict property access TS compiler flag. (#6255)
Co-authored-by: Jacob Richman <[email protected]>
Diffstat (limited to 'packages/core/src')
30 files changed, 175 insertions, 161 deletions
diff --git a/packages/core/src/code_assist/oauth2.test.ts b/packages/core/src/code_assist/oauth2.test.ts index 77a8fb90..821788d5 100644 --- a/packages/core/src/code_assist/oauth2.test.ts +++ b/packages/core/src/code_assist/oauth2.test.ts @@ -57,9 +57,7 @@ describe('oauth2', () => { fs.rmSync(tempHomeDir, { recursive: true, force: true }); vi.clearAllMocks(); resetOauthClientForTesting(); - delete process.env.CLOUD_SHELL; - delete process.env.GOOGLE_GENAI_USE_GCA; - delete process.env.GOOGLE_CLOUD_ACCESS_TOKEN; + vi.unstubAllEnvs(); }); it('should perform a web login', async () => { @@ -328,8 +326,8 @@ describe('oauth2', () => { describe('with GCP environment variables', () => { it('should use GOOGLE_CLOUD_ACCESS_TOKEN when GOOGLE_GENAI_USE_GCA is true', async () => { - process.env.GOOGLE_GENAI_USE_GCA = 'true'; - process.env.GOOGLE_CLOUD_ACCESS_TOKEN = 'gcp-access-token'; + vi.stubEnv('GOOGLE_GENAI_USE_GCA', 'true'); + vi.stubEnv('GOOGLE_CLOUD_ACCESS_TOKEN', 'gcp-access-token'); const mockSetCredentials = vi.fn(); const mockGetAccessToken = vi @@ -387,7 +385,7 @@ describe('oauth2', () => { }); it('should not use GCP token if GOOGLE_CLOUD_ACCESS_TOKEN is not set', async () => { - process.env.GOOGLE_GENAI_USE_GCA = 'true'; + vi.stubEnv('GOOGLE_GENAI_USE_GCA', 'true'); const mockSetCredentials = vi.fn(); const mockGetAccessToken = vi @@ -418,7 +416,7 @@ describe('oauth2', () => { }); it('should not use GCP token if GOOGLE_GENAI_USE_GCA is not set', async () => { - process.env.GOOGLE_CLOUD_ACCESS_TOKEN = 'gcp-access-token'; + vi.stubEnv('GOOGLE_CLOUD_ACCESS_TOKEN', 'gcp-access-token'); const mockSetCredentials = vi.fn(); const mockGetAccessToken = vi diff --git a/packages/core/src/code_assist/oauth2.ts b/packages/core/src/code_assist/oauth2.ts index f9518cbe..a4dcf8a7 100644 --- a/packages/core/src/code_assist/oauth2.ts +++ b/packages/core/src/code_assist/oauth2.ts @@ -81,11 +81,11 @@ async function initOauthClient( }); if ( - process.env.GOOGLE_GENAI_USE_GCA && - process.env.GOOGLE_CLOUD_ACCESS_TOKEN + process.env['GOOGLE_GENAI_USE_GCA'] && + process.env['GOOGLE_CLOUD_ACCESS_TOKEN'] ) { client.setCredentials({ - access_token: process.env.GOOGLE_CLOUD_ACCESS_TOKEN, + access_token: process.env['GOOGLE_CLOUD_ACCESS_TOKEN'], }); await fetchAndCacheUserInfo(client); return client; @@ -248,7 +248,7 @@ async function authWithUserCode(client: OAuth2Client): Promise<boolean> { async function authWithWeb(client: OAuth2Client): Promise<OauthWebLogin> { const port = await getAvailablePort(); // The hostname used for the HTTP server binding (e.g., '0.0.0.0' in Docker). - const host = process.env.OAUTH_CALLBACK_HOST || 'localhost'; + const host = process.env['OAUTH_CALLBACK_HOST'] || 'localhost'; // The `redirectUri` sent to Google's authorization server MUST use a loopback IP literal // (i.e., 'localhost' or '127.0.0.1'). This is a strict security policy for credentials of // type 'Desktop app' or 'Web application' (when using loopback flow) to mitigate @@ -323,7 +323,7 @@ export function getAvailablePort(): Promise<number> { return new Promise((resolve, reject) => { let port = 0; try { - const portStr = process.env.OAUTH_CALLBACK_PORT; + const portStr = process.env['OAUTH_CALLBACK_PORT']; if (portStr) { port = parseInt(portStr, 10); if (isNaN(port) || port <= 0 || port > 65535) { @@ -353,7 +353,8 @@ export function getAvailablePort(): Promise<number> { async function loadCachedCredentials(client: OAuth2Client): Promise<boolean> { try { const keyFile = - process.env.GOOGLE_APPLICATION_CREDENTIALS || getCachedCredentialPath(); + process.env['GOOGLE_APPLICATION_CREDENTIALS'] || + getCachedCredentialPath(); const creds = await fs.readFile(keyFile, 'utf-8'); client.setCredentials(JSON.parse(creds)); diff --git a/packages/core/src/code_assist/server.ts b/packages/core/src/code_assist/server.ts index 08339bdc..470143a6 100644 --- a/packages/core/src/code_assist/server.ts +++ b/packages/core/src/code_assist/server.ts @@ -214,7 +214,8 @@ export class CodeAssistServer implements ContentGenerator { } getMethodUrl(method: string): string { - const endpoint = process.env.CODE_ASSIST_ENDPOINT ?? CODE_ASSIST_ENDPOINT; + const endpoint = + process.env['CODE_ASSIST_ENDPOINT'] ?? CODE_ASSIST_ENDPOINT; return `${endpoint}/${CODE_ASSIST_API_VERSION}:${method}`; } } diff --git a/packages/core/src/code_assist/setup.test.ts b/packages/core/src/code_assist/setup.test.ts index cba051dd..61a7431a 100644 --- a/packages/core/src/code_assist/setup.test.ts +++ b/packages/core/src/code_assist/setup.test.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { setupUser, ProjectIdRequiredError } from './setup.js'; import { CodeAssistServer } from '../code_assist/server.js'; import { OAuth2Client } from 'google-auth-library'; @@ -50,8 +50,12 @@ describe('setupUser for existing user', () => { ); }); + afterEach(() => { + vi.unstubAllEnvs(); + }); + it('should use GOOGLE_CLOUD_PROJECT when set and project from server is undefined', async () => { - process.env.GOOGLE_CLOUD_PROJECT = 'test-project'; + vi.stubEnv('GOOGLE_CLOUD_PROJECT', 'test-project'); mockLoad.mockResolvedValue({ currentTier: mockPaidTier, }); @@ -66,7 +70,7 @@ describe('setupUser for existing user', () => { }); it('should ignore GOOGLE_CLOUD_PROJECT when project from server is set', async () => { - process.env.GOOGLE_CLOUD_PROJECT = 'test-project'; + vi.stubEnv('GOOGLE_CLOUD_PROJECT', 'test-project'); mockLoad.mockResolvedValue({ cloudaicompanionProject: 'server-project', currentTier: mockPaidTier, @@ -86,7 +90,7 @@ describe('setupUser for existing user', () => { }); it('should throw ProjectIdRequiredError when no project ID is available', async () => { - delete process.env.GOOGLE_CLOUD_PROJECT; + vi.stubEnv('GOOGLE_CLOUD_PROJECT', ''); // And the server itself requires a project ID internally vi.mocked(CodeAssistServer).mockImplementation(() => { throw new ProjectIdRequiredError(); @@ -122,8 +126,12 @@ describe('setupUser for new user', () => { ); }); + afterEach(() => { + vi.unstubAllEnvs(); + }); + it('should use GOOGLE_CLOUD_PROJECT when set and onboard a new paid user', async () => { - process.env.GOOGLE_CLOUD_PROJECT = 'test-project'; + vi.stubEnv('GOOGLE_CLOUD_PROJECT', 'test-project'); mockLoad.mockResolvedValue({ allowedTiers: [mockPaidTier], }); @@ -153,7 +161,7 @@ describe('setupUser for new user', () => { }); it('should onboard a new free user when GOOGLE_CLOUD_PROJECT is not set', async () => { - delete process.env.GOOGLE_CLOUD_PROJECT; + vi.stubEnv('GOOGLE_CLOUD_PROJECT', ''); mockLoad.mockResolvedValue({ allowedTiers: [mockFreeTier], }); @@ -182,7 +190,7 @@ describe('setupUser for new user', () => { }); it('should use GOOGLE_CLOUD_PROJECT when onboard response has no project ID', async () => { - process.env.GOOGLE_CLOUD_PROJECT = 'test-project'; + vi.stubEnv('GOOGLE_CLOUD_PROJECT', 'test-project'); mockLoad.mockResolvedValue({ allowedTiers: [mockPaidTier], }); @@ -200,7 +208,7 @@ describe('setupUser for new user', () => { }); it('should throw ProjectIdRequiredError when no project ID is available', async () => { - delete process.env.GOOGLE_CLOUD_PROJECT; + vi.stubEnv('GOOGLE_CLOUD_PROJECT', ''); mockLoad.mockResolvedValue({ allowedTiers: [mockPaidTier], }); diff --git a/packages/core/src/code_assist/setup.ts b/packages/core/src/code_assist/setup.ts index 2e460c98..d563301d 100644 --- a/packages/core/src/code_assist/setup.ts +++ b/packages/core/src/code_assist/setup.ts @@ -33,7 +33,7 @@ export interface UserData { * @returns the user's actual project id */ export async function setupUser(client: OAuth2Client): Promise<UserData> { - const projectId = process.env.GOOGLE_CLOUD_PROJECT || undefined; + const projectId = process.env['GOOGLE_CLOUD_PROJECT'] || undefined; const caServer = new CodeAssistServer(client, projectId, {}, '', undefined); const coreClientMetadata: ClientMetadata = { ideType: 'IDE_UNSPECIFIED', diff --git a/packages/core/src/config/config.ts b/packages/core/src/config/config.ts index 49f9ab45..acaf5eb1 100644 --- a/packages/core/src/config/config.ts +++ b/packages/core/src/config/config.ts @@ -458,7 +458,7 @@ export class Config { isRestrictiveSandbox(): boolean { const sandboxConfig = this.getSandbox(); - const seatbeltProfile = process.env.SEATBELT_PROFILE; + const seatbeltProfile = process.env['SEATBELT_PROFILE']; return ( !!sandboxConfig && sandboxConfig.command === 'sandbox-exec' && diff --git a/packages/core/src/core/client.ts b/packages/core/src/core/client.ts index a2abd0d0..66f3e08f 100644 --- a/packages/core/src/core/client.ts +++ b/packages/core/src/core/client.ts @@ -286,7 +286,7 @@ export class GeminiClient { const contextData: Record<string, unknown> = {}; if (activeFile) { - contextData.activeFile = { + contextData['activeFile'] = { path: activeFile.path, cursor: activeFile.cursor ? { @@ -299,7 +299,7 @@ export class GeminiClient { } if (otherOpenFiles.length > 0) { - contextData.otherOpenFiles = otherOpenFiles; + contextData['otherOpenFiles'] = otherOpenFiles; } if (Object.keys(contextData).length === 0) { @@ -345,7 +345,7 @@ export class GeminiClient { } } if (openedFiles.length > 0) { - changes.filesOpened = openedFiles; + changes['filesOpened'] = openedFiles; } const closedFiles: string[] = []; @@ -355,7 +355,7 @@ export class GeminiClient { } } if (closedFiles.length > 0) { - changes.filesClosed = closedFiles; + changes['filesClosed'] = closedFiles; } const lastActiveFile = ( @@ -367,7 +367,7 @@ export class GeminiClient { if (currentActiveFile) { if (!lastActiveFile || lastActiveFile.path !== currentActiveFile.path) { - changes.activeFileChanged = { + changes['activeFileChanged'] = { path: currentActiveFile.path, cursor: currentActiveFile.cursor ? { @@ -386,7 +386,7 @@ export class GeminiClient { lastCursor.line !== currentCursor.line || lastCursor.character !== currentCursor.character) ) { - changes.cursorMoved = { + changes['cursorMoved'] = { path: currentActiveFile.path, cursor: { line: currentCursor.line, @@ -398,14 +398,14 @@ export class GeminiClient { const lastSelectedText = lastActiveFile.selectedText || ''; const currentSelectedText = currentActiveFile.selectedText || ''; if (lastSelectedText !== currentSelectedText) { - changes.selectionChanged = { + changes['selectionChanged'] = { path: currentActiveFile.path, selectedText: currentSelectedText, }; } } } else if (lastActiveFile) { - changes.activeFileChanged = { + changes['activeFileChanged'] = { path: null, previousPath: lastActiveFile.path, }; @@ -415,7 +415,7 @@ export class GeminiClient { return { contextParts: [], newIdeContext: currentIdeContext }; } - delta.changes = changes; + delta['changes'] = changes; const jsonString = JSON.stringify(delta, null, 2); const contextParts = [ "Here is a summary of changes in the user's editor context, in JSON format. This is for your information only.", diff --git a/packages/core/src/core/contentGenerator.test.ts b/packages/core/src/core/contentGenerator.test.ts index e89b5bc7..b92e8046 100644 --- a/packages/core/src/core/contentGenerator.test.ts +++ b/packages/core/src/core/contentGenerator.test.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { describe, it, expect, vi, beforeEach, afterAll } from 'vitest'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { createContentGenerator, AuthType, @@ -72,7 +72,6 @@ describe('createContentGenerator', () => { }); describe('createContentGeneratorConfig', () => { - const originalEnv = process.env; const mockConfig = { getModel: vi.fn().mockReturnValue('gemini-pro'), setModel: vi.fn(), @@ -83,18 +82,15 @@ describe('createContentGeneratorConfig', () => { beforeEach(() => { // Reset modules to re-evaluate imports and environment variables vi.resetModules(); - // Restore process.env before each test - process.env = { ...originalEnv }; vi.clearAllMocks(); }); - afterAll(() => { - // Restore original process.env after all tests - process.env = originalEnv; + afterEach(() => { + vi.unstubAllEnvs(); }); it('should configure for Gemini using GEMINI_API_KEY when set', async () => { - process.env.GEMINI_API_KEY = 'env-gemini-key'; + vi.stubEnv('GEMINI_API_KEY', 'env-gemini-key'); const config = await createContentGeneratorConfig( mockConfig, AuthType.USE_GEMINI, @@ -104,7 +100,7 @@ describe('createContentGeneratorConfig', () => { }); it('should not configure for Gemini if GEMINI_API_KEY is empty', async () => { - process.env.GEMINI_API_KEY = ''; + vi.stubEnv('GEMINI_API_KEY', ''); const config = await createContentGeneratorConfig( mockConfig, AuthType.USE_GEMINI, @@ -114,7 +110,7 @@ describe('createContentGeneratorConfig', () => { }); it('should configure for Vertex AI using GOOGLE_API_KEY when set', async () => { - process.env.GOOGLE_API_KEY = 'env-google-key'; + vi.stubEnv('GOOGLE_API_KEY', 'env-google-key'); const config = await createContentGeneratorConfig( mockConfig, AuthType.USE_VERTEX_AI, @@ -124,8 +120,8 @@ describe('createContentGeneratorConfig', () => { }); it('should configure for Vertex AI using GCP project and location when set', async () => { - process.env.GOOGLE_CLOUD_PROJECT = 'env-gcp-project'; - process.env.GOOGLE_CLOUD_LOCATION = 'env-gcp-location'; + vi.stubEnv('GOOGLE_CLOUD_PROJECT', 'env-gcp-project'); + vi.stubEnv('GOOGLE_CLOUD_LOCATION', 'env-gcp-location'); const config = await createContentGeneratorConfig( mockConfig, AuthType.USE_VERTEX_AI, @@ -135,9 +131,9 @@ describe('createContentGeneratorConfig', () => { }); it('should not configure for Vertex AI if required env vars are empty', async () => { - process.env.GOOGLE_API_KEY = ''; - process.env.GOOGLE_CLOUD_PROJECT = ''; - process.env.GOOGLE_CLOUD_LOCATION = ''; + vi.stubEnv('GOOGLE_API_KEY', ''); + vi.stubEnv('GOOGLE_CLOUD_PROJECT', ''); + vi.stubEnv('GOOGLE_CLOUD_LOCATION', ''); const config = await createContentGeneratorConfig( mockConfig, AuthType.USE_VERTEX_AI, diff --git a/packages/core/src/core/contentGenerator.ts b/packages/core/src/core/contentGenerator.ts index 599a569b..19b285c7 100644 --- a/packages/core/src/core/contentGenerator.ts +++ b/packages/core/src/core/contentGenerator.ts @@ -60,10 +60,10 @@ export function createContentGeneratorConfig( config: Config, authType: AuthType | undefined, ): ContentGeneratorConfig { - const geminiApiKey = process.env.GEMINI_API_KEY || undefined; - const googleApiKey = process.env.GOOGLE_API_KEY || undefined; - const googleCloudProject = process.env.GOOGLE_CLOUD_PROJECT || undefined; - const googleCloudLocation = process.env.GOOGLE_CLOUD_LOCATION || undefined; + const geminiApiKey = process.env['GEMINI_API_KEY'] || undefined; + const googleApiKey = process.env['GOOGLE_API_KEY'] || undefined; + const googleCloudProject = process.env['GOOGLE_CLOUD_PROJECT'] || undefined; + const googleCloudLocation = process.env['GOOGLE_CLOUD_LOCATION'] || undefined; // Use runtime model from config if available; otherwise, fall back to parameter or default const effectiveModel = config.getModel() || DEFAULT_GEMINI_MODEL; @@ -107,7 +107,7 @@ export async function createContentGenerator( gcConfig: Config, sessionId?: string, ): Promise<ContentGenerator> { - const version = process.env.CLI_VERSION || process.version; + const version = process.env['CLI_VERSION'] || process.version; const httpOptions = { headers: { 'User-Agent': `GeminiCLI/${version} (${process.platform}; ${process.arch})`, diff --git a/packages/core/src/core/coreToolScheduler.ts b/packages/core/src/core/coreToolScheduler.ts index 0d442f9d..1a031de5 100644 --- a/packages/core/src/core/coreToolScheduler.ts +++ b/packages/core/src/core/coreToolScheduler.ts @@ -171,10 +171,10 @@ export function convertToFunctionResponse( // After this point, contentToProcess is a single Part object. if (contentToProcess.functionResponse) { - if (contentToProcess.functionResponse.response?.content) { + if (contentToProcess.functionResponse.response?.['content']) { const stringifiedOutput = getResponseTextFromParts( - contentToProcess.functionResponse.response.content as Part[], + contentToProcess.functionResponse.response['content'] as Part[], ) || ''; return createFunctionResponsePart(callId, toolName, stringifiedOutput); } diff --git a/packages/core/src/core/prompts.ts b/packages/core/src/core/prompts.ts index 95c55143..b4b9a979 100644 --- a/packages/core/src/core/prompts.ts +++ b/packages/core/src/core/prompts.ts @@ -24,7 +24,7 @@ export function getCoreSystemPrompt(userMemory?: string): string { // default path is .gemini/system.md but can be modified via custom path in GEMINI_SYSTEM_MD let systemMdEnabled = false; let systemMdPath = path.resolve(path.join(GEMINI_CONFIG_DIR, 'system.md')); - const systemMdVar = process.env.GEMINI_SYSTEM_MD; + const systemMdVar = process.env['GEMINI_SYSTEM_MD']; if (systemMdVar) { const systemMdVarLower = systemMdVar.toLowerCase(); if (!['0', 'false'].includes(systemMdVarLower)) { @@ -121,8 +121,8 @@ When requested to perform tasks like fixing bugs, adding features, refactoring, ${(function () { // Determine sandbox status based on environment variables - const isSandboxExec = process.env.SANDBOX === 'sandbox-exec'; - const isGenericSandbox = !!process.env.SANDBOX; // Check if SANDBOX is set to any non-empty value + const isSandboxExec = process.env['SANDBOX'] === 'sandbox-exec'; + const isGenericSandbox = !!process.env['SANDBOX']; // Check if SANDBOX is set to any non-empty value if (isSandboxExec) { return ` @@ -266,7 +266,7 @@ Your core function is efficient and safe assistance. Balance extreme conciseness `.trim(); // if GEMINI_WRITE_SYSTEM_MD is set (and not 0|false), write base system prompt to file - const writeSystemMdVar = process.env.GEMINI_WRITE_SYSTEM_MD; + const writeSystemMdVar = process.env['GEMINI_WRITE_SYSTEM_MD']; if (writeSystemMdVar) { const writeSystemMdVarLower = writeSystemMdVar.toLowerCase(); if (!['0', 'false'].includes(writeSystemMdVarLower)) { diff --git a/packages/core/src/ide/detect-ide.ts b/packages/core/src/ide/detect-ide.ts index 5cc3cb56..5eca5429 100644 --- a/packages/core/src/ide/detect-ide.ts +++ b/packages/core/src/ide/detect-ide.ts @@ -63,28 +63,28 @@ export function getIdeInfo(ide: DetectedIde): IdeInfo { export function detectIde(): DetectedIde | undefined { // Only VSCode-based integrations are currently supported. - if (process.env.TERM_PROGRAM !== 'vscode') { + if (process.env['TERM_PROGRAM'] !== 'vscode') { return undefined; } - if (process.env.__COG_BASHRC_SOURCED) { + if (process.env['__COG_BASHRC_SOURCED']) { return DetectedIde.Devin; } - if (process.env.REPLIT_USER) { + if (process.env['REPLIT_USER']) { return DetectedIde.Replit; } - if (process.env.CURSOR_TRACE_ID) { + if (process.env['CURSOR_TRACE_ID']) { return DetectedIde.Cursor; } - if (process.env.CODESPACES) { + if (process.env['CODESPACES']) { return DetectedIde.Codespaces; } - if (process.env.EDITOR_IN_CLOUD_SHELL || process.env.CLOUD_SHELL) { + if (process.env['EDITOR_IN_CLOUD_SHELL'] || process.env['CLOUD_SHELL']) { return DetectedIde.CloudShell; } - if (process.env.TERM_PRODUCT === 'Trae') { + if (process.env['TERM_PRODUCT'] === 'Trae') { return DetectedIde.Trae; } - if (process.env.FIREBASE_DEPLOY_AGENT || process.env.MONOSPACE_ENV) { + if (process.env['FIREBASE_DEPLOY_AGENT'] || process.env['MONOSPACE_ENV']) { return DetectedIde.FirebaseStudio; } return DetectedIde.VSCode; diff --git a/packages/core/src/ide/ide-installer.ts b/packages/core/src/ide/ide-installer.ts index dcfe9bee..4a771c67 100644 --- a/packages/core/src/ide/ide-installer.ts +++ b/packages/core/src/ide/ide-installer.ts @@ -59,7 +59,7 @@ async function findVsCodeCommand(): Promise<string | null> { // Windows locations.push( path.join( - process.env.ProgramFiles || 'C:\\Program Files', + process.env['ProgramFiles'] || 'C:\\Program Files', 'Microsoft VS Code', 'bin', 'code.cmd', diff --git a/packages/core/src/services/loopDetectionService.ts b/packages/core/src/services/loopDetectionService.ts index f89e00da..8e94ac69 100644 --- a/packages/core/src/services/loopDetectionService.ts +++ b/packages/core/src/services/loopDetectionService.ts @@ -367,10 +367,10 @@ Please analyze the conversation history to determine the possibility that the co return false; } - if (typeof result.confidence === 'number') { - if (result.confidence > 0.9) { - if (typeof result.reasoning === 'string' && result.reasoning) { - console.warn(result.reasoning); + if (typeof result['confidence'] === 'number') { + if (result['confidence'] > 0.9) { + if (typeof result['reasoning'] === 'string' && result['reasoning']) { + console.warn(result['reasoning']); } logLoopDetected( this.config, @@ -381,7 +381,7 @@ Please analyze the conversation history to determine the possibility that the co this.llmCheckInterval = Math.round( MIN_LLM_CHECK_INTERVAL + (MAX_LLM_CHECK_INTERVAL - MIN_LLM_CHECK_INTERVAL) * - (1 - result.confidence), + (1 - result['confidence']), ); } } diff --git a/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts b/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts index 60a31ae7..200a1a0d 100644 --- a/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts +++ b/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts @@ -87,11 +87,11 @@ export interface LogRequest { * methods might have in their runtimes. */ function determineSurface(): string { - if (process.env.SURFACE) { - return process.env.SURFACE; - } else if (process.env.GITHUB_SHA) { + if (process.env['SURFACE']) { + return process.env['SURFACE']; + } else if (process.env['GITHUB_SHA']) { return 'GitHub'; - } else if (process.env.TERM_PROGRAM === 'vscode') { + } else if (process.env['TERM_PROGRAM'] === 'vscode') { return detectIde() || DetectedIde.VSCode; } else { return 'SURFACE_NOT_SET'; diff --git a/packages/core/src/telemetry/loggers.ts b/packages/core/src/telemetry/loggers.ts index d7a81203..afc92807 100644 --- a/packages/core/src/telemetry/loggers.ts +++ b/packages/core/src/telemetry/loggers.ts @@ -98,7 +98,7 @@ export function logUserPrompt(config: Config, event: UserPromptEvent): void { }; if (shouldLogUserPrompts(config)) { - attributes.prompt = event.prompt; + attributes['prompt'] = event.prompt; } const logger = logs.getLogger(SERVICE_NAME); @@ -247,7 +247,7 @@ export function logApiResponse(config: Config, event: ApiResponseEvent): void { 'event.timestamp': new Date().toISOString(), }; if (event.response_text) { - attributes.response_text = event.response_text; + attributes['response_text'] = event.response_text; } if (event.error) { attributes['error.message'] = event.error; diff --git a/packages/core/src/telemetry/metrics.ts b/packages/core/src/telemetry/metrics.ts index 1e4509da..a0996410 100644 --- a/packages/core/src/telemetry/metrics.ts +++ b/packages/core/src/telemetry/metrics.ts @@ -197,14 +197,14 @@ export function recordFileOperationMetric( ...getCommonAttributes(config), operation, }; - if (lines !== undefined) attributes.lines = lines; - if (mimetype !== undefined) attributes.mimetype = mimetype; - if (extension !== undefined) attributes.extension = extension; + if (lines !== undefined) attributes['lines'] = lines; + if (mimetype !== undefined) attributes['mimetype'] = mimetype; + if (extension !== undefined) attributes['extension'] = extension; if (diffStat !== undefined) { - attributes.ai_added_lines = diffStat.ai_added_lines; - attributes.ai_removed_lines = diffStat.ai_removed_lines; - attributes.user_added_lines = diffStat.user_added_lines; - attributes.user_removed_lines = diffStat.user_removed_lines; + attributes['ai_added_lines'] = diffStat.ai_added_lines; + attributes['ai_removed_lines'] = diffStat.ai_removed_lines; + attributes['user_added_lines'] = diffStat.user_added_lines; + attributes['user_removed_lines'] = diffStat.user_removed_lines; } fileOperationCounter.add(1, attributes); } diff --git a/packages/core/src/tools/mcp-client.ts b/packages/core/src/tools/mcp-client.ts index 837b91fc..87d38815 100644 --- a/packages/core/src/tools/mcp-client.ts +++ b/packages/core/src/tools/mcp-client.ts @@ -448,7 +448,7 @@ export function hasValidTypes(schema: unknown): boolean { const s = schema as Record<string, unknown>; - if (!s.type) { + if (!s['type']) { // These keywords contain an array of schemas that should be validated. // // If no top level type was given, then they must each have a type. @@ -470,9 +470,9 @@ export function hasValidTypes(schema: unknown): boolean { if (!hasSubSchema) return false; } - if (s.type === 'object' && s.properties) { - if (typeof s.properties === 'object' && s.properties !== null) { - for (const prop of Object.values(s.properties)) { + if (s['type'] === 'object' && s['properties']) { + if (typeof s['properties'] === 'object' && s['properties'] !== null) { + for (const prop of Object.values(s['properties'])) { if (!hasValidTypes(prop)) { return false; } @@ -480,8 +480,8 @@ export function hasValidTypes(schema: unknown): boolean { } } - if (s.type === 'array' && s.items) { - if (!hasValidTypes(s.items)) { + if (s['type'] === 'array' && s['items']) { + if (!hasValidTypes(s['items'])) { return false; } } @@ -1046,7 +1046,7 @@ export async function connectToMcpServer( conciseError = `Connection failed for '${mcpServerName}': ${errorMessage}`; } - if (process.env.SANDBOX) { + if (process.env['SANDBOX']) { conciseError += ` (check sandbox availability)`; } diff --git a/packages/core/src/tools/mcp-tool.ts b/packages/core/src/tools/mcp-tool.ts index 88e89c85..64952dd1 100644 --- a/packages/core/src/tools/mcp-tool.ts +++ b/packages/core/src/tools/mcp-tool.ts @@ -271,7 +271,7 @@ function transformResourceLinkBlock(block: McpResourceLinkBlock): Part { */ function transformMcpContentToParts(sdkResponse: Part[]): Part[] { const funcResponse = sdkResponse?.[0]?.functionResponse; - const mcpContent = funcResponse?.response?.content as McpContentBlock[]; + const mcpContent = funcResponse?.response?.['content'] as McpContentBlock[]; const toolName = funcResponse?.name || 'unknown tool'; if (!Array.isArray(mcpContent)) { @@ -308,8 +308,9 @@ function transformMcpContentToParts(sdkResponse: Part[]): Part[] { * @returns A formatted string representing the tool's output. */ function getStringifiedResultForDisplay(rawResponse: Part[]): string { - const mcpContent = rawResponse?.[0]?.functionResponse?.response - ?.content as McpContentBlock[]; + const mcpContent = rawResponse?.[0]?.functionResponse?.response?.[ + 'content' + ] as McpContentBlock[]; if (!Array.isArray(mcpContent)) { return '```json\n' + JSON.stringify(rawResponse, null, 2) + '\n```'; diff --git a/packages/core/src/utils/browser.ts b/packages/core/src/utils/browser.ts index a9b2b013..35ee7461 100644 --- a/packages/core/src/utils/browser.ts +++ b/packages/core/src/utils/browser.ts @@ -15,19 +15,22 @@ export function shouldAttemptBrowserLaunch(): boolean { // A list of browser names that indicate we should not attempt to open a // web browser for the user. const browserBlocklist = ['www-browser']; - const browserEnv = process.env.BROWSER; + const browserEnv = process.env['BROWSER']; if (browserEnv && browserBlocklist.includes(browserEnv)) { return false; } // Common environment variables used in CI/CD or other non-interactive shells. - if (process.env.CI || process.env.DEBIAN_FRONTEND === 'noninteractive') { + if ( + process.env['CI'] || + process.env['DEBIAN_FRONTEND'] === 'noninteractive' + ) { return false; } // The presence of SSH_CONNECTION indicates a remote session. // We should not attempt to launch a browser unless a display is explicitly available // (checked below for Linux). - const isSSH = !!process.env.SSH_CONNECTION; + const isSSH = !!process.env['SSH_CONNECTION']; // On Linux, the presence of a display server is a strong indicator of a GUI. if (process.platform === 'linux') { diff --git a/packages/core/src/utils/editCorrector.ts b/packages/core/src/utils/editCorrector.ts index faa52b51..0d857409 100644 --- a/packages/core/src/utils/editCorrector.ts +++ b/packages/core/src/utils/editCorrector.ts @@ -119,7 +119,7 @@ async function findLastEditTimestamp( const { response } = part.functionResponse; if (response && !('error' in response) && 'output' in response) { id = part.functionResponse.id; - content = response.output; + content = response['output']; } } @@ -411,10 +411,10 @@ Return ONLY the corrected target snippet in the specified JSON format with the k if ( result && - typeof result.corrected_target_snippet === 'string' && - result.corrected_target_snippet.length > 0 + typeof result['corrected_target_snippet'] === 'string' && + result['corrected_target_snippet'].length > 0 ) { - return result.corrected_target_snippet; + return result['corrected_target_snippet']; } else { return problematicSnippet; } @@ -499,10 +499,10 @@ Return ONLY the corrected string in the specified JSON format with the key 'corr if ( result && - typeof result.corrected_new_string === 'string' && - result.corrected_new_string.length > 0 + typeof result['corrected_new_string'] === 'string' && + result['corrected_new_string'].length > 0 ) { - return result.corrected_new_string; + return result['corrected_new_string']; } else { return originalNewString; } @@ -568,10 +568,10 @@ Return ONLY the corrected string in the specified JSON format with the key 'corr if ( result && - typeof result.corrected_new_string_escaping === 'string' && - result.corrected_new_string_escaping.length > 0 + typeof result['corrected_new_string_escaping'] === 'string' && + result['corrected_new_string_escaping'].length > 0 ) { - return result.corrected_new_string_escaping; + return result['corrected_new_string_escaping']; } else { return potentiallyProblematicNewString; } @@ -634,10 +634,10 @@ Return ONLY the corrected string in the specified JSON format with the key 'corr if ( result && - typeof result.corrected_string_escaping === 'string' && - result.corrected_string_escaping.length > 0 + typeof result['corrected_string_escaping'] === 'string' && + result['corrected_string_escaping'].length > 0 ) { - return result.corrected_string_escaping; + return result['corrected_string_escaping']; } else { return potentiallyProblematicString; } diff --git a/packages/core/src/utils/editor.test.ts b/packages/core/src/utils/editor.test.ts index afdc2b24..fcf50f9c 100644 --- a/packages/core/src/utils/editor.test.ts +++ b/packages/core/src/utils/editor.test.ts @@ -33,7 +33,7 @@ const originalPlatform = process.platform; describe('editor utils', () => { beforeEach(() => { vi.clearAllMocks(); - delete process.env.SANDBOX; + vi.unstubAllEnvs(); Object.defineProperty(process, 'platform', { value: originalPlatform, writable: true, @@ -42,7 +42,7 @@ describe('editor utils', () => { afterEach(() => { vi.restoreAllMocks(); - delete process.env.SANDBOX; + vi.unstubAllEnvs(); Object.defineProperty(process, 'platform', { value: originalPlatform, writable: true, @@ -461,7 +461,7 @@ describe('editor utils', () => { describe('allowEditorTypeInSandbox', () => { it('should allow vim in sandbox mode', () => { - process.env.SANDBOX = 'sandbox'; + vi.stubEnv('SANDBOX', 'sandbox'); expect(allowEditorTypeInSandbox('vim')).toBe(true); }); @@ -470,7 +470,7 @@ describe('editor utils', () => { }); it('should allow emacs in sandbox mode', () => { - process.env.SANDBOX = 'sandbox'; + vi.stubEnv('SANDBOX', 'sandbox'); expect(allowEditorTypeInSandbox('emacs')).toBe(true); }); @@ -479,7 +479,7 @@ describe('editor utils', () => { }); it('should allow neovim in sandbox mode', () => { - process.env.SANDBOX = 'sandbox'; + vi.stubEnv('SANDBOX', 'sandbox'); expect(allowEditorTypeInSandbox('neovim')).toBe(true); }); @@ -496,7 +496,7 @@ describe('editor utils', () => { ]; for (const editor of guiEditors) { it(`should not allow ${editor} in sandbox mode`, () => { - process.env.SANDBOX = 'sandbox'; + vi.stubEnv('SANDBOX', 'sandbox'); expect(allowEditorTypeInSandbox(editor)).toBe(false); }); @@ -533,25 +533,25 @@ describe('editor utils', () => { it('should return false for vscode when installed and in sandbox mode', () => { (execSync as Mock).mockReturnValue(Buffer.from('/usr/bin/code')); - process.env.SANDBOX = 'sandbox'; + vi.stubEnv('SANDBOX', 'sandbox'); expect(isEditorAvailable('vscode')).toBe(false); }); it('should return true for vim when installed and in sandbox mode', () => { (execSync as Mock).mockReturnValue(Buffer.from('/usr/bin/vim')); - process.env.SANDBOX = 'sandbox'; + vi.stubEnv('SANDBOX', 'sandbox'); expect(isEditorAvailable('vim')).toBe(true); }); it('should return true for emacs when installed and in sandbox mode', () => { (execSync as Mock).mockReturnValue(Buffer.from('/usr/bin/emacs')); - process.env.SANDBOX = 'sandbox'; + vi.stubEnv('SANDBOX', 'sandbox'); expect(isEditorAvailable('emacs')).toBe(true); }); it('should return true for neovim when installed and in sandbox mode', () => { (execSync as Mock).mockReturnValue(Buffer.from('/usr/bin/nvim')); - process.env.SANDBOX = 'sandbox'; + vi.stubEnv('SANDBOX', 'sandbox'); expect(isEditorAvailable('neovim')).toBe(true); }); }); diff --git a/packages/core/src/utils/editor.ts b/packages/core/src/utils/editor.ts index f22297df..efaef249 100644 --- a/packages/core/src/utils/editor.ts +++ b/packages/core/src/utils/editor.ts @@ -72,7 +72,7 @@ export function checkHasEditorType(editor: EditorType): boolean { } export function allowEditorTypeInSandbox(editor: EditorType): boolean { - const notUsingSandbox = !process.env.SANDBOX; + const notUsingSandbox = !process.env['SANDBOX']; if (['vscode', 'vscodium', 'windsurf', 'cursor', 'zed'].includes(editor)) { return notUsingSandbox; } diff --git a/packages/core/src/utils/memoryDiscovery.test.ts b/packages/core/src/utils/memoryDiscovery.test.ts index 6c229dbb..d8f3ccc5 100644 --- a/packages/core/src/utils/memoryDiscovery.test.ts +++ b/packages/core/src/utils/memoryDiscovery.test.ts @@ -48,8 +48,8 @@ describe('loadServerHierarchicalMemory', () => { vi.resetAllMocks(); // Set environment variables to indicate test environment - process.env.NODE_ENV = 'test'; - process.env.VITEST = 'true'; + vi.stubEnv('NODE_ENV', 'test'); + vi.stubEnv('VITEST', 'true'); projectRoot = await createEmptyDir(path.join(testRootDir, 'project')); cwd = await createEmptyDir(path.join(projectRoot, 'src')); @@ -58,6 +58,7 @@ describe('loadServerHierarchicalMemory', () => { }); afterEach(async () => { + vi.unstubAllEnvs(); // Some tests set this to a different value. setGeminiMdFilename(DEFAULT_CONTEXT_FILENAME); // Clean up the temporary directory to prevent resource leaks. diff --git a/packages/core/src/utils/memoryDiscovery.ts b/packages/core/src/utils/memoryDiscovery.ts index fcb1abdd..d3c24baf 100644 --- a/packages/core/src/utils/memoryDiscovery.ts +++ b/packages/core/src/utils/memoryDiscovery.ts @@ -57,8 +57,9 @@ async function findProjectRoot(startDir: string): Promise<string | null> { (error as { code: string }).code === 'ENOENT'; // Only log unexpected errors in non-test environments - // process.env.NODE_ENV === 'test' or VITEST are common test indicators - const isTestEnv = process.env.NODE_ENV === 'test' || process.env.VITEST; + // process.env['NODE_ENV'] === 'test' or VITEST are common test indicators + const isTestEnv = + process.env['NODE_ENV'] === 'test' || process.env['VITEST']; if (!isENOENT && !isTestEnv) { if (typeof error === 'object' && error !== null && 'code' in error) { @@ -246,7 +247,8 @@ async function readGeminiMdFiles( `Successfully read and processed imports: ${filePath} (Length: ${processedResult.content.length})`, ); } catch (error: unknown) { - const isTestEnv = process.env.NODE_ENV === 'test' || process.env.VITEST; + const isTestEnv = + process.env['NODE_ENV'] === 'test' || process.env['VITEST']; if (!isTestEnv) { const message = error instanceof Error ? error.message : String(error); logger.warn( diff --git a/packages/core/src/utils/secure-browser-launcher.ts b/packages/core/src/utils/secure-browser-launcher.ts index ec8357be..c60a646d 100644 --- a/packages/core/src/utils/secure-browser-launcher.ts +++ b/packages/core/src/utils/secure-browser-launcher.ts @@ -151,20 +151,23 @@ export function shouldLaunchBrowser(): boolean { // A list of browser names that indicate we should not attempt to open a // web browser for the user. const browserBlocklist = ['www-browser']; - const browserEnv = process.env.BROWSER; + const browserEnv = process.env['BROWSER']; if (browserEnv && browserBlocklist.includes(browserEnv)) { return false; } // Common environment variables used in CI/CD or other non-interactive shells. - if (process.env.CI || process.env.DEBIAN_FRONTEND === 'noninteractive') { + if ( + process.env['CI'] || + process.env['DEBIAN_FRONTEND'] === 'noninteractive' + ) { return false; } // The presence of SSH_CONNECTION indicates a remote session. // We should not attempt to launch a browser unless a display is explicitly available // (checked below for Linux). - const isSSH = !!process.env.SSH_CONNECTION; + const isSSH = !!process.env['SSH_CONNECTION']; // On Linux, the presence of a display server is a strong indicator of a GUI. if (platform() === 'linux') { diff --git a/packages/core/src/utils/shell-utils.test.ts b/packages/core/src/utils/shell-utils.test.ts index 913ec897..18f88e11 100644 --- a/packages/core/src/utils/shell-utils.test.ts +++ b/packages/core/src/utils/shell-utils.test.ts @@ -388,7 +388,7 @@ describe('getShellConfiguration', () => { }); it('should return cmd.exe configuration by default', () => { - delete process.env.ComSpec; + delete process.env['ComSpec']; const config = getShellConfiguration(); expect(config.executable).toBe('cmd.exe'); expect(config.argsPrefix).toEqual(['/d', '/s', '/c']); @@ -397,7 +397,7 @@ describe('getShellConfiguration', () => { it('should respect ComSpec for cmd.exe', () => { const cmdPath = 'C:\\WINDOWS\\system32\\cmd.exe'; - process.env.ComSpec = cmdPath; + process.env['ComSpec'] = cmdPath; const config = getShellConfiguration(); expect(config.executable).toBe(cmdPath); expect(config.argsPrefix).toEqual(['/d', '/s', '/c']); @@ -407,7 +407,7 @@ describe('getShellConfiguration', () => { it('should return PowerShell configuration if ComSpec points to powershell.exe', () => { const psPath = 'C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'; - process.env.ComSpec = psPath; + process.env['ComSpec'] = psPath; const config = getShellConfiguration(); expect(config.executable).toBe(psPath); expect(config.argsPrefix).toEqual(['-NoProfile', '-Command']); @@ -416,7 +416,7 @@ describe('getShellConfiguration', () => { it('should return PowerShell configuration if ComSpec points to pwsh.exe', () => { const pwshPath = 'C:\\Program Files\\PowerShell\\7\\pwsh.exe'; - process.env.ComSpec = pwshPath; + process.env['ComSpec'] = pwshPath; const config = getShellConfiguration(); expect(config.executable).toBe(pwshPath); expect(config.argsPrefix).toEqual(['-NoProfile', '-Command']); @@ -424,7 +424,7 @@ describe('getShellConfiguration', () => { }); it('should be case-insensitive when checking ComSpec', () => { - process.env.ComSpec = 'C:\\Path\\To\\POWERSHELL.EXE'; + process.env['ComSpec'] = 'C:\\Path\\To\\POWERSHELL.EXE'; const config = getShellConfiguration(); expect(config.executable).toBe('C:\\Path\\To\\POWERSHELL.EXE'); expect(config.argsPrefix).toEqual(['-NoProfile', '-Command']); diff --git a/packages/core/src/utils/shell-utils.ts b/packages/core/src/utils/shell-utils.ts index 2c818c8e..808cf893 100644 --- a/packages/core/src/utils/shell-utils.ts +++ b/packages/core/src/utils/shell-utils.ts @@ -37,7 +37,7 @@ export interface ShellConfiguration { */ export function getShellConfiguration(): ShellConfiguration { if (isWindows()) { - const comSpec = process.env.ComSpec || 'cmd.exe'; + const comSpec = process.env['ComSpec'] || 'cmd.exe'; const executable = comSpec.toLowerCase(); if ( diff --git a/packages/core/src/utils/systemEncoding.test.ts b/packages/core/src/utils/systemEncoding.test.ts index 9375db9e..afabd33f 100644 --- a/packages/core/src/utils/systemEncoding.test.ts +++ b/packages/core/src/utils/systemEncoding.test.ts @@ -39,9 +39,9 @@ describe('Shell Command Processor - Encoding Functions', () => { resetEncodingCache(); // Clear environment variables that might affect tests - delete process.env.LC_ALL; - delete process.env.LC_CTYPE; - delete process.env.LANG; + delete process.env['LC_ALL']; + delete process.env['LC_CTYPE']; + delete process.env['LANG']; }); afterEach(() => { @@ -218,21 +218,21 @@ describe('Shell Command Processor - Encoding Functions', () => { }); it('should parse locale from LC_ALL environment variable', () => { - process.env.LC_ALL = 'en_US.UTF-8'; + process.env['LC_ALL'] = 'en_US.UTF-8'; const result = getSystemEncoding(); expect(result).toBe('utf-8'); }); it('should parse locale from LC_CTYPE when LC_ALL is not set', () => { - process.env.LC_CTYPE = 'fr_FR.ISO-8859-1'; + process.env['LC_CTYPE'] = 'fr_FR.ISO-8859-1'; const result = getSystemEncoding(); expect(result).toBe('iso-8859-1'); }); it('should parse locale from LANG when LC_ALL and LC_CTYPE are not set', () => { - process.env.LANG = 'de_DE.UTF-8'; + process.env['LANG'] = 'de_DE.UTF-8'; const result = getSystemEncoding(); expect(result).toBe('utf-8'); @@ -268,16 +268,16 @@ describe('Shell Command Processor - Encoding Functions', () => { }); it('should handle locale without encoding (no dot)', () => { - process.env.LANG = 'C'; + process.env['LANG'] = 'C'; const result = getSystemEncoding(); expect(result).toBe('c'); }); it('should handle empty locale environment variables', () => { - process.env.LC_ALL = ''; - process.env.LC_CTYPE = ''; - process.env.LANG = ''; + process.env['LC_ALL'] = ''; + process.env['LC_CTYPE'] = ''; + process.env['LANG'] = ''; mockedExecSync.mockReturnValue('UTF-8'); const result = getSystemEncoding(); @@ -285,24 +285,24 @@ describe('Shell Command Processor - Encoding Functions', () => { }); it('should return locale as-is when locale format has no dot', () => { - process.env.LANG = 'invalid_format'; + process.env['LANG'] = 'invalid_format'; const result = getSystemEncoding(); expect(result).toBe('invalid_format'); }); it('should prioritize LC_ALL over other environment variables', () => { - process.env.LC_ALL = 'en_US.UTF-8'; - process.env.LC_CTYPE = 'fr_FR.ISO-8859-1'; - process.env.LANG = 'de_DE.CP1252'; + process.env['LC_ALL'] = 'en_US.UTF-8'; + process.env['LC_CTYPE'] = 'fr_FR.ISO-8859-1'; + process.env['LANG'] = 'de_DE.CP1252'; const result = getSystemEncoding(); expect(result).toBe('utf-8'); }); it('should prioritize LC_CTYPE over LANG', () => { - process.env.LC_CTYPE = 'fr_FR.ISO-8859-1'; - process.env.LANG = 'de_DE.CP1252'; + process.env['LC_CTYPE'] = 'fr_FR.ISO-8859-1'; + process.env['LANG'] = 'de_DE.CP1252'; const result = getSystemEncoding(); expect(result).toBe('iso-8859-1'); @@ -315,7 +315,7 @@ describe('Shell Command Processor - Encoding Functions', () => { }); it('should use cached system encoding on subsequent calls', () => { - process.env.LANG = 'en_US.UTF-8'; + process.env['LANG'] = 'en_US.UTF-8'; const buffer = Buffer.from('test'); // First call @@ -323,7 +323,7 @@ describe('Shell Command Processor - Encoding Functions', () => { expect(result1).toBe('utf-8'); // Change environment (should not affect cached result) - process.env.LANG = 'fr_FR.ISO-8859-1'; + process.env['LANG'] = 'fr_FR.ISO-8859-1'; // Second call should use cached value const result2 = getCachedEncodingForBuffer(buffer); @@ -435,7 +435,7 @@ describe('Shell Command Processor - Encoding Functions', () => { describe('Cross-platform behavior', () => { it('should work correctly on macOS', () => { mockedOsPlatform.mockReturnValue('darwin'); - process.env.LANG = 'en_US.UTF-8'; + process.env['LANG'] = 'en_US.UTF-8'; const result = getSystemEncoding(); expect(result).toBe('utf-8'); @@ -443,7 +443,7 @@ describe('Shell Command Processor - Encoding Functions', () => { it('should work correctly on other Unix-like systems', () => { mockedOsPlatform.mockReturnValue('freebsd'); - process.env.LANG = 'en_US.UTF-8'; + process.env['LANG'] = 'en_US.UTF-8'; const result = getSystemEncoding(); expect(result).toBe('utf-8'); @@ -451,7 +451,7 @@ describe('Shell Command Processor - Encoding Functions', () => { it('should handle unknown platforms as Unix-like', () => { mockedOsPlatform.mockReturnValue('unknown' as NodeJS.Platform); - process.env.LANG = 'en_US.UTF-8'; + process.env['LANG'] = 'en_US.UTF-8'; const result = getSystemEncoding(); expect(result).toBe('utf-8'); @@ -461,7 +461,7 @@ describe('Shell Command Processor - Encoding Functions', () => { describe('Edge cases and error handling', () => { it('should handle empty buffer gracefully', () => { mockedOsPlatform.mockReturnValue('linux'); - process.env.LANG = 'en_US.UTF-8'; + process.env['LANG'] = 'en_US.UTF-8'; const buffer = Buffer.alloc(0); const result = getCachedEncodingForBuffer(buffer); @@ -470,7 +470,7 @@ describe('Shell Command Processor - Encoding Functions', () => { it('should handle very large buffers', () => { mockedOsPlatform.mockReturnValue('linux'); - process.env.LANG = 'en_US.UTF-8'; + process.env['LANG'] = 'en_US.UTF-8'; const buffer = Buffer.alloc(1024 * 1024, 'a'); const result = getCachedEncodingForBuffer(buffer); diff --git a/packages/core/src/utils/systemEncoding.ts b/packages/core/src/utils/systemEncoding.ts index f162c223..ba632d41 100644 --- a/packages/core/src/utils/systemEncoding.ts +++ b/packages/core/src/utils/systemEncoding.ts @@ -79,7 +79,7 @@ export function getSystemEncoding(): string | null { // system encoding. However, these environment variables might not always // be set or accurate. Handle cases where none of these variables are set. const env = process.env; - let locale = env.LC_ALL || env.LC_CTYPE || env.LANG || ''; + let locale = env['LC_ALL'] || env['LC_CTYPE'] || env['LANG'] || ''; // Fallback to querying the system directly when environment variables are missing if (!locale) { |
