feat: Show untrusted status in the Footer (#6210)

Co-authored-by: Jacob Richman <jacob314@gmail.com>
This commit is contained in:
shrutip90
2025-08-14 11:15:48 -07:00
committed by GitHub
parent 69d666cfaf
commit 69c5582723
10 changed files with 221 additions and 60 deletions

View File

@@ -1809,7 +1809,14 @@ describe('loadCliConfig trustedFolder', () => {
description,
} of testCases) {
it(`should be correct for: ${description}`, async () => {
(isWorkspaceTrusted as vi.Mock).mockReturnValue(mockTrustValue);
(isWorkspaceTrusted as vi.Mock).mockImplementation(
(settings: Settings) => {
const featureIsEnabled =
(settings.folderTrustFeature ?? false) &&
(settings.folderTrust ?? true);
return featureIsEnabled ? mockTrustValue : true;
},
);
const argv = await parseArguments();
const settings: Settings = { folderTrustFeature, folderTrust };
const config = await loadCliConfig(settings, [], 'test-session', argv);

View File

@@ -321,7 +321,7 @@ export async function loadCliConfig(
const folderTrustFeature = settings.folderTrustFeature ?? false;
const folderTrustSetting = settings.folderTrust ?? true;
const folderTrust = folderTrustFeature && folderTrustSetting;
const trustedFolder = folderTrust ? isWorkspaceTrusted() : true;
const trustedFolder = isWorkspaceTrusted(settings);
const allExtensions = annotateActiveExtensions(
extensions,

View File

@@ -35,6 +35,7 @@ import {
TrustLevel,
isWorkspaceTrusted,
} from './trustedFolders.js';
import { Settings } from './settings.js';
vi.mock('fs', async (importOriginal) => {
const actualFs = await importOriginal<typeof fs>();
@@ -130,6 +131,10 @@ describe('Trusted Folders Loading', () => {
describe('isWorkspaceTrusted', () => {
let mockCwd: string;
const mockRules: Record<string, TrustLevel> = {};
const mockSettings: Settings = {
folderTrustFeature: true,
folderTrust: true,
};
beforeEach(() => {
vi.spyOn(process, 'cwd').mockImplementation(() => mockCwd);
@@ -153,51 +158,51 @@ describe('isWorkspaceTrusted', () => {
it('should return true for a directly trusted folder', () => {
mockCwd = '/home/user/projectA';
mockRules['/home/user/projectA'] = TrustLevel.TRUST_FOLDER;
expect(isWorkspaceTrusted()).toBe(true);
expect(isWorkspaceTrusted(mockSettings)).toBe(true);
});
it('should return true for a child of a trusted folder', () => {
mockCwd = '/home/user/projectA/src';
mockRules['/home/user/projectA'] = TrustLevel.TRUST_FOLDER;
expect(isWorkspaceTrusted()).toBe(true);
expect(isWorkspaceTrusted(mockSettings)).toBe(true);
});
it('should return true for a child of a trusted parent folder', () => {
mockCwd = '/home/user/projectB';
mockRules['/home/user/projectB/somefile.txt'] = TrustLevel.TRUST_PARENT;
expect(isWorkspaceTrusted()).toBe(true);
expect(isWorkspaceTrusted(mockSettings)).toBe(true);
});
it('should return false for a directly untrusted folder', () => {
mockCwd = '/home/user/untrusted';
mockRules['/home/user/untrusted'] = TrustLevel.DO_NOT_TRUST;
expect(isWorkspaceTrusted()).toBe(false);
expect(isWorkspaceTrusted(mockSettings)).toBe(false);
});
it('should return undefined for a child of an untrusted folder', () => {
mockCwd = '/home/user/untrusted/src';
mockRules['/home/user/untrusted'] = TrustLevel.DO_NOT_TRUST;
expect(isWorkspaceTrusted()).toBeUndefined();
expect(isWorkspaceTrusted(mockSettings)).toBeUndefined();
});
it('should return undefined when no rules match', () => {
mockCwd = '/home/user/other';
mockRules['/home/user/projectA'] = TrustLevel.TRUST_FOLDER;
mockRules['/home/user/untrusted'] = TrustLevel.DO_NOT_TRUST;
expect(isWorkspaceTrusted()).toBeUndefined();
expect(isWorkspaceTrusted(mockSettings)).toBeUndefined();
});
it('should prioritize trust over distrust', () => {
mockCwd = '/home/user/projectA/untrusted';
mockRules['/home/user/projectA'] = TrustLevel.TRUST_FOLDER;
mockRules['/home/user/projectA/untrusted'] = TrustLevel.DO_NOT_TRUST;
expect(isWorkspaceTrusted()).toBe(true);
expect(isWorkspaceTrusted(mockSettings)).toBe(true);
});
it('should handle path normalization', () => {
mockCwd = '/home/user/projectA';
mockRules[`/home/user/../user/${path.basename('/home/user/projectA')}`] =
TrustLevel.TRUST_FOLDER;
expect(isWorkspaceTrusted()).toBe(true);
expect(isWorkspaceTrusted(mockSettings)).toBe(true);
});
});

View File

@@ -8,6 +8,7 @@ import * as fs from 'fs';
import * as path from 'path';
import { homedir } from 'os';
import { getErrorMessage, isWithinRoot } from '@google/gemini-cli-core';
import { Settings } from './settings.js';
import stripJsonComments from 'strip-json-comments';
export const TRUSTED_FOLDERS_FILENAME = 'trustedFolders.json';
@@ -109,7 +110,15 @@ export function saveTrustedFolders(
}
}
export function isWorkspaceTrusted(): boolean | undefined {
export function isWorkspaceTrusted(settings: Settings): boolean | undefined {
const folderTrustFeature = settings.folderTrustFeature ?? false;
const folderTrustSetting = settings.folderTrust ?? true;
const folderTrustEnabled = folderTrustFeature && folderTrustSetting;
if (!folderTrustEnabled) {
return true;
}
const { rules, errors } = loadTrustedFolders();
if (errors.length > 0) {