refactor: refactor settings to a nested structure (#7244)

This commit is contained in:
Gal Zahavi
2025-08-27 18:39:45 -07:00
committed by GitHub
parent b8a7bfd136
commit f22263c9e8
41 changed files with 2852 additions and 1424 deletions

View File

@@ -333,7 +333,7 @@ describe('loadCliConfig', () => {
it('should set showMemoryUsage to false by default from settings if CLI flag is not present', async () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments({} as Settings);
const settings: Settings = { showMemoryUsage: false };
const settings: Settings = { ui: { showMemoryUsage: false } };
const config = await loadCliConfig(settings, [], 'test-session', argv);
expect(config.getShowMemoryUsage()).toBe(false);
});
@@ -341,7 +341,7 @@ describe('loadCliConfig', () => {
it('should prioritize CLI flag over settings for showMemoryUsage (CLI true, settings false)', async () => {
process.argv = ['node', 'script.js', '--show-memory-usage'];
const argv = await parseArguments({} as Settings);
const settings: Settings = { showMemoryUsage: false };
const settings: Settings = { ui: { showMemoryUsage: false } };
const config = await loadCliConfig(settings, [], 'test-session', argv);
expect(config.getShowMemoryUsage()).toBe(true);
});
@@ -804,7 +804,7 @@ describe('mergeExcludeTools', () => {
});
it('should merge excludeTools from settings and extensions', async () => {
const settings: Settings = { excludeTools: ['tool1', 'tool2'] };
const settings: Settings = { tools: { exclude: ['tool1', 'tool2'] } };
const extensions: Extension[] = [
{
path: '/path/to/ext1',
@@ -840,7 +840,7 @@ describe('mergeExcludeTools', () => {
});
it('should handle overlapping excludeTools between settings and extensions', async () => {
const settings: Settings = { excludeTools: ['tool1', 'tool2'] };
const settings: Settings = { tools: { exclude: ['tool1', 'tool2'] } };
const extensions: Extension[] = [
{
path: '/path/to/ext1',
@@ -867,7 +867,7 @@ describe('mergeExcludeTools', () => {
});
it('should handle overlapping excludeTools between extensions', async () => {
const settings: Settings = { excludeTools: ['tool1'] };
const settings: Settings = { tools: { exclude: ['tool1'] } };
const extensions: Extension[] = [
{
path: '/path/to/ext1',
@@ -935,7 +935,7 @@ describe('mergeExcludeTools', () => {
it('should handle settings with excludeTools but no extensions', async () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments({} as Settings);
const settings: Settings = { excludeTools: ['tool1', 'tool2'] };
const settings: Settings = { tools: { exclude: ['tool1', 'tool2'] } };
const extensions: Extension[] = [];
const config = await loadCliConfig(
settings,
@@ -977,7 +977,7 @@ describe('mergeExcludeTools', () => {
});
it('should not modify the original settings object', async () => {
const settings: Settings = { excludeTools: ['tool1'] };
const settings: Settings = { tools: { exclude: ['tool1'] } };
const extensions: Extension[] = [
{
path: '/path/to/ext',
@@ -1166,7 +1166,7 @@ describe('Approval mode tool exclusion logic', () => {
'test',
];
const argv = await parseArguments({} as Settings);
const settings: Settings = { excludeTools: ['custom_tool'] };
const settings: Settings = { tools: { exclude: ['custom_tool'] } };
const extensions: Extension[] = [];
const config = await loadCliConfig(
@@ -1297,7 +1297,7 @@ describe('loadCliConfig with allowed-mcp-server-names', () => {
const argv = await parseArguments({} as Settings);
const settings: Settings = {
...baseSettings,
allowMCPServers: ['server1', 'server2'],
mcp: { allowed: ['server1', 'server2'] },
};
const config = await loadCliConfig(settings, [], 'test-session', argv);
expect(config.getMcpServers()).toEqual({
@@ -1311,7 +1311,7 @@ describe('loadCliConfig with allowed-mcp-server-names', () => {
const argv = await parseArguments({} as Settings);
const settings: Settings = {
...baseSettings,
excludeMCPServers: ['server1', 'server2'],
mcp: { excluded: ['server1', 'server2'] },
};
const config = await loadCliConfig(settings, [], 'test-session', argv);
expect(config.getMcpServers()).toEqual({
@@ -1324,8 +1324,10 @@ describe('loadCliConfig with allowed-mcp-server-names', () => {
const argv = await parseArguments({} as Settings);
const settings: Settings = {
...baseSettings,
excludeMCPServers: ['server1'],
allowMCPServers: ['server1', 'server2'],
mcp: {
excluded: ['server1'],
allowed: ['server1', 'server2'],
},
};
const config = await loadCliConfig(settings, [], 'test-session', argv);
expect(config.getMcpServers()).toEqual({
@@ -1343,14 +1345,40 @@ describe('loadCliConfig with allowed-mcp-server-names', () => {
const argv = await parseArguments({} as Settings);
const settings: Settings = {
...baseSettings,
excludeMCPServers: ['server1'],
allowMCPServers: ['server2'],
mcp: {
excluded: ['server1'],
allowed: ['server2'],
},
};
const config = await loadCliConfig(settings, [], 'test-session', argv);
expect(config.getMcpServers()).toEqual({
server1: { url: 'http://localhost:8080' },
});
});
it('should prioritize CLI flag over both allowed and excluded settings', async () => {
process.argv = [
'node',
'script.js',
'--allowed-mcp-server-names',
'server2',
'--allowed-mcp-server-names',
'server3',
];
const argv = await parseArguments({} as Settings);
const settings: Settings = {
...baseSettings,
mcp: {
allowed: ['server1', 'server2'], // Should be ignored
excluded: ['server3'], // Should be ignored
},
};
const config = await loadCliConfig(settings, [], 'test-session', argv);
expect(config.getMcpServers()).toEqual({
server2: { url: 'http://localhost:8081' },
server3: { url: 'http://localhost:8082' },
});
});
});
describe('loadCliConfig extensions', () => {
@@ -1403,7 +1431,9 @@ describe('loadCliConfig model selection', () => {
const argv = await parseArguments({} as Settings);
const config = await loadCliConfig(
{
model: 'gemini-9001-ultra',
model: {
name: 'gemini-9001-ultra',
},
},
[],
'test-session',
@@ -1433,7 +1463,9 @@ describe('loadCliConfig model selection', () => {
const argv = await parseArguments({} as Settings);
const config = await loadCliConfig(
{
model: 'gemini-9001-ultra',
model: {
name: 'gemini-9001-ultra',
},
},
[],
'test-session',
@@ -1485,7 +1517,9 @@ describe('loadCliConfig folderTrustFeature', () => {
it('should be true when settings.folderTrustFeature is true', async () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments({} as Settings);
const settings: Settings = { folderTrustFeature: true };
const settings: Settings = {
security: { folderTrust: { featureEnabled: true } },
};
const config = await loadCliConfig(settings, [], 'test-session', argv);
expect(config.getFolderTrustFeature()).toBe(true);
});
@@ -1509,8 +1543,12 @@ describe('loadCliConfig folderTrust', () => {
it('should be false if folderTrustFeature is false and folderTrust is false', async () => {
process.argv = ['node', 'script.js'];
const settings: Settings = {
folderTrustFeature: false,
folderTrust: false,
security: {
folderTrust: {
featureEnabled: false,
enabled: false,
},
},
};
const argv = await parseArguments({} as Settings);
const config = await loadCliConfig(settings, [], 'test-session', argv);
@@ -1520,7 +1558,14 @@ describe('loadCliConfig folderTrust', () => {
it('should be false if folderTrustFeature is true and folderTrust is false', async () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments({} as Settings);
const settings: Settings = { folderTrustFeature: true, folderTrust: false };
const settings: Settings = {
security: {
folderTrust: {
featureEnabled: true,
enabled: false,
},
},
};
const config = await loadCliConfig(settings, [], 'test-session', argv);
expect(config.getFolderTrust()).toBe(false);
});
@@ -1528,7 +1573,14 @@ describe('loadCliConfig folderTrust', () => {
it('should be false if folderTrustFeature is false and folderTrust is true', async () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments({} as Settings);
const settings: Settings = { folderTrustFeature: false, folderTrust: true };
const settings: Settings = {
security: {
folderTrust: {
featureEnabled: false,
enabled: true,
},
},
};
const config = await loadCliConfig(settings, [], 'test-session', argv);
expect(config.getFolderTrust()).toBe(false);
});
@@ -1536,7 +1588,14 @@ describe('loadCliConfig folderTrust', () => {
it('should be true when folderTrustFeature is true and folderTrust is true', async () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments({} as Settings);
const settings: Settings = { folderTrustFeature: true, folderTrust: true };
const settings: Settings = {
security: {
folderTrust: {
featureEnabled: true,
enabled: true,
},
},
};
const config = await loadCliConfig(settings, [], 'test-session', argv);
expect(config.getFolderTrust()).toBe(true);
});
@@ -1570,11 +1629,13 @@ describe('loadCliConfig with includeDirectories', () => {
];
const argv = await parseArguments({} as Settings);
const settings: Settings = {
includeDirectories: [
path.resolve(path.sep, 'settings', 'path1'),
path.join(os.homedir(), 'settings', 'path2'),
path.join(mockCwd, 'settings', 'path3'),
],
context: {
includeDirectories: [
path.resolve(path.sep, 'settings', 'path1'),
path.join(os.homedir(), 'settings', 'path2'),
path.join(mockCwd, 'settings', 'path3'),
],
},
};
const config = await loadCliConfig(settings, [], 'test-session', argv);
const expected = [
@@ -1613,8 +1674,10 @@ describe('loadCliConfig chatCompression', () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments({} as Settings);
const settings: Settings = {
chatCompression: {
contextPercentageThreshold: 0.5,
model: {
chatCompression: {
contextPercentageThreshold: 0.5,
},
},
};
const config = await loadCliConfig(settings, [], 'test-session', argv);
@@ -1658,7 +1721,7 @@ describe('loadCliConfig useRipgrep', () => {
it('should be true when useRipgrep is set to true in settings', async () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments({} as Settings);
const settings: Settings = { useRipgrep: true };
const settings: Settings = { tools: { useRipgrep: true } };
const config = await loadCliConfig(settings, [], 'test-session', argv);
expect(config.getUseRipgrep()).toBe(true);
});
@@ -1666,7 +1729,7 @@ describe('loadCliConfig useRipgrep', () => {
it('should be false when useRipgrep is explicitly set to false in settings', async () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments({} as Settings);
const settings: Settings = { useRipgrep: false };
const settings: Settings = { tools: { useRipgrep: false } };
const config = await loadCliConfig(settings, [], 'test-session', argv);
expect(config.getUseRipgrep()).toBe(false);
});
@@ -2002,13 +2065,26 @@ describe('loadCliConfig trustedFolder', () => {
} of testCases) {
it(`should be correct for: ${description}`, async () => {
(isWorkspaceTrusted as Mock).mockImplementation((settings: Settings) => {
const featureIsEnabled =
(settings.folderTrustFeature ?? false) &&
(settings.folderTrust ?? true);
return featureIsEnabled ? mockTrustValue : true;
const folderTrustFeature =
settings.security?.folderTrust?.featureEnabled ?? false;
const folderTrustSetting =
settings.security?.folderTrust?.enabled ?? true;
const folderTrustEnabled = folderTrustFeature && folderTrustSetting;
if (!folderTrustEnabled) {
return true;
}
return mockTrustValue; // This is the part that comes from the test case
});
const argv = await parseArguments({} as Settings);
const settings: Settings = { folderTrustFeature, folderTrust };
const settings: Settings = {
security: {
folderTrust: {
featureEnabled: folderTrustFeature,
enabled: folderTrust,
},
},
};
const config = await loadCliConfig(settings, [], 'test-session', argv);
expect(config.getFolderTrust()).toBe(expectedFolderTrust);