@@ -289,7 +289,17 @@ describe("createAITools filesystem tools", () => {
289289 ) ;
290290 await expect ( executeTool ( tools . ls , { path : "/workspace/notes" } ) ) . resolves . toEqual ( {
291291 path : "/workspace/notes" ,
292- entries : [ { name : "todo.txt" , isFile : true , isDirectory : false } ] ,
292+ count : 1 ,
293+ entries : [
294+ {
295+ name : "todo.txt" ,
296+ size : 8 ,
297+ mtime : 1_700_000_000_000 ,
298+ isFile : true ,
299+ isDirectory : false ,
300+ isSymbolicLink : false ,
301+ } ,
302+ ] ,
293303 } ) ;
294304 await expect (
295305 executeTool ( tools . read , { path : "/workspace/notes/todo.txt" , limit : 1 } ) ,
@@ -313,6 +323,32 @@ describe("createAITools filesystem tools", () => {
313323 ) ;
314324 } ) ;
315325
326+ it ( "paginates ls results and reports a continuation offset" , async ( ) => {
327+ const workspace = makeWorkspace ( ) ;
328+ await workspace . fs . mkdir ( "/workspace" , { recursive : true } ) ;
329+ for ( const name of [ "a" , "b" , "c" ] ) {
330+ await workspace . fs . writeFile ( `/workspace/${ name } ` , name ) ;
331+ }
332+ const tools = createAITools ( { workspace } ) ;
333+
334+ await expect (
335+ executeTool ( tools . ls , { path : "/workspace" , limit : 2 , offset : 0 } ) ,
336+ ) . resolves . toMatchObject ( {
337+ count : 2 ,
338+ entries : [
339+ { name : "a" , size : 1 } ,
340+ { name : "b" , size : 1 } ,
341+ ] ,
342+ nextOffset : 2 ,
343+ } ) ;
344+ await expect (
345+ executeTool ( tools . ls , { path : "/workspace" , limit : 2 , offset : 2 } ) ,
346+ ) . resolves . toMatchObject ( {
347+ count : 1 ,
348+ entries : [ { name : "c" , size : 1 } ] ,
349+ } ) ;
350+ } ) ;
351+
316352 it ( "preserves file mode when write overwrites an existing file" , async ( ) => {
317353 const writes : Array < { path : string ; content : string ; mode ?: number } > = [ ] ;
318354 const tool = createWriteTool ( {
0 commit comments