From 84734a3c99b13b51c521462a24b1cd511aa7aa55 Mon Sep 17 00:00:00 2001 From: GerardGao <213731635+GerardGao@users.noreply.github.com> Date: Mon, 24 Aug 2026 20:11:17 +0800 Subject: [PATCH] fix(local): populate IsDir, Size and ModifiedAt in LsInfo results Local.LsInfo filled only FileInfo.Path, so models using the ls tool could not tell files from directories and had no size information to avoid reading large or binary files. Fill the same fields the in-memory backend already returns. Fixes cloudwego/eino#1100 --- adk/backend/local/local.go | 9 ++++++++- adk/backend/local/local_test.go | 32 +++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/adk/backend/local/local.go b/adk/backend/local/local.go index bc1953302..8667f78f7 100644 --- a/adk/backend/local/local.go +++ b/adk/backend/local/local.go @@ -298,8 +298,15 @@ func (s *Local) LsInfo(ctx context.Context, req *filesystem.LsInfoRequest) ([]fi var files []filesystem.FileInfo for _, entry := range entries { + info, err := entry.Info() + if err != nil { + return nil, fmt.Errorf("failed to get info of %s: %w", entry.Name(), err) + } files = append(files, filesystem.FileInfo{ - Path: entry.Name(), + Path: entry.Name(), + IsDir: entry.IsDir(), + Size: info.Size(), + ModifiedAt: info.ModTime().Format(time.RFC3339Nano), }) } diff --git a/adk/backend/local/local_test.go b/adk/backend/local/local_test.go index 52435626b..2d613b557 100644 --- a/adk/backend/local/local_test.go +++ b/adk/backend/local/local_test.go @@ -23,6 +23,7 @@ import ( "fmt" "os" "path/filepath" + "runtime" "strings" "testing" "time" @@ -51,7 +52,7 @@ func TestLsInfo(t *testing.T) { defer os.RemoveAll(dir) // Create test files and directories - assert.NoError(t, os.WriteFile(filepath.Join(dir, "file1.txt"), []byte(""), 0644)) + assert.NoError(t, os.WriteFile(filepath.Join(dir, "file1.txt"), []byte("hello"), 0644)) assert.NoError(t, os.Mkdir(filepath.Join(dir, "subdir"), 0755)) req := &filesystem.LsInfoRequest{Path: dir} @@ -59,7 +60,36 @@ func TestLsInfo(t *testing.T) { assert.NoError(t, err) assert.Len(t, files, 2) assert.Equal(t, "file1.txt", files[0].Path) + assert.False(t, files[0].IsDir) + assert.Equal(t, int64(len("hello")), files[0].Size) + _, err = time.Parse(time.RFC3339Nano, files[0].ModifiedAt) + assert.NoError(t, err) assert.Equal(t, "subdir", files[1].Path) + assert.True(t, files[1].IsDir) + _, err = time.Parse(time.RFC3339Nano, files[1].ModifiedAt) + assert.NoError(t, err) + }) + + t.Run("symlink entries report the link itself", func(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("creating symlinks on windows requires privileges") + } + + dir := setupTestDir(t) + defer os.RemoveAll(dir) + + assert.NoError(t, os.WriteFile(filepath.Join(dir, "target.txt"), []byte("hello"), 0644)) + assert.NoError(t, os.Symlink("target.txt", filepath.Join(dir, "link.txt"))) + + req := &filesystem.LsInfoRequest{Path: dir} + files, err := s.LsInfo(ctx, req) + assert.NoError(t, err) + assert.Len(t, files, 2) + assert.Equal(t, "link.txt", files[0].Path) + assert.False(t, files[0].IsDir) + assert.Equal(t, int64(len("target.txt")), files[0].Size) + assert.Equal(t, "target.txt", files[1].Path) + assert.False(t, files[1].IsDir) }) t.Run("list non-existent directory", func(t *testing.T) {