diff --git a/.changeset/read-tool-dual-cap-message.md b/.changeset/read-tool-dual-cap-message.md new file mode 100644 index 00000000..42908f69 --- /dev/null +++ b/.changeset/read-tool-dual-cap-message.md @@ -0,0 +1,6 @@ +--- +"@moonshot-ai/agent-core": patch +"@moonshot-ai/kimi-code": patch +--- + +Report both MAX_LINES and MAX_BYTES limits in Read tool status when both are reached. diff --git a/packages/agent-core/src/tools/builtin/file/read.ts b/packages/agent-core/src/tools/builtin/file/read.ts index 5c711007..bc374c33 100644 --- a/packages/agent-core/src/tools/builtin/file/read.ts +++ b/packages/agent-core/src/tools/builtin/file/read.ts @@ -435,9 +435,11 @@ export class ReadTool implements BuiltinTool { parts.push(`Total lines in file: ${String(input.totalLines)}.`); if (input.maxLinesReached) { parts.push(`Max ${String(MAX_LINES)} lines reached.`); - } else if (input.maxBytesReached) { + } + if (input.maxBytesReached) { parts.push(`Max ${String(MAX_BYTES)} bytes reached.`); - } else if (lineCount < input.requestedLines) { + } + if (!input.maxLinesReached && !input.maxBytesReached && lineCount < input.requestedLines) { parts.push('End of file reached.'); } if (input.truncatedLineNumbers.length > 0) { diff --git a/packages/agent-core/test/tools/read.test.ts b/packages/agent-core/test/tools/read.test.ts index 035b4dde..c14b34ee 100644 --- a/packages/agent-core/test/tools/read.test.ts +++ b/packages/agent-core/test/tools/read.test.ts @@ -597,6 +597,23 @@ describe('ReadTool', () => { expect(result.output).not.toContain(`${String(MAX_LINES + 1)}\tline ${String(MAX_LINES + 1)}`); }); + it('reports both MAX_LINES and MAX_BYTES when both caps are hit', async () => { + const lineCount = MAX_LINES + 5; + const lineContent = 'x'.repeat(105); + const content = Array.from({ length: lineCount }, (_, i) => `${lineContent} ${String(i + 1)}`).join( + '\n', + ); + const tool = toolWithContent(content); + + const result = await executeTool(tool, context({ path: '/tmp/both-caps.txt' })); + const output = toolContentString(result); + + expect(result.isError).toBeFalsy(); + expect(output).toContain(`Max ${String(MAX_LINES)} lines reached.`); + expect(output).toContain(`Max ${String(MAX_BYTES)} bytes reached.`); + expect(output).not.toContain('End of file reached.'); + }); + it('tail byte truncation keeps the newest lines closest to EOF', async () => { const numLines = Math.floor(MAX_BYTES / 1001) + 20; const content = Array.from({ length: numLines }, (_, i) => {