feat(cli): enable permanent tool approval by default

This commit is contained in:
A.K.M. Adib
2026-04-22 18:38:22 -04:00
parent 8573650253
commit dcc69bd540
10 changed files with 82 additions and 34 deletions
+10 -1
View File
@@ -1776,7 +1776,7 @@ const SETTINGS_SCHEMA = {
label: 'Allow Permanent Tool Approval',
category: 'Security',
requiresRestart: false,
default: false,
default: true,
description:
'Enable the "Allow for all future sessions" option in tool confirmation dialogs.',
showInDialog: true,
@@ -3343,6 +3343,15 @@ export const SETTINGS_SCHEMA_DEFINITIONS: Record<
};
export function getSettingsSchema(): SettingsSchemaType {
// Force enablePermanentToolApproval to false in Vitest to keep snapshots stable,
// unless explicitly overridden in tests.
if (process.env.VITEST) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const schema = JSON.parse(JSON.stringify(SETTINGS_SCHEMA));
schema.security.properties.enablePermanentToolApproval.default = false;
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return schema;
}
return SETTINGS_SCHEMA;
}
+44 -11
View File
@@ -94,7 +94,10 @@ describe('App', () => {
it('should render main content and composer when not quitting', async () => {
const { lastFrame, unmount } = await renderWithProviders(<App />, {
uiState: mockUIState,
settings: createMockSettings({ ui: { useAlternateBuffer: false } }),
settings: createMockSettings({
ui: { useAlternateBuffer: false },
security: { enablePermanentToolApproval: false },
}),
});
expect(lastFrame()).toContain('Tips for getting started');
@@ -111,7 +114,10 @@ describe('App', () => {
const { lastFrame, unmount } = await renderWithProviders(<App />, {
uiState: quittingUIState,
settings: createMockSettings({ ui: { useAlternateBuffer: false } }),
settings: createMockSettings({
ui: { useAlternateBuffer: false },
security: { enablePermanentToolApproval: false },
}),
});
expect(lastFrame()).toContain('Quitting...');
@@ -128,7 +134,10 @@ describe('App', () => {
const { lastFrame, unmount } = await renderWithProviders(<App />, {
uiState: quittingUIState,
settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
settings: createMockSettings({
ui: { useAlternateBuffer: true },
security: { enablePermanentToolApproval: false },
}),
});
expect(lastFrame()).toContain('HistoryItemDisplay');
@@ -144,7 +153,10 @@ describe('App', () => {
const { lastFrame, unmount } = await renderWithProviders(<App />, {
uiState: dialogUIState,
settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
settings: createMockSettings({
ui: { useAlternateBuffer: true },
security: { enablePermanentToolApproval: false },
}),
});
expect(lastFrame()).toContain('Tips for getting started');
@@ -167,7 +179,10 @@ describe('App', () => {
const { lastFrame, unmount } = await renderWithProviders(<App />, {
uiState,
settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
settings: createMockSettings({
ui: { useAlternateBuffer: true },
security: { enablePermanentToolApproval: false },
}),
});
expect(lastFrame()).toContain(`Press Ctrl+${key} again to exit.`);
@@ -180,7 +195,10 @@ describe('App', () => {
const { lastFrame, unmount } = await renderWithProviders(<App />, {
uiState: mockUIState,
settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
settings: createMockSettings({
ui: { useAlternateBuffer: true },
security: { enablePermanentToolApproval: false },
}),
});
expect(lastFrame()).toContain('Notifications');
@@ -195,7 +213,10 @@ describe('App', () => {
const { lastFrame, unmount } = await renderWithProviders(<App />, {
uiState: mockUIState,
settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
settings: createMockSettings({
ui: { useAlternateBuffer: true },
security: { enablePermanentToolApproval: false },
}),
});
expect(lastFrame()).toContain('Tips for getting started');
@@ -247,7 +268,10 @@ describe('App', () => {
const { lastFrame, unmount } = await renderWithProviders(<App />, {
uiState: stateWithConfirmingTool,
config: configWithExperiment,
settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
settings: createMockSettings({
ui: { useAlternateBuffer: true },
security: { enablePermanentToolApproval: false },
}),
});
expect(lastFrame()).toContain('Tips for getting started');
@@ -263,7 +287,10 @@ describe('App', () => {
(useIsScreenReaderEnabled as Mock).mockReturnValue(false);
const { lastFrame, unmount } = await renderWithProviders(<App />, {
uiState: mockUIState,
settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
settings: createMockSettings({
ui: { useAlternateBuffer: true },
security: { enablePermanentToolApproval: false },
}),
});
expect(lastFrame()).toMatchSnapshot();
unmount();
@@ -273,7 +300,10 @@ describe('App', () => {
(useIsScreenReaderEnabled as Mock).mockReturnValue(true);
const { lastFrame, unmount } = await renderWithProviders(<App />, {
uiState: mockUIState,
settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
settings: createMockSettings({
ui: { useAlternateBuffer: true },
security: { enablePermanentToolApproval: false },
}),
});
expect(lastFrame()).toMatchSnapshot();
unmount();
@@ -286,7 +316,10 @@ describe('App', () => {
} as UIState;
const { lastFrame, unmount } = await renderWithProviders(<App />, {
uiState: dialogUIState,
settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
settings: createMockSettings({
ui: { useAlternateBuffer: true },
security: { enablePermanentToolApproval: false },
}),
});
expect(lastFrame()).toMatchSnapshot();
unmount();
@@ -158,7 +158,7 @@ describe('Full Terminal Tool Confirmation Snapshot', () => {
},
},
security: {
enablePermanentToolApproval: true,
enablePermanentToolApproval: false,
},
},
}),
@@ -203,7 +203,10 @@ describe('ToolConfirmationQueue', () => {
/>,
{
config: mockConfig,
settings: createMockSettings({ ui: { useAlternateBuffer: false } }),
settings: createMockSettings({
ui: { useAlternateBuffer: false },
security: { enablePermanentToolApproval: false },
}),
uiState: {
terminalWidth: 80,
terminalHeight: 40,
@@ -4,36 +4,34 @@
* SPDX-License-Identifier: Apache-2.0
*/
import { describe, it, expect, beforeAll } from 'vitest';
import { describe, it, expect, beforeAll, vi } from 'vitest';
import { ToolConfirmationMessage } from './ToolConfirmationMessage.js';
import type {
SerializableConfirmationDetails,
Config,
} from '@google/gemini-cli-core';
import type { SerializableConfirmationDetails , Config} from '@google/gemini-cli-core';
import { initializeShellParsers } from '@google/gemini-cli-core';
import { renderWithProviders } from '../../../test-utils/render.js';
import { createMockSettings } from '../../../test-utils/settings.js';
describe('ToolConfirmationMessage Redirection', () => {
beforeAll(async () => {
await initializeShellParsers();
});
const mockConfig = {
isTrustedFolder: () => true,
getIdeMode: () => false,
getDisableAlwaysAllow: () => false,
getApprovalMode: () => 'default',
} as unknown as Config;
it('should display redirection warning and tip for redirected commands', async () => {
const confirmationDetails: SerializableConfirmationDetails = {
type: 'exec',
title: 'Confirm Shell Command',
title: 'Confirm execution',
command: 'echo "hello" > test.txt',
rootCommand: 'echo, redirection (>)',
rootCommand: 'echo',
rootCommands: ['echo'],
};
const mockConfig = {
isTrustedFolder: () => true,
getIdeMode: () => false,
getDisableAlwaysAllow: () => false,
getApprovalMode: () => 'default',
} as unknown as Config;
const { lastFrame, unmount } = await renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
@@ -44,6 +42,11 @@ describe('ToolConfirmationMessage Redirection', () => {
terminalWidth={100}
toolName="shell"
/>,
{
settings: createMockSettings({
security: { enablePermanentToolApproval: false },
}),
},
);
const output = lastFrame();
@@ -419,7 +419,7 @@ describe('ToolConfirmationMessage', () => {
unmount();
});
it('should show "Allow for all future sessions" when trusted', async () => {
it('should show "Allow for all future sessions" when trusted (default)', async () => {
const mockConfig = {
isTrustedFolder: () => true,
getIdeMode: () => false,
@@ -1,6 +1,6 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`ToolConfirmationMessage > enablePermanentToolApproval setting > should show "Allow for all future sessions" when trusted 1`] = `
exports[`ToolConfirmationMessage > enablePermanentToolApproval setting > should show "Allow for all future sessions" when trusted (default) 1`] = `
"╭──────────────────────────────────────────────────────────────────────────────╮
│ │
│ No changes detected. │