Add new folderTrust setting that the users can enable or disable (#5798)

This commit is contained in:
shrutip90 2025-08-07 14:06:17 -07:00 committed by GitHub
parent 3a3b138195
commit 53f8617b24
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 130 additions and 4 deletions

View File

@ -1042,6 +1042,58 @@ describe('loadCliConfig folderTrustFeature', () => {
}); });
}); });
describe('loadCliConfig folderTrust', () => {
const originalArgv = process.argv;
const originalEnv = { ...process.env };
beforeEach(() => {
vi.resetAllMocks();
vi.mocked(os.homedir).mockReturnValue('/mock/home/user');
process.env.GEMINI_API_KEY = 'test-api-key';
});
afterEach(() => {
process.argv = originalArgv;
process.env = originalEnv;
vi.restoreAllMocks();
});
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,
};
const argv = await parseArguments();
const config = await loadCliConfig(settings, [], 'test-session', argv);
expect(config.getFolderTrust()).toBe(false);
});
it('should be false if folderTrustFeature is true and folderTrust is false', async () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments();
const settings: Settings = { folderTrustFeature: true, folderTrust: false };
const config = await loadCliConfig(settings, [], 'test-session', argv);
expect(config.getFolderTrust()).toBe(false);
});
it('should be false if folderTrustFeature is false and folderTrust is true', async () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments();
const settings: Settings = { folderTrustFeature: false, folderTrust: true };
const config = await loadCliConfig(settings, [], 'test-session', argv);
expect(config.getFolderTrust()).toBe(false);
});
it('should be true when folderTrustFeature is true and folderTrust is true', async () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments();
const settings: Settings = { folderTrustFeature: true, folderTrust: true };
const config = await loadCliConfig(settings, [], 'test-session', argv);
expect(config.getFolderTrust()).toBe(true);
});
});
vi.mock('fs', async () => { vi.mock('fs', async () => {
const actualFs = await vi.importActual<typeof fs>('fs'); const actualFs = await vi.importActual<typeof fs>('fs');
const MOCK_CWD1 = process.cwd(); const MOCK_CWD1 = process.cwd();

View File

@ -314,6 +314,8 @@ export async function loadCliConfig(
argv.ideModeFeature ?? settings.ideModeFeature ?? false; argv.ideModeFeature ?? settings.ideModeFeature ?? false;
const folderTrustFeature = settings.folderTrustFeature ?? false; const folderTrustFeature = settings.folderTrustFeature ?? false;
const folderTrustSetting = settings.folderTrust ?? false;
const folderTrust = folderTrustFeature && folderTrustSetting;
const allExtensions = annotateActiveExtensions( const allExtensions = annotateActiveExtensions(
extensions, extensions,
@ -484,6 +486,7 @@ export async function loadCliConfig(
ideModeFeature, ideModeFeature,
chatCompression: settings.chatCompression, chatCompression: settings.chatCompression,
folderTrustFeature, folderTrustFeature,
folderTrust,
}); });
} }

View File

@ -310,6 +310,62 @@ describe('Settings Loading and Merging', () => {
}); });
}); });
it('should ignore folderTrust from workspace settings', () => {
(mockFsExistsSync as Mock).mockReturnValue(true);
const userSettingsContent = {
folderTrust: true,
};
const workspaceSettingsContent = {
folderTrust: false, // This should be ignored
};
const systemSettingsContent = {
// No folderTrust here
};
(fs.readFileSync as Mock).mockImplementation(
(p: fs.PathOrFileDescriptor) => {
if (p === getSystemSettingsPath())
return JSON.stringify(systemSettingsContent);
if (p === USER_SETTINGS_PATH)
return JSON.stringify(userSettingsContent);
if (p === MOCK_WORKSPACE_SETTINGS_PATH)
return JSON.stringify(workspaceSettingsContent);
return '{}';
},
);
const settings = loadSettings(MOCK_WORKSPACE_DIR);
expect(settings.merged.folderTrust).toBe(true); // User setting should be used
});
it('should use system folderTrust over user setting', () => {
(mockFsExistsSync as Mock).mockReturnValue(true);
const userSettingsContent = {
folderTrust: false,
};
const workspaceSettingsContent = {
folderTrust: true, // This should be ignored
};
const systemSettingsContent = {
folderTrust: true,
};
(fs.readFileSync as Mock).mockImplementation(
(p: fs.PathOrFileDescriptor) => {
if (p === getSystemSettingsPath())
return JSON.stringify(systemSettingsContent);
if (p === USER_SETTINGS_PATH)
return JSON.stringify(userSettingsContent);
if (p === MOCK_WORKSPACE_SETTINGS_PATH)
return JSON.stringify(workspaceSettingsContent);
return '{}';
},
);
const settings = loadSettings(MOCK_WORKSPACE_DIR);
expect(settings.merged.folderTrust).toBe(true); // System setting should be used
});
it('should handle contextFileName correctly when only in user settings', () => { it('should handle contextFileName correctly when only in user settings', () => {
(mockFsExistsSync as Mock).mockImplementation( (mockFsExistsSync as Mock).mockImplementation(
(p: fs.PathLike) => p === USER_SETTINGS_PATH, (p: fs.PathLike) => p === USER_SETTINGS_PATH,

View File

@ -113,10 +113,14 @@ export interface Settings {
// Flag to be removed post-launch. // Flag to be removed post-launch.
ideModeFeature?: boolean; ideModeFeature?: boolean;
folderTrustFeature?: boolean;
/// IDE mode setting configured via slash command toggle. /// IDE mode setting configured via slash command toggle.
ideMode?: boolean; ideMode?: boolean;
// Flag to be removed post-launch.
folderTrustFeature?: boolean;
// Setting to track whether Folder trust is enabled.
folderTrust?: boolean;
// Setting to track if the user has seen the IDE integration nudge. // Setting to track if the user has seen the IDE integration nudge.
hasSeenIdeIntegrationNudge?: boolean; hasSeenIdeIntegrationNudge?: boolean;
@ -178,9 +182,13 @@ export class LoadedSettings {
const user = this.user.settings; const user = this.user.settings;
const workspace = this.workspace.settings; const workspace = this.workspace.settings;
// folderTrust is not supported at workspace level.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { folderTrust, ...workspaceWithoutFolderTrust } = workspace;
return { return {
...user, ...user,
...workspace, ...workspaceWithoutFolderTrust,
...system, ...system,
customThemes: { customThemes: {
...(user.customThemes || {}), ...(user.customThemes || {}),

View File

@ -193,6 +193,7 @@ export interface ConfigParameters {
summarizeToolOutput?: Record<string, SummarizeToolOutputSettings>; summarizeToolOutput?: Record<string, SummarizeToolOutputSettings>;
ideModeFeature?: boolean; ideModeFeature?: boolean;
folderTrustFeature?: boolean; folderTrustFeature?: boolean;
folderTrust?: boolean;
ideMode?: boolean; ideMode?: boolean;
loadMemoryFromIncludeDirectories?: boolean; loadMemoryFromIncludeDirectories?: boolean;
chatCompression?: ChatCompressionSettings; chatCompression?: ChatCompressionSettings;
@ -240,6 +241,7 @@ export class Config {
private readonly noBrowser: boolean; private readonly noBrowser: boolean;
private readonly ideModeFeature: boolean; private readonly ideModeFeature: boolean;
private readonly folderTrustFeature: boolean; private readonly folderTrustFeature: boolean;
private readonly folderTrust: boolean;
private ideMode: boolean; private ideMode: boolean;
private ideClient: IdeClient; private ideClient: IdeClient;
private inFallbackMode = false; private inFallbackMode = false;
@ -314,6 +316,7 @@ export class Config {
this.summarizeToolOutput = params.summarizeToolOutput; this.summarizeToolOutput = params.summarizeToolOutput;
this.ideModeFeature = params.ideModeFeature ?? false; this.ideModeFeature = params.ideModeFeature ?? false;
this.folderTrustFeature = params.folderTrustFeature ?? false; this.folderTrustFeature = params.folderTrustFeature ?? false;
this.folderTrust = params.folderTrust ?? false;
this.ideMode = params.ideMode ?? false; this.ideMode = params.ideMode ?? false;
this.ideClient = IdeClient.getInstance(); this.ideClient = IdeClient.getInstance();
if (this.ideMode && this.ideModeFeature) { if (this.ideMode && this.ideModeFeature) {
@ -648,12 +651,16 @@ export class Config {
return this.ideModeFeature; return this.ideModeFeature;
} }
getIdeMode(): boolean {
return this.ideMode;
}
getFolderTrustFeature(): boolean { getFolderTrustFeature(): boolean {
return this.folderTrustFeature; return this.folderTrustFeature;
} }
getIdeMode(): boolean { getFolderTrust(): boolean {
return this.ideMode; return this.folderTrust;
} }
setIdeMode(value: boolean): void { setIdeMode(value: boolean): void {