@@ -276,13 +276,31 @@ describe("ReadCommandOutputTool", () => {
276276 } )
277277
278278 describe ( "Search filtering" , ( ) => {
279+ // Helper to setup file handle mock for search (which now uses streaming)
280+ const setupSearchMock = ( content : string ) => {
281+ const buffer = Buffer . from ( content )
282+ const fileSize = buffer . length
283+ vi . mocked ( fs . stat ) . mockResolvedValue ( { size : fileSize } as any )
284+
285+ // Mock streaming read - return entire content in one chunk (simulates small file)
286+ mockFileHandle . read . mockImplementation (
287+ ( buf : Buffer , bufOffset : number , length : number , position : number | null ) => {
288+ const pos = position ?? 0
289+ if ( pos >= fileSize ) {
290+ return Promise . resolve ( { bytesRead : 0 } )
291+ }
292+ const bytesToRead = Math . min ( length , fileSize - pos )
293+ buffer . copy ( buf , 0 , pos , pos + bytesToRead )
294+ return Promise . resolve ( { bytesRead : bytesToRead } )
295+ } ,
296+ )
297+ }
298+
279299 it ( "should filter lines matching pattern" , async ( ) => {
280300 const artifactId = "cmd-1706119234567.txt"
281301 const content = "Line 1: error occurred\nLine 2: success\nLine 3: error found\nLine 4: complete\n"
282- const fileSize = Buffer . byteLength ( content , "utf8" )
283302
284- vi . mocked ( fs . stat ) . mockResolvedValue ( { size : fileSize } as any )
285- vi . mocked ( fs . readFile ) . mockResolvedValue ( content )
303+ setupSearchMock ( content )
286304
287305 await tool . execute ( { artifact_id : artifactId , search : "error" } , mockTask , mockCallbacks )
288306
@@ -296,10 +314,8 @@ describe("ReadCommandOutputTool", () => {
296314 it ( "should use case-insensitive matching" , async ( ) => {
297315 const artifactId = "cmd-1706119234567.txt"
298316 const content = "ERROR: Something bad\nwarning: minor issue\nERROR: Another problem\n"
299- const fileSize = Buffer . byteLength ( content , "utf8" )
300317
301- vi . mocked ( fs . stat ) . mockResolvedValue ( { size : fileSize } as any )
302- vi . mocked ( fs . readFile ) . mockResolvedValue ( content )
318+ setupSearchMock ( content )
303319
304320 await tool . execute ( { artifact_id : artifactId , search : "error" } , mockTask , mockCallbacks )
305321
@@ -311,10 +327,8 @@ describe("ReadCommandOutputTool", () => {
311327 it ( "should show match count and line numbers" , async ( ) => {
312328 const artifactId = "cmd-1706119234567.txt"
313329 const content = "Line 1\nError on line 2\nLine 3\nError on line 4\n"
314- const fileSize = Buffer . byteLength ( content , "utf8" )
315330
316- vi . mocked ( fs . stat ) . mockResolvedValue ( { size : fileSize } as any )
317- vi . mocked ( fs . readFile ) . mockResolvedValue ( content )
331+ setupSearchMock ( content )
318332
319333 await tool . execute ( { artifact_id : artifactId , search : "Error" } , mockTask , mockCallbacks )
320334
@@ -327,10 +341,8 @@ describe("ReadCommandOutputTool", () => {
327341 it ( "should handle empty search results gracefully" , async ( ) => {
328342 const artifactId = "cmd-1706119234567.txt"
329343 const content = "Line 1\nLine 2\nLine 3\n"
330- const fileSize = Buffer . byteLength ( content , "utf8" )
331344
332- vi . mocked ( fs . stat ) . mockResolvedValue ( { size : fileSize } as any )
333- vi . mocked ( fs . readFile ) . mockResolvedValue ( content )
345+ setupSearchMock ( content )
334346
335347 await tool . execute ( { artifact_id : artifactId , search : "NOTFOUND" } , mockTask , mockCallbacks )
336348
@@ -341,10 +353,8 @@ describe("ReadCommandOutputTool", () => {
341353 it ( "should handle regex patterns in search" , async ( ) => {
342354 const artifactId = "cmd-1706119234567.txt"
343355 const content = "test123\ntest456\nabc789\ntest000\n"
344- const fileSize = Buffer . byteLength ( content , "utf8" )
345356
346- vi . mocked ( fs . stat ) . mockResolvedValue ( { size : fileSize } as any )
347- vi . mocked ( fs . readFile ) . mockResolvedValue ( content )
357+ setupSearchMock ( content )
348358
349359 await tool . execute ( { artifact_id : artifactId , search : "test\\d+" } , mockTask , mockCallbacks )
350360
@@ -358,10 +368,8 @@ describe("ReadCommandOutputTool", () => {
358368 it ( "should handle invalid regex patterns by treating as literal" , async ( ) => {
359369 const artifactId = "cmd-1706119234567.txt"
360370 const content = "Line with [brackets]\nLine without\n"
361- const fileSize = Buffer . byteLength ( content , "utf8" )
362371
363- vi . mocked ( fs . stat ) . mockResolvedValue ( { size : fileSize } as any )
364- vi . mocked ( fs . readFile ) . mockResolvedValue ( content )
372+ setupSearchMock ( content )
365373
366374 // Invalid regex but valid as literal string
367375 await tool . execute ( { artifact_id : artifactId , search : "[" } , mockTask , mockCallbacks )
0 commit comments