From 03317b7a45ccc1e03050a36783120f96dbb6be83 Mon Sep 17 00:00:00 2001 From: King Star Date: Sun, 16 Aug 2026 22:03:04 +0800 Subject: [PATCH] fix: handle trailing newline in filesystem tail --- src/filesystem/__tests__/lib.test.ts | 27 +++++++++++++++++++++++++++ src/filesystem/lib.ts | 8 +++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/filesystem/__tests__/lib.test.ts b/src/filesystem/__tests__/lib.test.ts index e0ae61224f..ec6a6b1e49 100644 --- a/src/filesystem/__tests__/lib.test.ts +++ b/src/filesystem/__tests__/lib.test.ts @@ -643,6 +643,33 @@ describe('Lib Functions', () => { expect(mockFileHandle.close).toHaveBeenCalled(); }); + it('ignores trailing newline when returning last lines', async () => { + const content = Buffer.from('line1\nline2\n'); + mockFs.stat.mockResolvedValue({ size: content.length } as any); + + const mockFileHandle = { + read: vi.fn( + (buffer: Buffer, offset: number, length: number, position: number) => { + const bytesRead = content.copy( + buffer, + offset, + position, + Math.min(position + length, content.length) + ); + return Promise.resolve({ bytesRead }); + } + ), + close: vi.fn().mockResolvedValue(undefined) + } as any; + + mockFs.open.mockResolvedValue(mockFileHandle); + + const result = await tailFile('/test/file.txt', 1); + + expect(result).toBe('line2'); + expect(mockFileHandle.close).toHaveBeenCalled(); + }); + it('handles read errors gracefully', async () => { mockFs.stat.mockResolvedValue({ size: 100 } as any); diff --git a/src/filesystem/lib.ts b/src/filesystem/lib.ts index ce4af9f38a..763e145819 100644 --- a/src/filesystem/lib.ts +++ b/src/filesystem/lib.ts @@ -297,6 +297,7 @@ export async function tailFile(filePath: string, numLines: number): Promise 0 && linesFound < numLines) { @@ -311,7 +312,12 @@ export async function tailFile(filePath: string, numLines: number): Promise