mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-12 21:03:05 -07:00
fix: remove ask_user tool from non-interactive modes (#18154)
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
|||||||
WRITE_FILE_TOOL_NAME,
|
WRITE_FILE_TOOL_NAME,
|
||||||
EDIT_TOOL_NAME,
|
EDIT_TOOL_NAME,
|
||||||
WEB_FETCH_TOOL_NAME,
|
WEB_FETCH_TOOL_NAME,
|
||||||
|
ASK_USER_TOOL_NAME,
|
||||||
type ExtensionLoader,
|
type ExtensionLoader,
|
||||||
debugLogger,
|
debugLogger,
|
||||||
ApprovalMode,
|
ApprovalMode,
|
||||||
@@ -1014,7 +1015,9 @@ describe('mergeExcludeTools', () => {
|
|||||||
process.argv = ['node', 'script.js', '-p', 'test'];
|
process.argv = ['node', 'script.js', '-p', 'test'];
|
||||||
const argv = await parseArguments(createTestMergedSettings());
|
const argv = await parseArguments(createTestMergedSettings());
|
||||||
const config = await loadCliConfig(settings, 'test-session', argv);
|
const config = await loadCliConfig(settings, 'test-session', argv);
|
||||||
expect(config.getExcludeTools()).toEqual(defaultExcludes);
|
expect(config.getExcludeTools()).toEqual(
|
||||||
|
new Set([...defaultExcludes, ASK_USER_TOOL_NAME]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle settings with excludeTools but no extensions', async () => {
|
it('should handle settings with excludeTools but no extensions', async () => {
|
||||||
@@ -1098,6 +1101,7 @@ describe('Approval mode tool exclusion logic', () => {
|
|||||||
expect(excludedTools).toContain(SHELL_TOOL_NAME);
|
expect(excludedTools).toContain(SHELL_TOOL_NAME);
|
||||||
expect(excludedTools).toContain(EDIT_TOOL_NAME);
|
expect(excludedTools).toContain(EDIT_TOOL_NAME);
|
||||||
expect(excludedTools).toContain(WRITE_FILE_TOOL_NAME);
|
expect(excludedTools).toContain(WRITE_FILE_TOOL_NAME);
|
||||||
|
expect(excludedTools).toContain(ASK_USER_TOOL_NAME);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should exclude all interactive tools in non-interactive mode with explicit default approval mode', async () => {
|
it('should exclude all interactive tools in non-interactive mode with explicit default approval mode', async () => {
|
||||||
@@ -1118,6 +1122,7 @@ describe('Approval mode tool exclusion logic', () => {
|
|||||||
expect(excludedTools).toContain(SHELL_TOOL_NAME);
|
expect(excludedTools).toContain(SHELL_TOOL_NAME);
|
||||||
expect(excludedTools).toContain(EDIT_TOOL_NAME);
|
expect(excludedTools).toContain(EDIT_TOOL_NAME);
|
||||||
expect(excludedTools).toContain(WRITE_FILE_TOOL_NAME);
|
expect(excludedTools).toContain(WRITE_FILE_TOOL_NAME);
|
||||||
|
expect(excludedTools).toContain(ASK_USER_TOOL_NAME);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should exclude only shell tools in non-interactive mode with auto_edit approval mode', async () => {
|
it('should exclude only shell tools in non-interactive mode with auto_edit approval mode', async () => {
|
||||||
@@ -1138,9 +1143,10 @@ describe('Approval mode tool exclusion logic', () => {
|
|||||||
expect(excludedTools).toContain(SHELL_TOOL_NAME);
|
expect(excludedTools).toContain(SHELL_TOOL_NAME);
|
||||||
expect(excludedTools).not.toContain(EDIT_TOOL_NAME);
|
expect(excludedTools).not.toContain(EDIT_TOOL_NAME);
|
||||||
expect(excludedTools).not.toContain(WRITE_FILE_TOOL_NAME);
|
expect(excludedTools).not.toContain(WRITE_FILE_TOOL_NAME);
|
||||||
|
expect(excludedTools).toContain(ASK_USER_TOOL_NAME);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should exclude no interactive tools in non-interactive mode with yolo approval mode', async () => {
|
it('should exclude only ask_user in non-interactive mode with yolo approval mode', async () => {
|
||||||
process.argv = [
|
process.argv = [
|
||||||
'node',
|
'node',
|
||||||
'script.js',
|
'script.js',
|
||||||
@@ -1158,6 +1164,7 @@ describe('Approval mode tool exclusion logic', () => {
|
|||||||
expect(excludedTools).not.toContain(SHELL_TOOL_NAME);
|
expect(excludedTools).not.toContain(SHELL_TOOL_NAME);
|
||||||
expect(excludedTools).not.toContain(EDIT_TOOL_NAME);
|
expect(excludedTools).not.toContain(EDIT_TOOL_NAME);
|
||||||
expect(excludedTools).not.toContain(WRITE_FILE_TOOL_NAME);
|
expect(excludedTools).not.toContain(WRITE_FILE_TOOL_NAME);
|
||||||
|
expect(excludedTools).toContain(ASK_USER_TOOL_NAME);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should exclude all interactive tools in non-interactive mode with plan approval mode', async () => {
|
it('should exclude all interactive tools in non-interactive mode with plan approval mode', async () => {
|
||||||
@@ -1182,9 +1189,10 @@ describe('Approval mode tool exclusion logic', () => {
|
|||||||
expect(excludedTools).toContain(SHELL_TOOL_NAME);
|
expect(excludedTools).toContain(SHELL_TOOL_NAME);
|
||||||
expect(excludedTools).toContain(EDIT_TOOL_NAME);
|
expect(excludedTools).toContain(EDIT_TOOL_NAME);
|
||||||
expect(excludedTools).toContain(WRITE_FILE_TOOL_NAME);
|
expect(excludedTools).toContain(WRITE_FILE_TOOL_NAME);
|
||||||
|
expect(excludedTools).toContain(ASK_USER_TOOL_NAME);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should exclude no interactive tools in non-interactive mode with legacy yolo flag', async () => {
|
it('should exclude only ask_user in non-interactive mode with legacy yolo flag', async () => {
|
||||||
process.argv = ['node', 'script.js', '--yolo', '-p', 'test'];
|
process.argv = ['node', 'script.js', '--yolo', '-p', 'test'];
|
||||||
const argv = await parseArguments(createTestMergedSettings());
|
const argv = await parseArguments(createTestMergedSettings());
|
||||||
const settings = createTestMergedSettings();
|
const settings = createTestMergedSettings();
|
||||||
@@ -1195,6 +1203,7 @@ describe('Approval mode tool exclusion logic', () => {
|
|||||||
expect(excludedTools).not.toContain(SHELL_TOOL_NAME);
|
expect(excludedTools).not.toContain(SHELL_TOOL_NAME);
|
||||||
expect(excludedTools).not.toContain(EDIT_TOOL_NAME);
|
expect(excludedTools).not.toContain(EDIT_TOOL_NAME);
|
||||||
expect(excludedTools).not.toContain(WRITE_FILE_TOOL_NAME);
|
expect(excludedTools).not.toContain(WRITE_FILE_TOOL_NAME);
|
||||||
|
expect(excludedTools).toContain(ASK_USER_TOOL_NAME);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not exclude interactive tools in interactive mode regardless of approval mode', async () => {
|
it('should not exclude interactive tools in interactive mode regardless of approval mode', async () => {
|
||||||
@@ -1219,6 +1228,7 @@ describe('Approval mode tool exclusion logic', () => {
|
|||||||
expect(excludedTools).not.toContain(SHELL_TOOL_NAME);
|
expect(excludedTools).not.toContain(SHELL_TOOL_NAME);
|
||||||
expect(excludedTools).not.toContain(EDIT_TOOL_NAME);
|
expect(excludedTools).not.toContain(EDIT_TOOL_NAME);
|
||||||
expect(excludedTools).not.toContain(WRITE_FILE_TOOL_NAME);
|
expect(excludedTools).not.toContain(WRITE_FILE_TOOL_NAME);
|
||||||
|
expect(excludedTools).not.toContain(ASK_USER_TOOL_NAME);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1777,6 +1787,7 @@ describe('loadCliConfig tool exclusions', () => {
|
|||||||
expect(config.getExcludeTools()).not.toContain('run_shell_command');
|
expect(config.getExcludeTools()).not.toContain('run_shell_command');
|
||||||
expect(config.getExcludeTools()).not.toContain('replace');
|
expect(config.getExcludeTools()).not.toContain('replace');
|
||||||
expect(config.getExcludeTools()).not.toContain('write_file');
|
expect(config.getExcludeTools()).not.toContain('write_file');
|
||||||
|
expect(config.getExcludeTools()).not.toContain('ask_user');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not exclude interactive tools in interactive mode with YOLO', async () => {
|
it('should not exclude interactive tools in interactive mode with YOLO', async () => {
|
||||||
@@ -1791,6 +1802,7 @@ describe('loadCliConfig tool exclusions', () => {
|
|||||||
expect(config.getExcludeTools()).not.toContain('run_shell_command');
|
expect(config.getExcludeTools()).not.toContain('run_shell_command');
|
||||||
expect(config.getExcludeTools()).not.toContain('replace');
|
expect(config.getExcludeTools()).not.toContain('replace');
|
||||||
expect(config.getExcludeTools()).not.toContain('write_file');
|
expect(config.getExcludeTools()).not.toContain('write_file');
|
||||||
|
expect(config.getExcludeTools()).not.toContain('ask_user');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should exclude interactive tools in non-interactive mode without YOLO', async () => {
|
it('should exclude interactive tools in non-interactive mode without YOLO', async () => {
|
||||||
@@ -1805,9 +1817,10 @@ describe('loadCliConfig tool exclusions', () => {
|
|||||||
expect(config.getExcludeTools()).toContain('run_shell_command');
|
expect(config.getExcludeTools()).toContain('run_shell_command');
|
||||||
expect(config.getExcludeTools()).toContain('replace');
|
expect(config.getExcludeTools()).toContain('replace');
|
||||||
expect(config.getExcludeTools()).toContain('write_file');
|
expect(config.getExcludeTools()).toContain('write_file');
|
||||||
|
expect(config.getExcludeTools()).toContain('ask_user');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not exclude interactive tools in non-interactive mode with YOLO', async () => {
|
it('should exclude only ask_user in non-interactive mode with YOLO', async () => {
|
||||||
process.stdin.isTTY = false;
|
process.stdin.isTTY = false;
|
||||||
process.argv = ['node', 'script.js', '-p', 'test', '--yolo'];
|
process.argv = ['node', 'script.js', '-p', 'test', '--yolo'];
|
||||||
const argv = await parseArguments(createTestMergedSettings());
|
const argv = await parseArguments(createTestMergedSettings());
|
||||||
@@ -1819,6 +1832,7 @@ describe('loadCliConfig tool exclusions', () => {
|
|||||||
expect(config.getExcludeTools()).not.toContain('run_shell_command');
|
expect(config.getExcludeTools()).not.toContain('run_shell_command');
|
||||||
expect(config.getExcludeTools()).not.toContain('replace');
|
expect(config.getExcludeTools()).not.toContain('replace');
|
||||||
expect(config.getExcludeTools()).not.toContain('write_file');
|
expect(config.getExcludeTools()).not.toContain('write_file');
|
||||||
|
expect(config.getExcludeTools()).toContain('ask_user');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not exclude shell tool in non-interactive mode when --allowed-tools="ShellTool" is set', async () => {
|
it('should not exclude shell tool in non-interactive mode when --allowed-tools="ShellTool" is set', async () => {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import {
|
|||||||
debugLogger,
|
debugLogger,
|
||||||
loadServerHierarchicalMemory,
|
loadServerHierarchicalMemory,
|
||||||
WEB_FETCH_TOOL_NAME,
|
WEB_FETCH_TOOL_NAME,
|
||||||
|
ASK_USER_TOOL_NAME,
|
||||||
getVersion,
|
getVersion,
|
||||||
PREVIEW_GEMINI_MODEL_AUTO,
|
PREVIEW_GEMINI_MODEL_AUTO,
|
||||||
type HookDefinition,
|
type HookDefinition,
|
||||||
@@ -596,6 +597,10 @@ export async function loadCliConfig(
|
|||||||
// In non-interactive mode, exclude tools that require a prompt.
|
// In non-interactive mode, exclude tools that require a prompt.
|
||||||
const extraExcludes: string[] = [];
|
const extraExcludes: string[] = [];
|
||||||
if (!interactive) {
|
if (!interactive) {
|
||||||
|
// ask_user requires user interaction and must be excluded in all
|
||||||
|
// non-interactive modes, regardless of the approval mode.
|
||||||
|
extraExcludes.push(ASK_USER_TOOL_NAME);
|
||||||
|
|
||||||
const defaultExcludes = [
|
const defaultExcludes = [
|
||||||
SHELL_TOOL_NAME,
|
SHELL_TOOL_NAME,
|
||||||
EDIT_TOOL_NAME,
|
EDIT_TOOL_NAME,
|
||||||
|
|||||||
Reference in New Issue
Block a user