mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-21 10:34:35 -07:00
feat(policy): support auto-add to policy by default and scoped persistence (#20361)
This commit is contained in:
@@ -20,11 +20,14 @@ import {
|
||||
type ToolLocation,
|
||||
type ToolResult,
|
||||
type ToolResultDisplay,
|
||||
type PolicyUpdateOptions,
|
||||
} from './tools.js';
|
||||
import { buildFilePathArgsPattern } from '../policy/utils.js';
|
||||
import type { MessageBus } from '../confirmation-bus/message-bus.js';
|
||||
import { ToolErrorType } from './tool-error.js';
|
||||
import { makeRelative, shortenPath } from '../utils/paths.js';
|
||||
import { isNodeError } from '../utils/errors.js';
|
||||
import { correctPath } from '../utils/pathCorrector.js';
|
||||
import type { Config } from '../config/config.js';
|
||||
import { ApprovalMode } from '../policy/types.js';
|
||||
import { CoreToolCallStatus } from '../scheduler/types.js';
|
||||
@@ -44,7 +47,6 @@ import {
|
||||
logEditCorrectionEvent,
|
||||
} from '../telemetry/loggers.js';
|
||||
|
||||
import { correctPath } from '../utils/pathCorrector.js';
|
||||
import {
|
||||
EDIT_TOOL_NAME,
|
||||
READ_FILE_TOOL_NAME,
|
||||
@@ -442,6 +444,8 @@ class EditToolInvocation
|
||||
extends BaseToolInvocation<EditToolParams, ToolResult>
|
||||
implements ToolInvocation<EditToolParams, ToolResult>
|
||||
{
|
||||
private readonly resolvedPath: string;
|
||||
|
||||
constructor(
|
||||
private readonly config: Config,
|
||||
params: EditToolParams,
|
||||
@@ -450,10 +454,31 @@ class EditToolInvocation
|
||||
displayName?: string,
|
||||
) {
|
||||
super(params, messageBus, toolName, displayName);
|
||||
if (!path.isAbsolute(this.params.file_path)) {
|
||||
const result = correctPath(this.params.file_path, this.config);
|
||||
if (result.success) {
|
||||
this.resolvedPath = result.correctedPath;
|
||||
} else {
|
||||
this.resolvedPath = path.resolve(
|
||||
this.config.getTargetDir(),
|
||||
this.params.file_path,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this.resolvedPath = this.params.file_path;
|
||||
}
|
||||
}
|
||||
|
||||
override toolLocations(): ToolLocation[] {
|
||||
return [{ path: this.params.file_path }];
|
||||
return [{ path: this.resolvedPath }];
|
||||
}
|
||||
|
||||
override getPolicyUpdateOptions(
|
||||
_outcome: ToolConfirmationOutcome,
|
||||
): PolicyUpdateOptions | undefined {
|
||||
return {
|
||||
argsPattern: buildFilePathArgsPattern(this.params.file_path),
|
||||
};
|
||||
}
|
||||
|
||||
private async attemptSelfCorrection(
|
||||
@@ -471,7 +496,7 @@ class EditToolInvocation
|
||||
const initialContentHash = hashContent(currentContent);
|
||||
const onDiskContent = await this.config
|
||||
.getFileSystemService()
|
||||
.readTextFile(params.file_path);
|
||||
.readTextFile(this.resolvedPath);
|
||||
const onDiskContentHash = hashContent(onDiskContent.replace(/\r\n/g, '\n'));
|
||||
|
||||
if (initialContentHash !== onDiskContentHash) {
|
||||
@@ -582,7 +607,7 @@ class EditToolInvocation
|
||||
try {
|
||||
currentContent = await this.config
|
||||
.getFileSystemService()
|
||||
.readTextFile(params.file_path);
|
||||
.readTextFile(this.resolvedPath);
|
||||
originalLineEnding = detectLineEnding(currentContent);
|
||||
currentContent = currentContent.replace(/\r\n/g, '\n');
|
||||
fileExists = true;
|
||||
@@ -615,7 +640,7 @@ class EditToolInvocation
|
||||
isNewFile: false,
|
||||
error: {
|
||||
display: `File not found. Cannot apply edit. Use an empty old_string to create a new file.`,
|
||||
raw: `File not found: ${params.file_path}`,
|
||||
raw: `File not found: ${this.resolvedPath}`,
|
||||
type: ToolErrorType.FILE_NOT_FOUND,
|
||||
},
|
||||
originalLineEnding,
|
||||
@@ -630,7 +655,7 @@ class EditToolInvocation
|
||||
isNewFile: false,
|
||||
error: {
|
||||
display: `Failed to read content of file.`,
|
||||
raw: `Failed to read content of existing file: ${params.file_path}`,
|
||||
raw: `Failed to read content of existing file: ${this.resolvedPath}`,
|
||||
type: ToolErrorType.READ_CONTENT_FAILURE,
|
||||
},
|
||||
originalLineEnding,
|
||||
@@ -645,7 +670,7 @@ class EditToolInvocation
|
||||
isNewFile: false,
|
||||
error: {
|
||||
display: `Failed to edit. Attempted to create a file that already exists.`,
|
||||
raw: `File already exists, cannot create: ${params.file_path}`,
|
||||
raw: `File already exists, cannot create: ${this.resolvedPath}`,
|
||||
type: ToolErrorType.ATTEMPT_TO_CREATE_EXISTING_FILE,
|
||||
},
|
||||
originalLineEnding,
|
||||
@@ -727,7 +752,7 @@ class EditToolInvocation
|
||||
return false;
|
||||
}
|
||||
|
||||
const fileName = path.basename(this.params.file_path);
|
||||
const fileName = path.basename(this.resolvedPath);
|
||||
const fileDiff = Diff.createPatch(
|
||||
fileName,
|
||||
editData.currentContent ?? '',
|
||||
@@ -739,14 +764,14 @@ class EditToolInvocation
|
||||
const ideClient = await IdeClient.getInstance();
|
||||
const ideConfirmation =
|
||||
this.config.getIdeMode() && ideClient.isDiffingEnabled()
|
||||
? ideClient.openDiff(this.params.file_path, editData.newContent)
|
||||
? ideClient.openDiff(this.resolvedPath, editData.newContent)
|
||||
: undefined;
|
||||
|
||||
const confirmationDetails: ToolEditConfirmationDetails = {
|
||||
type: 'edit',
|
||||
title: `Confirm Edit: ${shortenPath(makeRelative(this.params.file_path, this.config.getTargetDir()))}`,
|
||||
title: `Confirm Edit: ${shortenPath(makeRelative(this.resolvedPath, this.config.getTargetDir()))}`,
|
||||
fileName,
|
||||
filePath: this.params.file_path,
|
||||
filePath: this.resolvedPath,
|
||||
fileDiff,
|
||||
originalContent: editData.currentContent,
|
||||
newContent: editData.newContent,
|
||||
@@ -771,7 +796,7 @@ class EditToolInvocation
|
||||
|
||||
getDescription(): string {
|
||||
const relativePath = makeRelative(
|
||||
this.params.file_path,
|
||||
this.resolvedPath,
|
||||
this.config.getTargetDir(),
|
||||
);
|
||||
if (this.params.old_string === '') {
|
||||
@@ -797,11 +822,7 @@ class EditToolInvocation
|
||||
* @returns Result of the edit operation
|
||||
*/
|
||||
async execute(signal: AbortSignal): Promise<ToolResult> {
|
||||
const resolvedPath = path.resolve(
|
||||
this.config.getTargetDir(),
|
||||
this.params.file_path,
|
||||
);
|
||||
const validationError = this.config.validatePathAccess(resolvedPath);
|
||||
const validationError = this.config.validatePathAccess(this.resolvedPath);
|
||||
if (validationError) {
|
||||
return {
|
||||
llmContent: validationError,
|
||||
@@ -843,7 +864,7 @@ class EditToolInvocation
|
||||
}
|
||||
|
||||
try {
|
||||
await this.ensureParentDirectoriesExistAsync(this.params.file_path);
|
||||
await this.ensureParentDirectoriesExistAsync(this.resolvedPath);
|
||||
let finalContent = editData.newContent;
|
||||
|
||||
// Restore original line endings if they were CRLF, or use OS default for new files
|
||||
@@ -856,15 +877,15 @@ class EditToolInvocation
|
||||
}
|
||||
await this.config
|
||||
.getFileSystemService()
|
||||
.writeTextFile(this.params.file_path, finalContent);
|
||||
.writeTextFile(this.resolvedPath, finalContent);
|
||||
|
||||
let displayResult: ToolResultDisplay;
|
||||
if (editData.isNewFile) {
|
||||
displayResult = `Created ${shortenPath(makeRelative(this.params.file_path, this.config.getTargetDir()))}`;
|
||||
displayResult = `Created ${shortenPath(makeRelative(this.resolvedPath, this.config.getTargetDir()))}`;
|
||||
} else {
|
||||
// Generate diff for display, even though core logic doesn't technically need it
|
||||
// The CLI wrapper will use this part of the ToolResult
|
||||
const fileName = path.basename(this.params.file_path);
|
||||
const fileName = path.basename(this.resolvedPath);
|
||||
const fileDiff = Diff.createPatch(
|
||||
fileName,
|
||||
editData.currentContent ?? '', // Should not be null here if not isNewFile
|
||||
@@ -883,7 +904,7 @@ class EditToolInvocation
|
||||
displayResult = {
|
||||
fileDiff,
|
||||
fileName,
|
||||
filePath: this.params.file_path,
|
||||
filePath: this.resolvedPath,
|
||||
originalContent: editData.currentContent,
|
||||
newContent: editData.newContent,
|
||||
diffStat,
|
||||
@@ -893,8 +914,8 @@ class EditToolInvocation
|
||||
|
||||
const llmSuccessMessageParts = [
|
||||
editData.isNewFile
|
||||
? `Created new file: ${this.params.file_path} with provided content.`
|
||||
: `Successfully modified file: ${this.params.file_path} (${editData.occurrences} replacements).`,
|
||||
? `Created new file: ${this.resolvedPath} with provided content.`
|
||||
: `Successfully modified file: ${this.resolvedPath} (${editData.occurrences} replacements).`,
|
||||
];
|
||||
|
||||
// Return a diff of the file before and after the write so that the agent
|
||||
@@ -985,16 +1006,20 @@ export class EditTool
|
||||
return "The 'file_path' parameter must be non-empty.";
|
||||
}
|
||||
|
||||
let filePath = params.file_path;
|
||||
if (!path.isAbsolute(filePath)) {
|
||||
// Attempt to auto-correct to an absolute path
|
||||
const result = correctPath(filePath, this.config);
|
||||
if (!result.success) {
|
||||
return result.error;
|
||||
let resolvedPath: string;
|
||||
if (!path.isAbsolute(params.file_path)) {
|
||||
const result = correctPath(params.file_path, this.config);
|
||||
if (result.success) {
|
||||
resolvedPath = result.correctedPath;
|
||||
} else {
|
||||
resolvedPath = path.resolve(
|
||||
this.config.getTargetDir(),
|
||||
params.file_path,
|
||||
);
|
||||
}
|
||||
filePath = result.correctedPath;
|
||||
} else {
|
||||
resolvedPath = params.file_path;
|
||||
}
|
||||
params.file_path = filePath;
|
||||
|
||||
const newPlaceholders = detectOmissionPlaceholders(params.new_string);
|
||||
if (newPlaceholders.length > 0) {
|
||||
@@ -1009,7 +1034,7 @@ export class EditTool
|
||||
}
|
||||
}
|
||||
|
||||
return this.config.validatePathAccess(params.file_path);
|
||||
return this.config.validatePathAccess(resolvedPath);
|
||||
}
|
||||
|
||||
protected createInvocation(
|
||||
|
||||
@@ -14,12 +14,15 @@ import {
|
||||
Kind,
|
||||
type ToolInvocation,
|
||||
type ToolResult,
|
||||
type PolicyUpdateOptions,
|
||||
type ToolConfirmationOutcome,
|
||||
} from './tools.js';
|
||||
import { shortenPath, makeRelative } from '../utils/paths.js';
|
||||
import { type Config } from '../config/config.js';
|
||||
import { DEFAULT_FILE_FILTERING_OPTIONS } from '../config/constants.js';
|
||||
import { ToolErrorType } from './tool-error.js';
|
||||
import { GLOB_TOOL_NAME, GLOB_DISPLAY_NAME } from './tool-names.js';
|
||||
import { buildPatternArgsPattern } from '../policy/utils.js';
|
||||
import { getErrorMessage } from '../utils/errors.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
import { GLOB_DEFINITION } from './definitions/coreTools.js';
|
||||
@@ -118,6 +121,14 @@ class GlobToolInvocation extends BaseToolInvocation<
|
||||
return description;
|
||||
}
|
||||
|
||||
override getPolicyUpdateOptions(
|
||||
_outcome: ToolConfirmationOutcome,
|
||||
): PolicyUpdateOptions | undefined {
|
||||
return {
|
||||
argsPattern: buildPatternArgsPattern(this.params.pattern),
|
||||
};
|
||||
}
|
||||
|
||||
async execute(signal: AbortSignal): Promise<ToolResult> {
|
||||
try {
|
||||
const workspaceContext = this.config.getWorkspaceContext();
|
||||
|
||||
@@ -21,6 +21,8 @@ import {
|
||||
Kind,
|
||||
type ToolInvocation,
|
||||
type ToolResult,
|
||||
type PolicyUpdateOptions,
|
||||
type ToolConfirmationOutcome,
|
||||
} from './tools.js';
|
||||
import { makeRelative, shortenPath } from '../utils/paths.js';
|
||||
import { getErrorMessage, isNodeError } from '../utils/errors.js';
|
||||
@@ -29,6 +31,7 @@ import type { Config } from '../config/config.js';
|
||||
import type { FileExclusions } from '../utils/ignorePatterns.js';
|
||||
import { ToolErrorType } from './tool-error.js';
|
||||
import { GREP_TOOL_NAME } from './tool-names.js';
|
||||
import { buildPatternArgsPattern } from '../policy/utils.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
import { GREP_DEFINITION } from './definitions/coreTools.js';
|
||||
import { resolveToolDeclaration } from './definitions/resolver.js';
|
||||
@@ -285,6 +288,14 @@ class GrepToolInvocation extends BaseToolInvocation<
|
||||
}
|
||||
}
|
||||
|
||||
override getPolicyUpdateOptions(
|
||||
_outcome: ToolConfirmationOutcome,
|
||||
): PolicyUpdateOptions | undefined {
|
||||
return {
|
||||
argsPattern: buildPatternArgsPattern(this.params.pattern),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a command is available in the system's PATH.
|
||||
* @param {string} command The command name (e.g., 'git', 'grep').
|
||||
|
||||
@@ -13,12 +13,15 @@ import {
|
||||
Kind,
|
||||
type ToolInvocation,
|
||||
type ToolResult,
|
||||
type PolicyUpdateOptions,
|
||||
type ToolConfirmationOutcome,
|
||||
} from './tools.js';
|
||||
import { makeRelative, shortenPath } from '../utils/paths.js';
|
||||
import type { Config } from '../config/config.js';
|
||||
import { DEFAULT_FILE_FILTERING_OPTIONS } from '../config/constants.js';
|
||||
import { ToolErrorType } from './tool-error.js';
|
||||
import { LS_TOOL_NAME } from './tool-names.js';
|
||||
import { buildFilePathArgsPattern } from '../policy/utils.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
import { LS_DEFINITION } from './definitions/coreTools.js';
|
||||
import { resolveToolDeclaration } from './definitions/resolver.js';
|
||||
@@ -123,6 +126,14 @@ class LSToolInvocation extends BaseToolInvocation<LSToolParams, ToolResult> {
|
||||
return shortenPath(relativePath);
|
||||
}
|
||||
|
||||
override getPolicyUpdateOptions(
|
||||
_outcome: ToolConfirmationOutcome,
|
||||
): PolicyUpdateOptions | undefined {
|
||||
return {
|
||||
argsPattern: buildFilePathArgsPattern(this.params.dir_path),
|
||||
};
|
||||
}
|
||||
|
||||
// Helper for consistent error formatting
|
||||
private errorResult(
|
||||
llmContent: string,
|
||||
|
||||
@@ -184,7 +184,7 @@ export class DiscoveredMCPToolInvocation extends BaseToolInvocation<
|
||||
);
|
||||
}
|
||||
|
||||
protected override getPolicyUpdateOptions(
|
||||
override getPolicyUpdateOptions(
|
||||
_outcome: ToolConfirmationOutcome,
|
||||
): PolicyUpdateOptions | undefined {
|
||||
return { mcpName: this.serverName };
|
||||
|
||||
@@ -14,8 +14,11 @@ import {
|
||||
type ToolInvocation,
|
||||
type ToolLocation,
|
||||
type ToolResult,
|
||||
type PolicyUpdateOptions,
|
||||
type ToolConfirmationOutcome,
|
||||
} from './tools.js';
|
||||
import { ToolErrorType } from './tool-error.js';
|
||||
import { buildFilePathArgsPattern } from '../policy/utils.js';
|
||||
|
||||
import type { PartUnion } from '@google/genai';
|
||||
import {
|
||||
@@ -88,6 +91,14 @@ class ReadFileToolInvocation extends BaseToolInvocation<
|
||||
];
|
||||
}
|
||||
|
||||
override getPolicyUpdateOptions(
|
||||
_outcome: ToolConfirmationOutcome,
|
||||
): PolicyUpdateOptions | undefined {
|
||||
return {
|
||||
argsPattern: buildFilePathArgsPattern(this.params.file_path),
|
||||
};
|
||||
}
|
||||
|
||||
async execute(): Promise<ToolResult> {
|
||||
const validationError = this.config.validatePathAccess(
|
||||
this.resolvedPath,
|
||||
|
||||
@@ -11,11 +11,14 @@ import {
|
||||
Kind,
|
||||
type ToolInvocation,
|
||||
type ToolResult,
|
||||
type PolicyUpdateOptions,
|
||||
type ToolConfirmationOutcome,
|
||||
} from './tools.js';
|
||||
import { getErrorMessage } from '../utils/errors.js';
|
||||
import * as fsPromises from 'node:fs/promises';
|
||||
import * as path from 'node:path';
|
||||
import { glob, escape } from 'glob';
|
||||
import { buildPatternArgsPattern } from '../policy/utils.js';
|
||||
import {
|
||||
detectFileType,
|
||||
processSingleFileContent,
|
||||
@@ -155,6 +158,16 @@ ${finalExclusionPatternsForDescription
|
||||
)}".`;
|
||||
}
|
||||
|
||||
override getPolicyUpdateOptions(
|
||||
_outcome: ToolConfirmationOutcome,
|
||||
): PolicyUpdateOptions | undefined {
|
||||
// We join the include patterns to match the JSON stringified arguments.
|
||||
// buildPatternArgsPattern handles JSON stringification.
|
||||
return {
|
||||
argsPattern: buildPatternArgsPattern(JSON.stringify(this.params.include)),
|
||||
};
|
||||
}
|
||||
|
||||
async execute(signal: AbortSignal): Promise<ToolResult> {
|
||||
const { include, exclude = [], useDefaultExcludes = true } = this.params;
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ export class ShellToolInvocation extends BaseToolInvocation<
|
||||
return description;
|
||||
}
|
||||
|
||||
protected override getPolicyUpdateOptions(
|
||||
override getPolicyUpdateOptions(
|
||||
outcome: ToolConfirmationOutcome,
|
||||
): PolicyUpdateOptions | undefined {
|
||||
if (
|
||||
|
||||
@@ -154,12 +154,22 @@ export const LS_TOOL_NAME_LEGACY = 'list_directory'; // Just to be safe if anyth
|
||||
|
||||
export const EDIT_TOOL_NAMES = new Set([EDIT_TOOL_NAME, WRITE_FILE_TOOL_NAME]);
|
||||
|
||||
// Tool Display Names
|
||||
export const WRITE_FILE_DISPLAY_NAME = 'WriteFile';
|
||||
export const EDIT_DISPLAY_NAME = 'Edit';
|
||||
export const ASK_USER_DISPLAY_NAME = 'Ask User';
|
||||
export const READ_FILE_DISPLAY_NAME = 'ReadFile';
|
||||
export const GLOB_DISPLAY_NAME = 'FindFiles';
|
||||
/**
|
||||
* Tools that can access local files or remote resources and should be
|
||||
* treated with extra caution when updating policies.
|
||||
*/
|
||||
export const SENSITIVE_TOOLS = new Set([
|
||||
GLOB_TOOL_NAME,
|
||||
GREP_TOOL_NAME,
|
||||
READ_MANY_FILES_TOOL_NAME,
|
||||
WEB_FETCH_TOOL_NAME,
|
||||
READ_FILE_TOOL_NAME,
|
||||
LS_TOOL_NAME,
|
||||
WRITE_FILE_TOOL_NAME,
|
||||
EDIT_TOOL_NAME,
|
||||
SHELL_TOOL_NAME,
|
||||
]);
|
||||
|
||||
export const TRACKER_CREATE_TASK_TOOL_NAME = 'tracker_create_task';
|
||||
export const TRACKER_UPDATE_TASK_TOOL_NAME = 'tracker_update_task';
|
||||
export const TRACKER_GET_TASK_TOOL_NAME = 'tracker_get_task';
|
||||
@@ -167,6 +177,13 @@ export const TRACKER_LIST_TASKS_TOOL_NAME = 'tracker_list_tasks';
|
||||
export const TRACKER_ADD_DEPENDENCY_TOOL_NAME = 'tracker_add_dependency';
|
||||
export const TRACKER_VISUALIZE_TOOL_NAME = 'tracker_visualize';
|
||||
|
||||
// Tool Display Names
|
||||
export const WRITE_FILE_DISPLAY_NAME = 'WriteFile';
|
||||
export const EDIT_DISPLAY_NAME = 'Edit';
|
||||
export const ASK_USER_DISPLAY_NAME = 'Ask User';
|
||||
export const READ_FILE_DISPLAY_NAME = 'ReadFile';
|
||||
export const GLOB_DISPLAY_NAME = 'FindFiles';
|
||||
|
||||
/**
|
||||
* Mapping of legacy tool names to their current names.
|
||||
* This ensures backward compatibility for user-defined policies, skills, and hooks.
|
||||
|
||||
@@ -68,12 +68,21 @@ export interface ToolInvocation<
|
||||
updateOutput?: (output: ToolLiveOutput) => void,
|
||||
shellExecutionConfig?: ShellExecutionConfig,
|
||||
): Promise<TResult>;
|
||||
|
||||
/**
|
||||
* Returns tool-specific options for policy updates.
|
||||
* This is used by the scheduler to narrow policy rules when a tool is approved.
|
||||
*/
|
||||
getPolicyUpdateOptions?(
|
||||
outcome: ToolConfirmationOutcome,
|
||||
): PolicyUpdateOptions | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for policy updates that can be customized by tool invocations.
|
||||
*/
|
||||
export interface PolicyUpdateOptions {
|
||||
argsPattern?: string;
|
||||
commandPrefix?: string | string[];
|
||||
mcpName?: string;
|
||||
}
|
||||
@@ -130,7 +139,7 @@ export abstract class BaseToolInvocation<
|
||||
* Subclasses can override this to provide additional options like
|
||||
* commandPrefix (for shell) or mcpName (for MCP tools).
|
||||
*/
|
||||
protected getPolicyUpdateOptions(
|
||||
getPolicyUpdateOptions(
|
||||
_outcome: ToolConfirmationOutcome,
|
||||
): PolicyUpdateOptions | undefined {
|
||||
return undefined;
|
||||
|
||||
@@ -12,7 +12,9 @@ import {
|
||||
type ToolInvocation,
|
||||
type ToolResult,
|
||||
type ToolConfirmationOutcome,
|
||||
type PolicyUpdateOptions,
|
||||
} from './tools.js';
|
||||
import { buildPatternArgsPattern } from '../policy/utils.js';
|
||||
import type { MessageBus } from '../confirmation-bus/message-bus.js';
|
||||
import { ToolErrorType } from './tool-error.js';
|
||||
import { getErrorMessage } from '../utils/errors.js';
|
||||
@@ -291,6 +293,22 @@ ${textContent}
|
||||
return `Processing URLs and instructions from prompt: "${displayPrompt}"`;
|
||||
}
|
||||
|
||||
override getPolicyUpdateOptions(
|
||||
_outcome: ToolConfirmationOutcome,
|
||||
): PolicyUpdateOptions | undefined {
|
||||
if (this.params.url) {
|
||||
return {
|
||||
argsPattern: buildPatternArgsPattern(this.params.url),
|
||||
};
|
||||
}
|
||||
if (this.params.prompt) {
|
||||
return {
|
||||
argsPattern: buildPatternArgsPattern(this.params.prompt),
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
protected override async getConfirmationDetails(
|
||||
_abortSignal: AbortSignal,
|
||||
): Promise<ToolCallConfirmationDetails | false> {
|
||||
|
||||
@@ -24,7 +24,9 @@ import {
|
||||
type ToolLocation,
|
||||
type ToolResult,
|
||||
type ToolConfirmationOutcome,
|
||||
type PolicyUpdateOptions,
|
||||
} from './tools.js';
|
||||
import { buildFilePathArgsPattern } from '../policy/utils.js';
|
||||
import { ToolErrorType } from './tool-error.js';
|
||||
import { makeRelative, shortenPath } from '../utils/paths.js';
|
||||
import { getErrorMessage, isNodeError } from '../utils/errors.js';
|
||||
@@ -164,6 +166,14 @@ class WriteFileToolInvocation extends BaseToolInvocation<
|
||||
return [{ path: this.resolvedPath }];
|
||||
}
|
||||
|
||||
override getPolicyUpdateOptions(
|
||||
_outcome: ToolConfirmationOutcome,
|
||||
): PolicyUpdateOptions | undefined {
|
||||
return {
|
||||
argsPattern: buildFilePathArgsPattern(this.params.file_path),
|
||||
};
|
||||
}
|
||||
|
||||
override getDescription(): string {
|
||||
const relativePath = makeRelative(
|
||||
this.resolvedPath,
|
||||
|
||||
Reference in New Issue
Block a user