merge main de resolve conflict

This commit is contained in:
DennisYu07 2026-03-06 16:00:51 -08:00
commit 3458c1d68b
191 changed files with 9340 additions and 7371 deletions

View file

@ -1322,7 +1322,7 @@ describe('loadCliConfig with allowed-mcp-server-names', () => {
});
});
it('should read excludeMCPServers from settings', async () => {
it('should read excludeMCPServers from settings but still return all servers', async () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments();
const settings: Settings = {
@ -1330,12 +1330,18 @@ describe('loadCliConfig with allowed-mcp-server-names', () => {
mcp: { excluded: ['server1', 'server2'] },
};
const config = await loadCliConfig(settings, argv, undefined, []);
// getMcpServers() now returns all servers, use isMcpServerDisabled() to check status
expect(config.getMcpServers()).toEqual({
server1: { url: 'http://localhost:8080' },
server2: { url: 'http://localhost:8081' },
server3: { url: 'http://localhost:8082' },
});
expect(config.isMcpServerDisabled('server1')).toBe(true);
expect(config.isMcpServerDisabled('server2')).toBe(true);
expect(config.isMcpServerDisabled('server3')).toBe(false);
});
it('should override allowMCPServers with excludeMCPServers if overlapping', async () => {
it('should apply allowedMcpServers filter but excluded servers are still returned', async () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments();
const settings: Settings = {
@ -1346,9 +1352,14 @@ describe('loadCliConfig with allowed-mcp-server-names', () => {
},
};
const config = await loadCliConfig(settings, argv, undefined, []);
// allowedMcpServers filters which servers are available
// but excluded servers are still returned by getMcpServers()
expect(config.getMcpServers()).toEqual({
server1: { url: 'http://localhost:8080' },
server2: { url: 'http://localhost:8081' },
});
expect(config.isMcpServerDisabled('server1')).toBe(true);
expect(config.isMcpServerDisabled('server2')).toBe(false);
});
it('should prioritize mcp server flag if set', async () => {
@ -2244,8 +2255,8 @@ describe('parseArguments with positional prompt', () => {
});
describe('Telemetry configuration via environment variables', () => {
it('should prioritize GEMINI_TELEMETRY_ENABLED over settings', async () => {
vi.stubEnv('GEMINI_TELEMETRY_ENABLED', 'true');
it('should prioritize QWEN_TELEMETRY_ENABLED over settings', async () => {
vi.stubEnv('QWEN_TELEMETRY_ENABLED', 'true');
process.argv = ['node', 'script.js'];
const argv = await parseArguments();
const settings: Settings = { telemetry: { enabled: false } };
@ -2253,8 +2264,8 @@ describe('Telemetry configuration via environment variables', () => {
expect(config.getTelemetryEnabled()).toBe(true);
});
it('should prioritize GEMINI_TELEMETRY_TARGET over settings', async () => {
vi.stubEnv('GEMINI_TELEMETRY_TARGET', 'gcp');
it('should prioritize QWEN_TELEMETRY_TARGET over settings', async () => {
vi.stubEnv('QWEN_TELEMETRY_TARGET', 'gcp');
process.argv = ['node', 'script.js'];
const argv = await parseArguments();
const settings: Settings = {
@ -2264,8 +2275,8 @@ describe('Telemetry configuration via environment variables', () => {
expect(config.getTelemetryTarget()).toBe('gcp');
});
it('should throw when GEMINI_TELEMETRY_TARGET is invalid', async () => {
vi.stubEnv('GEMINI_TELEMETRY_TARGET', 'bogus');
it('should throw when QWEN_TELEMETRY_TARGET is invalid', async () => {
vi.stubEnv('QWEN_TELEMETRY_TARGET', 'bogus');
process.argv = ['node', 'script.js'];
const argv = await parseArguments();
const settings: Settings = {
@ -2277,9 +2288,9 @@ describe('Telemetry configuration via environment variables', () => {
vi.unstubAllEnvs();
});
it('should prioritize GEMINI_TELEMETRY_OTLP_ENDPOINT over settings and default env var', async () => {
it('should prioritize QWEN_TELEMETRY_OTLP_ENDPOINT over settings and default env var', async () => {
vi.stubEnv('OTEL_EXPORTER_OTLP_ENDPOINT', 'http://default.env.com');
vi.stubEnv('GEMINI_TELEMETRY_OTLP_ENDPOINT', 'http://gemini.env.com');
vi.stubEnv('QWEN_TELEMETRY_OTLP_ENDPOINT', 'http://gemini.env.com');
process.argv = ['node', 'script.js'];
const argv = await parseArguments();
const settings: Settings = {
@ -2289,8 +2300,8 @@ describe('Telemetry configuration via environment variables', () => {
expect(config.getTelemetryOtlpEndpoint()).toBe('http://gemini.env.com');
});
it('should prioritize GEMINI_TELEMETRY_OTLP_PROTOCOL over settings', async () => {
vi.stubEnv('GEMINI_TELEMETRY_OTLP_PROTOCOL', 'http');
it('should prioritize QWEN_TELEMETRY_OTLP_PROTOCOL over settings', async () => {
vi.stubEnv('QWEN_TELEMETRY_OTLP_PROTOCOL', 'http');
process.argv = ['node', 'script.js'];
const argv = await parseArguments();
const settings: Settings = { telemetry: { otlpProtocol: 'grpc' } };
@ -2298,8 +2309,8 @@ describe('Telemetry configuration via environment variables', () => {
expect(config.getTelemetryOtlpProtocol()).toBe('http');
});
it('should prioritize GEMINI_TELEMETRY_LOG_PROMPTS over settings', async () => {
vi.stubEnv('GEMINI_TELEMETRY_LOG_PROMPTS', 'false');
it('should prioritize QWEN_TELEMETRY_LOG_PROMPTS over settings', async () => {
vi.stubEnv('QWEN_TELEMETRY_LOG_PROMPTS', 'false');
process.argv = ['node', 'script.js'];
const argv = await parseArguments();
const settings: Settings = { telemetry: { logPrompts: true } };
@ -2307,8 +2318,8 @@ describe('Telemetry configuration via environment variables', () => {
expect(config.getTelemetryLogPromptsEnabled()).toBe(false);
});
it('should prioritize GEMINI_TELEMETRY_OUTFILE over settings', async () => {
vi.stubEnv('GEMINI_TELEMETRY_OUTFILE', '/gemini/env/telemetry.log');
it('should prioritize QWEN_TELEMETRY_OUTFILE over settings', async () => {
vi.stubEnv('QWEN_TELEMETRY_OUTFILE', '/gemini/env/telemetry.log');
process.argv = ['node', 'script.js'];
const argv = await parseArguments();
const settings: Settings = {
@ -2318,8 +2329,8 @@ describe('Telemetry configuration via environment variables', () => {
expect(config.getTelemetryOutfile()).toBe('/gemini/env/telemetry.log');
});
it('should prioritize GEMINI_TELEMETRY_USE_COLLECTOR over settings', async () => {
vi.stubEnv('GEMINI_TELEMETRY_USE_COLLECTOR', 'true');
it('should prioritize QWEN_TELEMETRY_USE_COLLECTOR over settings', async () => {
vi.stubEnv('QWEN_TELEMETRY_USE_COLLECTOR', 'true');
process.argv = ['node', 'script.js'];
const argv = await parseArguments();
const settings: Settings = { telemetry: { useCollector: false } };
@ -2327,8 +2338,8 @@ describe('Telemetry configuration via environment variables', () => {
expect(config.getTelemetryUseCollector()).toBe(true);
});
it('should use settings value when GEMINI_TELEMETRY_ENABLED is not set', async () => {
vi.stubEnv('GEMINI_TELEMETRY_ENABLED', undefined);
it('should use settings value when QWEN_TELEMETRY_ENABLED is not set', async () => {
vi.stubEnv('QWEN_TELEMETRY_ENABLED', undefined);
process.argv = ['node', 'script.js'];
const argv = await parseArguments();
const settings: Settings = { telemetry: { enabled: true } };
@ -2336,8 +2347,8 @@ describe('Telemetry configuration via environment variables', () => {
expect(config.getTelemetryEnabled()).toBe(true);
});
it('should use settings value when GEMINI_TELEMETRY_TARGET is not set', async () => {
vi.stubEnv('GEMINI_TELEMETRY_TARGET', undefined);
it('should use settings value when QWEN_TELEMETRY_TARGET is not set', async () => {
vi.stubEnv('QWEN_TELEMETRY_TARGET', undefined);
process.argv = ['node', 'script.js'];
const argv = await parseArguments();
const settings: Settings = {
@ -2347,16 +2358,16 @@ describe('Telemetry configuration via environment variables', () => {
expect(config.getTelemetryTarget()).toBe('local');
});
it("should treat GEMINI_TELEMETRY_ENABLED='1' as true", async () => {
vi.stubEnv('GEMINI_TELEMETRY_ENABLED', '1');
it("should treat QWEN_TELEMETRY_ENABLED='1' as true", async () => {
vi.stubEnv('QWEN_TELEMETRY_ENABLED', '1');
process.argv = ['node', 'script.js'];
const argv = await parseArguments();
const config = await loadCliConfig({}, argv, undefined, []);
expect(config.getTelemetryEnabled()).toBe(true);
});
it("should treat GEMINI_TELEMETRY_ENABLED='0' as false", async () => {
vi.stubEnv('GEMINI_TELEMETRY_ENABLED', '0');
it("should treat QWEN_TELEMETRY_ENABLED='0' as false", async () => {
vi.stubEnv('QWEN_TELEMETRY_ENABLED', '0');
process.argv = ['node', 'script.js'];
const argv = await parseArguments();
const config = await loadCliConfig(
@ -2368,16 +2379,16 @@ describe('Telemetry configuration via environment variables', () => {
expect(config.getTelemetryEnabled()).toBe(false);
});
it("should treat GEMINI_TELEMETRY_LOG_PROMPTS='1' as true", async () => {
vi.stubEnv('GEMINI_TELEMETRY_LOG_PROMPTS', '1');
it("should treat QWEN_TELEMETRY_LOG_PROMPTS='1' as true", async () => {
vi.stubEnv('QWEN_TELEMETRY_LOG_PROMPTS', '1');
process.argv = ['node', 'script.js'];
const argv = await parseArguments();
const config = await loadCliConfig({}, argv, undefined, []);
expect(config.getTelemetryLogPromptsEnabled()).toBe(true);
});
it("should treat GEMINI_TELEMETRY_LOG_PROMPTS='false' as false", async () => {
vi.stubEnv('GEMINI_TELEMETRY_LOG_PROMPTS', 'false');
it("should treat QWEN_TELEMETRY_LOG_PROMPTS='false' as false", async () => {
vi.stubEnv('QWEN_TELEMETRY_LOG_PROMPTS', 'false');
process.argv = ['node', 'script.js'];
const argv = await parseArguments();
const config = await loadCliConfig(

View file

@ -1023,7 +1023,7 @@ export async function loadCliConfig(
useBuiltinRipgrep: settings.tools?.useBuiltinRipgrep,
shouldUseNodePtyShell: settings.tools?.shell?.enableInteractiveShell,
skipNextSpeakerCheck: settings.model?.skipNextSpeakerCheck,
skipLoopDetection: settings.model?.skipLoopDetection ?? false,
skipLoopDetection: settings.model?.skipLoopDetection ?? true,
skipStartupContext: settings.model?.skipStartupContext ?? false,
truncateToolOutputThreshold: settings.tools?.truncateToolOutputThreshold,
truncateToolOutputLines: settings.tools?.truncateToolOutputLines,

View file

@ -38,7 +38,7 @@ function getSandboxCommand(
// note environment variable takes precedence over argument (from command line or settings)
const environmentConfiguredSandbox =
process.env['GEMINI_SANDBOX']?.toLowerCase().trim() ?? '';
process.env['QWEN_SANDBOX']?.toLowerCase().trim() ?? '';
sandbox =
environmentConfiguredSandbox?.length > 0
? environmentConfiguredSandbox
@ -63,7 +63,7 @@ function getSandboxCommand(
return sandbox;
}
throw new FatalSandboxError(
`Missing sandbox command '${sandbox}' (from GEMINI_SANDBOX)`,
`Missing sandbox command '${sandbox}' (from QWEN_SANDBOX)`,
);
}
@ -80,8 +80,8 @@ function getSandboxCommand(
// throw an error if user requested sandbox but no command was found
if (sandbox === true) {
throw new FatalSandboxError(
'GEMINI_SANDBOX is true but failed to determine command for sandbox; ' +
'install docker or podman or specify command in GEMINI_SANDBOX',
'QWEN_SANDBOX is true but failed to determine command for sandbox; ' +
'install docker or podman or specify command in QWEN_SANDBOX',
);
}
@ -98,7 +98,7 @@ export async function loadSandboxConfig(
const packageJson = await getPackageJson();
const image =
argv.sandboxImage ??
process.env['GEMINI_SANDBOX_IMAGE'] ??
process.env['QWEN_SANDBOX_IMAGE'] ??
packageJson?.config?.sandboxImageUri;
return command && image ? { command, image } : undefined;

View file

@ -453,7 +453,7 @@ describe('Settings Loading and Merging', () => {
);
});
it('should warn about unknown top-level keys in a v2 settings file', () => {
it('should silently ignore unknown top-level keys in a v2 settings file', () => {
(mockFsExistsSync as Mock).mockImplementation(
(p: fs.PathLike) => p === USER_SETTINGS_PATH,
);
@ -471,13 +471,7 @@ describe('Settings Loading and Merging', () => {
const settings = loadSettings(MOCK_WORKSPACE_DIR);
expect(getSettingsWarnings(settings)).toEqual(
expect.arrayContaining([
expect.stringContaining(
"Unknown setting 'someUnknownKey' will be ignored",
),
]),
);
expect(getSettingsWarnings(settings)).toEqual([]);
});
it('should not warn for valid v2 container keys', () => {

View file

@ -34,7 +34,6 @@ import { resolveEnvVarsInObject } from '../utils/envVarResolver.js';
import { setNestedPropertySafe } from '../utils/settingsUtils.js';
import { customDeepMerge } from '../utils/deepMerge.js';
import { updateSettingsFilePreservingFormat } from '../utils/commentJson.js';
const debugLogger = createDebugLogger('SETTINGS');
import { runMigrations, needsMigration } from './migration/index.js';
import {
V1_TO_V2_MIGRATION_MAP,
@ -42,6 +41,8 @@ import {
} from './migration/versions/v1-to-v2-shared.js';
import { writeWithBackupSync } from '../utils/writeWithBackup.js';
const debugLogger = createDebugLogger('SETTINGS');
function getMergeStrategyForPath(path: string[]): MergeStrategy | undefined {
let current: SettingDefinition | undefined = undefined;
let currentSchema: SettingsSchema | undefined = getSettingsSchema();
@ -165,7 +166,7 @@ function getSettingsFileKeyWarnings(
);
}
// Unknown top-level keys.
// Unknown top-level keys — log silently to debug output.
const schemaKeys = new Set(Object.keys(getSettingsSchema()));
for (const key of Object.keys(settings)) {
if (key === SETTINGS_VERSION_KEY) {
@ -178,8 +179,8 @@ function getSettingsFileKeyWarnings(
continue;
}
warnings.push(
`Warning: Unknown setting '${key}' will be ignored in ${settingsFilePath}.`,
debugLogger.warn(
`Unknown setting '${key}' will be ignored in ${settingsFilePath}.`,
);
}

View file

@ -589,7 +589,7 @@ const SETTINGS_SCHEMA = {
label: 'Skip Loop Detection',
category: 'Model',
requiresRestart: false,
default: false,
default: true,
description: 'Disable all loop detection checks (streaming and LLM).',
showInDialog: false,
},
@ -822,9 +822,9 @@ const SETTINGS_SCHEMA = {
label: 'Interactive Shell (PTY)',
category: 'Tools',
requiresRestart: true,
default: false,
default: true,
description:
'Use node-pty for an interactive shell experience. Fallback to child_process still applies.',
'Use node-pty for an interactive shell experience. Falls back to child_process if PTY is unavailable.',
showInDialog: true,
},
pager: {

View file

@ -158,9 +158,9 @@ describe('Trusted Folders Loading', () => {
expect(errors[0].message).toContain('Unexpected token');
});
it('should use GEMINI_CLI_TRUSTED_FOLDERS_PATH env var if set', () => {
it('should use QWEN_CODE_TRUSTED_FOLDERS_PATH env var if set', () => {
const customPath = '/custom/path/to/trusted_folders.json';
process.env['GEMINI_CLI_TRUSTED_FOLDERS_PATH'] = customPath;
process.env['QWEN_CODE_TRUSTED_FOLDERS_PATH'] = customPath;
(mockFsExistsSync as Mock).mockImplementation((p) => p === customPath);
const userContent = {
@ -180,7 +180,7 @@ describe('Trusted Folders Loading', () => {
]);
expect(errors).toEqual([]);
delete process.env['GEMINI_CLI_TRUSTED_FOLDERS_PATH'];
delete process.env['QWEN_CODE_TRUSTED_FOLDERS_PATH'];
});
it('setValue should update the user config and save it', () => {

View file

@ -22,8 +22,8 @@ export const SETTINGS_DIRECTORY_NAME = '.qwen';
export const USER_SETTINGS_DIR = path.join(homedir(), SETTINGS_DIRECTORY_NAME);
export function getTrustedFoldersPath(): string {
if (process.env['GEMINI_CLI_TRUSTED_FOLDERS_PATH']) {
return process.env['GEMINI_CLI_TRUSTED_FOLDERS_PATH'];
if (process.env['QWEN_CODE_TRUSTED_FOLDERS_PATH']) {
return process.env['QWEN_CODE_TRUSTED_FOLDERS_PATH'];
}
return path.join(USER_SETTINGS_DIR, TRUSTED_FOLDERS_FILENAME);
}