mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
chore(compiler): Enable strict property access TS compiler flag. (#6255)
Co-authored-by: Jacob Richman <jacob314@gmail.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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],
|
||||
});
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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' &&
|
||||
|
||||
@@ -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.",
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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})`,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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']),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)`;
|
||||
}
|
||||
|
||||
|
||||
@@ -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```';
|
||||
|
||||
@@ -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') {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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') {
|
||||
|
||||
@@ -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']);
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user