feat: Add --yolo mode that automatically accepts all tools executions (#695)

Co-authored-by: N. Taylor Mullen <ntaylormullen@google.com>
This commit is contained in:
Tolik Malibroda
2025-06-02 22:05:45 +02:00
committed by GitHub
parent 42bedbc3d3
commit 0795e55f0e
15 changed files with 364 additions and 156 deletions

View File

@@ -25,7 +25,7 @@ import { FileDiff } from './tools.js';
import path from 'path';
import fs from 'fs';
import os from 'os';
import { Config } from '../config/config.js';
import { ApprovalMode, Config } from '../config/config.js';
import { Content, Part, SchemaUnion } from '@google/genai';
describe('EditTool', () => {
@@ -41,8 +41,8 @@ describe('EditTool', () => {
mockConfig = {
getTargetDir: () => rootDir,
getAlwaysSkipModificationConfirmation: vi.fn(() => false),
setAlwaysSkipModificationConfirmation: vi.fn(),
getApprovalMode: vi.fn(() => false),
setApprovalMode: vi.fn(),
// getGeminiConfig: () => ({ apiKey: 'test-api-key' }), // This was not a real Config method
// Add other properties/methods of Config if EditTool uses them
// Minimal other methods to satisfy Config type if needed by EditTool constructor or other direct uses:
@@ -65,12 +65,10 @@ describe('EditTool', () => {
} as unknown as Config;
// Reset mocks before each test
(mockConfig.getAlwaysSkipModificationConfirmation as Mock).mockClear();
(mockConfig.setAlwaysSkipModificationConfirmation as Mock).mockClear();
(mockConfig.getApprovalMode as Mock).mockClear();
(mockConfig.getApprovalMode as Mock).mockClear();
// Default to not skipping confirmation
(mockConfig.getAlwaysSkipModificationConfirmation as Mock).mockReturnValue(
false,
);
(mockConfig.getApprovalMode as Mock).mockReturnValue(ApprovalMode.DEFAULT);
// Reset mocks and set default implementation for ensureCorrectEdit
mockEnsureCorrectEdit.mockReset();
@@ -439,9 +437,9 @@ describe('EditTool', () => {
new_string: fileContent,
};
(
mockConfig.getAlwaysSkipModificationConfirmation as Mock
).mockReturnValueOnce(true);
(mockConfig.getApprovalMode as Mock).mockReturnValueOnce(
ApprovalMode.AUTO_EDIT,
);
const result = await tool.execute(params, new AbortController().signal);
expect(result.llmContent).toMatch(/Created new file/);

View File

@@ -20,7 +20,7 @@ import { makeRelative, shortenPath } from '../utils/paths.js';
import { isNodeError } from '../utils/errors.js';
import { ReadFileTool } from './read-file.js';
import { GeminiClient } from '../core/client.js';
import { Config } from '../config/config.js';
import { Config, ApprovalMode } from '../config/config.js';
import { ensureCorrectEdit } from '../utils/editCorrector.js';
import { DEFAULT_DIFF_OPTIONS } from './diffOptions.js';
@@ -281,7 +281,7 @@ Expectation for required parameters:
params: EditToolParams,
abortSignal: AbortSignal,
): Promise<ToolCallConfirmationDetails | false> {
if (this.config.getAlwaysSkipModificationConfirmation()) {
if (this.config.getApprovalMode() === ApprovalMode.AUTO_EDIT) {
return false;
}
const validationError = this.validateToolParams(params);
@@ -356,7 +356,7 @@ Expectation for required parameters:
fileDiff,
onConfirm: async (outcome: ToolConfirmationOutcome) => {
if (outcome === ToolConfirmationOutcome.ProceedAlways) {
this.config.setAlwaysSkipModificationConfirmation(true);
this.config.setApprovalMode(ApprovalMode.AUTO_EDIT);
}
},
};

View File

@@ -16,7 +16,7 @@ import {
} from 'vitest';
import { ToolRegistry, DiscoveredTool } from './tool-registry.js';
import { DiscoveredMCPTool } from './mcp-tool.js';
import { Config, ConfigParameters } from '../config/config.js';
import { ApprovalMode, Config, ConfigParameters } from '../config/config.js';
import { BaseTool, ToolResult } from './tools.js';
import { FunctionDeclaration } from '@google/genai';
import { execSync, spawn } from 'node:child_process'; // Import spawn here
@@ -85,7 +85,7 @@ const baseConfigParams: ConfigParameters = {
userAgent: 'TestAgent/1.0',
userMemory: '',
geminiMdFileCount: 0,
alwaysSkipModificationConfirmation: false,
approvalMode: ApprovalMode.DEFAULT,
vertexai: false,
};

View File

@@ -20,7 +20,7 @@ import {
ToolEditConfirmationDetails,
} from './tools.js';
import { type EditToolParams } from './edit.js';
import { Config } from '../config/config.js';
import { ApprovalMode, Config } from '../config/config.js';
import { ToolRegistry } from './tool-registry.js';
import path from 'path';
import fs from 'fs';
@@ -51,8 +51,8 @@ vi.mocked(ensureCorrectFileContent).mockImplementation(
// Mock Config
const mockConfigInternal = {
getTargetDir: () => rootDir,
getAlwaysSkipModificationConfirmation: vi.fn(() => false),
setAlwaysSkipModificationConfirmation: vi.fn(),
getApprovalMode: vi.fn(() => ApprovalMode.DEFAULT),
setApprovalMode: vi.fn(),
getApiKey: () => 'test-key',
getModel: () => 'test-model',
getSandbox: () => false,
@@ -100,10 +100,8 @@ describe('WriteFileTool', () => {
tool = new WriteFileTool(mockConfig);
// Reset mocks before each test
mockConfigInternal.getAlwaysSkipModificationConfirmation.mockReturnValue(
false,
);
mockConfigInternal.setAlwaysSkipModificationConfirmation.mockClear();
mockConfigInternal.getApprovalMode.mockReturnValue(ApprovalMode.DEFAULT);
mockConfigInternal.setApprovalMode.mockClear();
mockEnsureCorrectEdit.mockReset();
mockEnsureCorrectFileContent.mockReset();

View File

@@ -7,7 +7,7 @@
import fs from 'fs';
import path from 'path';
import * as Diff from 'diff';
import { Config } from '../config/config.js';
import { Config, ApprovalMode } from '../config/config.js';
import {
BaseTool,
ToolResult,
@@ -143,7 +143,7 @@ export class WriteFileTool extends BaseTool<WriteFileToolParams, ToolResult> {
params: WriteFileToolParams,
abortSignal: AbortSignal,
): Promise<ToolCallConfirmationDetails | false> {
if (this.config.getAlwaysSkipModificationConfirmation()) {
if (this.config.getApprovalMode() === ApprovalMode.AUTO_EDIT) {
return false;
}
@@ -186,7 +186,7 @@ export class WriteFileTool extends BaseTool<WriteFileToolParams, ToolResult> {
fileDiff,
onConfirm: async (outcome: ToolConfirmationOutcome) => {
if (outcome === ToolConfirmationOutcome.ProceedAlways) {
this.config.setAlwaysSkipModificationConfirmation(true);
this.config.setApprovalMode(ApprovalMode.AUTO_EDIT);
}
},
};