feat(cli): Add --allowed-tools flag to bypass tool confirmation (#2417) (#6453)

This commit is contained in:
Andrew Garrett
2025-08-27 02:17:43 +10:00
committed by GitHub
parent c33a0da1df
commit 52dae2c583
14 changed files with 524 additions and 135 deletions

View File

@@ -0,0 +1,94 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { expect, describe, it } from 'vitest';
import { doesToolInvocationMatch } from './tool-utils.js';
import type { AnyToolInvocation, Config } from '../index.js';
import { ReadFileTool } from '../tools/read-file.js';
describe('doesToolInvocationMatch', () => {
it('should not match a partial command prefix', () => {
const invocation = {
params: { command: 'git commitsomething' },
} as AnyToolInvocation;
const patterns = ['ShellTool(git commit)'];
const result = doesToolInvocationMatch(
'run_shell_command',
invocation,
patterns,
);
expect(result).toBe(false);
});
it('should match an exact command', () => {
const invocation = {
params: { command: 'git status' },
} as AnyToolInvocation;
const patterns = ['ShellTool(git status)'];
const result = doesToolInvocationMatch(
'run_shell_command',
invocation,
patterns,
);
expect(result).toBe(true);
});
it('should match a command that is a prefix', () => {
const invocation = {
params: { command: 'git status -v' },
} as AnyToolInvocation;
const patterns = ['ShellTool(git status)'];
const result = doesToolInvocationMatch(
'run_shell_command',
invocation,
patterns,
);
expect(result).toBe(true);
});
describe('for non-shell tools', () => {
const readFileTool = new ReadFileTool({} as Config);
const invocation = {
params: { file: 'test.txt' },
} as AnyToolInvocation;
it('should match by tool name', () => {
const patterns = ['read_file'];
const result = doesToolInvocationMatch(
readFileTool,
invocation,
patterns,
);
expect(result).toBe(true);
});
it('should match by tool class name', () => {
const patterns = ['ReadFileTool'];
const result = doesToolInvocationMatch(
readFileTool,
invocation,
patterns,
);
expect(result).toBe(true);
});
it('should not match if neither name is in the patterns', () => {
const patterns = ['some_other_tool', 'AnotherToolClass'];
const result = doesToolInvocationMatch(
readFileTool,
invocation,
patterns,
);
expect(result).toBe(false);
});
it('should match by tool name when passed as a string', () => {
const patterns = ['read_file'];
const result = doesToolInvocationMatch('read_file', invocation, patterns);
expect(result).toBe(true);
});
});
});