From 2fa13420aeb67adcbba0ca0fa8c4827be34b8f0d Mon Sep 17 00:00:00 2001 From: Gaurav Sehgal Date: Mon, 27 Oct 2025 09:47:13 +0530 Subject: [PATCH] add absolute file path description for windows (#12007) --- packages/core/src/tools/edit.test.ts | 40 +++++++++++++++++++++++ packages/core/src/tools/edit.ts | 5 ++- packages/core/src/tools/read-file.test.ts | 40 +++++++++++++++++++++++ packages/core/src/tools/read-file.ts | 5 ++- 4 files changed, 88 insertions(+), 2 deletions(-) diff --git a/packages/core/src/tools/edit.test.ts b/packages/core/src/tools/edit.test.ts index 60f09c7a81..ab021cd161 100644 --- a/packages/core/src/tools/edit.test.ts +++ b/packages/core/src/tools/edit.test.ts @@ -36,6 +36,14 @@ vi.mock('../telemetry/loggers.js', () => ({ logFileOperation: vi.fn(), })); +interface EditFileParameterSchema { + properties: { + file_path: { + description: string; + }; + }; +} + import type { Mock } from 'vitest'; import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import type { EditToolParams } from './edit.js'; @@ -1025,6 +1033,38 @@ describe('EditTool', () => { }); }); + describe('constructor', () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + it('should use windows-style path examples on windows', () => { + vi.spyOn(process, 'platform', 'get').mockReturnValue('win32'); + + const tool = new EditTool({} as unknown as Config); + const schema = tool.schema; + expect( + (schema.parametersJsonSchema as EditFileParameterSchema).properties + .file_path.description, + ).toBe( + "The absolute path to the file to modify (e.g., 'C:\\Users\\project\\file.txt'). Must be an absolute path.", + ); + }); + + it('should use unix-style path examples on non-windows platforms', () => { + vi.spyOn(process, 'platform', 'get').mockReturnValue('linux'); + + const tool = new EditTool({} as unknown as Config); + const schema = tool.schema; + expect( + (schema.parametersJsonSchema as EditFileParameterSchema).properties + .file_path.description, + ).toBe( + "The absolute path to the file to modify (e.g., '/home/user/project/file.txt'). Must start with '/'.", + ); + }); + }); + describe('IDE mode', () => { const testFile = 'edit_me.txt'; let filePath: string; diff --git a/packages/core/src/tools/edit.ts b/packages/core/src/tools/edit.ts index 749dffe813..6ce1a1f946 100644 --- a/packages/core/src/tools/edit.ts +++ b/packages/core/src/tools/edit.ts @@ -7,6 +7,7 @@ import * as fs from 'node:fs'; import * as path from 'node:path'; import * as Diff from 'diff'; +import process from 'node:process'; import type { ToolCallConfirmationDetails, ToolEditConfirmationDetails, @@ -504,7 +505,9 @@ Expectation for required parameters: properties: { file_path: { description: - "The absolute path to the file to modify. Must start with '/'.", + process.platform === 'win32' + ? "The absolute path to the file to modify (e.g., 'C:\\Users\\project\\file.txt'). Must be an absolute path." + : "The absolute path to the file to modify (e.g., '/home/user/project/file.txt'). Must start with '/'.", type: 'string', }, old_string: { diff --git a/packages/core/src/tools/read-file.test.ts b/packages/core/src/tools/read-file.test.ts index 825d807cc4..a079651298 100644 --- a/packages/core/src/tools/read-file.test.ts +++ b/packages/core/src/tools/read-file.test.ts @@ -22,6 +22,14 @@ vi.mock('../telemetry/loggers.js', () => ({ logFileOperation: vi.fn(), })); +interface ReadFileParameterSchema { + properties: { + absolute_path: { + description: string; + }; + }; +} + describe('ReadFileTool', () => { let tempRootDir: string; let tool: ReadFileTool; @@ -196,6 +204,38 @@ describe('ReadFileTool', () => { }); }); + describe('constructor', () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + it('should use windows-style path examples on windows', () => { + vi.spyOn(process, 'platform', 'get').mockReturnValue('win32'); + + const tool = new ReadFileTool({} as unknown as Config); + const schema = tool.schema; + expect( + (schema.parametersJsonSchema as ReadFileParameterSchema).properties + .absolute_path.description, + ).toBe( + "The absolute path to the file to read (e.g., 'C:\\Users\\project\\file.txt'). Relative paths are not supported. You must provide an absolute path.", + ); + }); + + it('should use unix-style path examples on non-windows platforms', () => { + vi.spyOn(process, 'platform', 'get').mockReturnValue('linux'); + + const tool = new ReadFileTool({} as unknown as Config); + const schema = tool.schema; + expect( + (schema.parametersJsonSchema as ReadFileParameterSchema).properties + .absolute_path.description, + ).toBe( + "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.", + ); + }); + }); + describe('execute', () => { it('should return error if file does not exist', async () => { const filePath = path.join(tempRootDir, 'nonexistent.txt'); diff --git a/packages/core/src/tools/read-file.ts b/packages/core/src/tools/read-file.ts index affb428907..95461c1f06 100644 --- a/packages/core/src/tools/read-file.ts +++ b/packages/core/src/tools/read-file.ts @@ -6,6 +6,7 @@ import type { MessageBus } from '../confirmation-bus/message-bus.js'; import path from 'node:path'; +import process from 'node:process'; import { makeRelative, shortenPath } from '../utils/paths.js'; import type { ToolInvocation, ToolLocation, ToolResult } from './tools.js'; import { BaseDeclarativeTool, BaseToolInvocation, Kind } from './tools.js'; @@ -155,7 +156,9 @@ export class ReadFileTool extends BaseDeclarativeTool< properties: { absolute_path: { description: - "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.", + process.platform === 'win32' + ? "The absolute path to the file to read (e.g., 'C:\\Users\\project\\file.txt'). Relative paths are not supported. You must provide an absolute path." + : "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', }, offset: {