diff --git a/packages/core/src/tools/read-file.test.ts b/packages/core/src/tools/read-file.test.ts index 08fe5edcb8..44e48cee7d 100644 --- a/packages/core/src/tools/read-file.test.ts +++ b/packages/core/src/tools/read-file.test.ts @@ -146,20 +146,52 @@ describe('ReadFileTool', () => { offset: -1, }; expect(() => tool.build(params)).toThrow( - 'Offset must be a non-negative number', + 'Offset must be a non-negative integer', ); }); - it('should throw error if limit is zero or negative', () => { + it('should throw error if offset is fractional', () => { const params: ReadFileToolParams = { file_path: path.join(tempRootDir, 'test.txt'), - limit: 0, + offset: 1.5, }; - expect(() => tool.build(params)).toThrow( - 'Limit must be a positive number', - ); + expect(() => tool.build(params)).toThrow('params/offset must be integer'); }); + it('should allow zero offset', () => { + const params: ReadFileToolParams = { + file_path: path.join(tempRootDir, 'test.txt'), + offset: 0, + }; + expect(tool.build(params)).toBeDefined(); + }); + + it.each([0, -1])( + 'should throw error if limit is not positive (%s)', + (limit) => { + const params: ReadFileToolParams = { + file_path: path.join(tempRootDir, 'test.txt'), + limit, + }; + expect(() => tool.build(params)).toThrow( + 'Limit must be a positive integer', + ); + }, + ); + + it.each([0.5, 1.5])( + 'should throw error if limit is fractional (%s)', + (limit) => { + const params: ReadFileToolParams = { + file_path: path.join(tempRootDir, 'test.txt'), + limit, + }; + expect(() => tool.build(params)).toThrow( + 'params/limit must be integer', + ); + }, + ); + it('should reject offset or limit for notebook files', () => { const params: ReadFileToolParams = { file_path: path.join(tempRootDir, 'test.ipynb'), diff --git a/packages/core/src/tools/read-file.ts b/packages/core/src/tools/read-file.ts index 4dd0b53e7d..29775dc8a6 100644 --- a/packages/core/src/tools/read-file.ts +++ b/packages/core/src/tools/read-file.ts @@ -406,12 +406,12 @@ export class ReadFileTool extends BaseDeclarativeTool< offset: { description: "Optional: For text files, the 0-based line number to start reading from. Requires 'limit' to be set. Use for paginating through large files.", - type: 'number', + type: 'integer', }, limit: { description: "Optional: For text files, maximum number of lines to read. Use with 'offset' to paginate through large files. If omitted, reads the entire file (if feasible, up to a default limit).", - type: 'number', + type: 'integer', }, pages: { description: @@ -441,11 +441,17 @@ export class ReadFileTool extends BaseDeclarativeTool< return `File path must be absolute, but was relative: ${filePath}. You must provide an absolute path.`; } - if (params.offset !== undefined && params.offset < 0) { - return 'Offset must be a non-negative number'; + if ( + params.offset !== undefined && + (!Number.isInteger(params.offset) || params.offset < 0) + ) { + return 'Offset must be a non-negative integer'; } - if (params.limit !== undefined && params.limit <= 0) { - return 'Limit must be a positive number'; + if ( + params.limit !== undefined && + (!Number.isInteger(params.limit) || params.limit <= 0) + ) { + return 'Limit must be a positive integer'; } if (params.pages !== undefined) {