fix: Push tool calls to absolute paths (#1055) (#1057)

Make several changes to guide the model to request absolute paths,
reducing frequent accidental relative path tool call failures.

- Switch the parameter name: path --> absolute_path.
- Update the tool definition to strongly require an absolute path.
- Update the system prompt to indicate absolute paths are required.
- Update the system prompt tool use examples to use absolute paths.

Test case:

Open GC in GC: "Locate the primary file calling genai"
- Expected: Model opens files with absolute path, successfully.
- Actual (pre-patch): Failure, attempts to read with relative path.
- Actual (post-patch): Success, attempts to read with absolute path.
This commit is contained in:
Keir Mierle
2025-06-14 21:16:11 -07:00
committed by GitHub
parent e30e650a77
commit 32dd298351
5 changed files with 82 additions and 68 deletions

View File

@@ -18,7 +18,7 @@ export interface ReadFileToolParams {
/**
* The absolute path to the file to read
*/
path: string;
absolute_path: string;
/**
* The line number to start reading from (optional)
@@ -47,10 +47,11 @@ export class ReadFileTool extends BaseTool<ReadFileToolParams, ToolResult> {
'Reads and returns the content of a specified file from the local filesystem. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), and PDF files. For text files, it can read specific line ranges.',
{
properties: {
path: {
absolute_path: {
description:
"The absolute path to the file to read (e.g., '/home/user/project/file.txt'). Relative paths are not supported.",
"The absolute path to the file to read (e.g., '/home/user/project/file.txt'). Relative paths are not supported. You must provide an absolute path.",
type: 'string',
pattern: '^/',
},
offset: {
description:
@@ -63,7 +64,7 @@ export class ReadFileTool extends BaseTool<ReadFileToolParams, ToolResult> {
type: 'number',
},
},
required: ['path'],
required: ['absolute_path'],
type: 'object',
},
);
@@ -80,9 +81,9 @@ export class ReadFileTool extends BaseTool<ReadFileToolParams, ToolResult> {
) {
return 'Parameters failed schema validation.';
}
const filePath = params.path;
const filePath = params.absolute_path;
if (!path.isAbsolute(filePath)) {
return `File path must be absolute: ${filePath}`;
return `File path must be absolute, but was relative: ${filePath}. You must provide an absolute path.`;
}
if (!isWithinRoot(filePath, this.rootDirectory)) {
return `File path must be within the root directory (${this.rootDirectory}): ${filePath}`;
@@ -95,8 +96,11 @@ export class ReadFileTool extends BaseTool<ReadFileToolParams, ToolResult> {
}
const fileService = this.config.getFileService();
if (fileService.shouldGeminiIgnoreFile(params.path)) {
const relativePath = makeRelative(params.path, this.rootDirectory);
if (fileService.shouldGeminiIgnoreFile(params.absolute_path)) {
const relativePath = makeRelative(
params.absolute_path,
this.rootDirectory,
);
return `File path '${shortenPath(relativePath)}' is ignored by .geminiignore pattern(s).`;
}
@@ -106,12 +110,12 @@ export class ReadFileTool extends BaseTool<ReadFileToolParams, ToolResult> {
getDescription(params: ReadFileToolParams): string {
if (
!params ||
typeof params.path !== 'string' ||
params.path.trim() === ''
typeof params.absolute_path !== 'string' ||
params.absolute_path.trim() === ''
) {
return `Path unavailable`;
}
const relativePath = makeRelative(params.path, this.rootDirectory);
const relativePath = makeRelative(params.absolute_path, this.rootDirectory);
return shortenPath(relativePath);
}
@@ -128,7 +132,7 @@ export class ReadFileTool extends BaseTool<ReadFileToolParams, ToolResult> {
}
const result = await processSingleFileContent(
params.path,
params.absolute_path,
this.rootDirectory,
params.offset,
params.limit,