@@ -32,8 +32,10 @@ import (
3232)
3333
3434const (
35- localFileDefaultReadLimit = 12000
36- localFileMaxReadLimit = 100000
35+ localFileDefaultPreviewChars = 1200
36+ localFileMaxPreviewChars = 20000
37+ localFileDefaultReadLimit = 12000
38+ localFileMaxReadLimit = 100000
3739)
3840
3941// LocalFileTool is the Tool Type "local_file".
@@ -44,17 +46,23 @@ type LocalFileTool struct {
4446func (p * LocalFileTool ) BuiltinTools () []BuiltinTool {
4547 return []BuiltinTool {
4648 & localSpecialDirsBuiltin {},
47- & localFileScanBuiltin {},
49+ & localFileScanBuiltin {lang : p . lang },
4850 & localFileReadBuiltin {lang : p .lang },
4951 & localFileWriteBuiltin {},
5052 & localFileMoveBuiltin {},
5153 }
5254}
5355
5456type localFileScanItem struct {
55- Type string `json:"type"`
56- Name string `json:"name"`
57- Path string `json:"path"`
57+ Type string `json:"type"`
58+ Name string `json:"name"`
59+ Path string `json:"path"`
60+ Size int64 `json:"size,omitempty"`
61+ ModifiedTime string `json:"modifiedTime,omitempty"`
62+ TextLength int `json:"textLength,omitempty"`
63+ Preview string `json:"preview,omitempty"`
64+ Truncated bool `json:"truncated,omitempty"`
65+ Error string `json:"error,omitempty"`
5866}
5967
6068type localSpecialDirInfo struct {
@@ -283,7 +291,9 @@ func (b *localSpecialDirsBuiltin) Execute(_ context.Context, _ map[string]interf
283291 }), nil
284292}
285293
286- type localFileScanBuiltin struct {}
294+ type localFileScanBuiltin struct {
295+ lang string
296+ }
287297
288298func (b * localFileScanBuiltin ) GetName () string {
289299 return "local_file_scan"
@@ -292,7 +302,8 @@ func (b *localFileScanBuiltin) GetName() string {
292302func (b * localFileScanBuiltin ) GetDescription () string {
293303 return `Scan a local directory recursively and return a JSON manifest of all descendant files and directories.
294304- root (required): absolute directory path for the current operating system.
295- - Returns items with type, name, and path.`
305+ - preview_chars: maximum text preview characters per file (default 1200, max 20000). Set to 0 to skip previews.
306+ - Returns items with type, name, path, size, modifiedTime, and a text preview for readable files.`
296307}
297308
298309func (b * localFileScanBuiltin ) GetInputSchema () interface {} {
@@ -303,6 +314,10 @@ func (b *localFileScanBuiltin) GetInputSchema() interface{} {
303314 "type" : "string" ,
304315 "description" : "Absolute directory path to scan." ,
305316 },
317+ "preview_chars" : map [string ]interface {}{
318+ "type" : "number" ,
319+ "description" : "Maximum text preview characters per file (default 1200, max 20000). Set to 0 to skip previews." ,
320+ },
306321 },
307322 "required" : []string {"root" },
308323 }
@@ -322,6 +337,9 @@ func (b *localFileScanBuiltin) Execute(_ context.Context, arguments map[string]i
322337 return localFileError ("root must be a directory" ), nil
323338 }
324339
340+ previewChars := localFileIntArg (arguments , "preview_chars" , localFileDefaultPreviewChars )
341+ previewChars = localFileClamp (previewChars , 0 , localFileMaxPreviewChars )
342+
325343 var items []localFileScanItem
326344 walkErr := filepath .WalkDir (root , func (path string , d fs.DirEntry , err error ) error {
327345 if err != nil {
@@ -331,15 +349,34 @@ func (b *localFileScanBuiltin) Execute(_ context.Context, arguments map[string]i
331349 return nil
332350 }
333351
334- itemType := "file"
335352 if d .IsDir () {
336- itemType = "directory"
353+ items = append (items , localFileScanItem {
354+ Type : "directory" ,
355+ Name : d .Name (),
356+ Path : path ,
357+ })
358+ return nil
337359 }
338- items = append (items , localFileScanItem {
339- Type : itemType ,
360+
361+ item := localFileScanItem {
362+ Type : "file" ,
340363 Name : d .Name (),
341364 Path : path ,
342- })
365+ }
366+ if fileInfo , statErr := d .Info (); statErr == nil {
367+ item .Size = fileInfo .Size ()
368+ item .ModifiedTime = fileInfo .ModTime ().Format ("2006-01-02 15:04:05" )
369+ }
370+ if previewChars > 0 {
371+ ext := strings .ToLower (filepath .Ext (path ))
372+ if text , readErr := localFileReadText (path , ext , b .lang ); readErr != nil {
373+ item .Error = readErr .Error ()
374+ } else {
375+ item .TextLength = len ([]rune (text ))
376+ item .Preview , item .Truncated = localFileSliceText (text , 0 , previewChars )
377+ }
378+ }
379+ items = append (items , item )
343380 return nil
344381 })
345382 if walkErr != nil {
0 commit comments