cloudwego / cloudwego/eino-ext
adk/backend/local: Local backend is not compatible with plantask.Backend
- Dominant language
- Go
- Stars
- 811
- Forks
- 368
- Avg merge
- 16h 22m
- Merged PRs (30d)
- 13
Description
**Describe the bug**
`github.com/cloudwego/eino-ext/adk/backend/local.Local` implements `github.com/cloudwego/eino/adk/filesystem.Backend`, and can be used by the filesystem middleware and the skill filesystem backend.
However, it cannot be used directly with `github.com/cloudwego/eino/adk/middlewares/plantask`, even though `plantask` reuses the same filesystem request/response types for `LsInfo`, `Read`, and `Write`.
There are two incompatibilities:
1. `plantask.Backend` requires `Delete`, but `local.Local` does not implement it.
2. `local.Local.LsInfo` returns only entry names, while `plantask` treats `FileInfo.Path` as a path that can be passed back to `Read`.
**To Reproduce**
Steps to reproduce the behavior:
1. Create a small module that imports both packages and points them at local/current versions:
```go
package main
import (
"context"
extlocal "github.com/cloudwego/eino-ext/adk/backend/local"
"github.com/cloudwego/eino/adk/filesystem"
"github.com/cloudwego/eino/adk/middlewares/plantask"
)
func main() {
ctx := context.Background()
b, err := extlocal.NewBackend(ctx, &extlocal.Config{})
if err != nil {
panic(err)
}
var _ filesystem.Backend = b // OK
var _ plantask.Backend = b // FAIL
}
```
2. Run `go test ./...` or `go build`.
3. The compile-time check fails:
```text
./main.go:19:27: cannot use b (variable of type *local.Local) as plantask.Backend value in variable declaration: *local.Local does not implement plantask.Backend (missing method Delete)
```
4. Even if `Delete` is provided externally, `LsInfo` path semantics still do not match `plantask`'s current usage. `local.Local.LsInfo` returns basenames:
```go
files = append(files, filesystem.FileInfo{
Path: entry.Name(),
})
```
For example, listing `/tmp/tasks` may return:
```go
FileInfo{Path: ".highwatermark"}
FileInfo{Path: "1.json"}
```
But `plantask` uses `file.Path` directly as a readable path:
```go
content, readErr := t.Backend.Read(ctx, &ReadRequest{
FilePath: file.Path,
})
```
With `local.Local`, `Read(".highwatermark")` reads from the process working directory, not from the requested `BaseDir` such as `/tmp/tasks`.
**Expected behavior**
A local backend intended for ADK middleware usage should be usable with `plantask`, or the documentation should clearly state that `filesystem.Backend` implementations are not directly compatible with `plantask.Backend`.
For example, this should either compile and work, or have a documented adapter requirement:
```go
localBackend, _ := local.NewBackend(ctx, &local.Config{})
mw, err := plantask.New(ctx, &plantask.Config{
Backend: localBackend,
BaseDir: "/tmp/tasks",
})
```
**Screenshots**
N/A
**Version:**
Verified against:
- `cloudwego/eino-ext` local commit: `7f6839c`
- `github.com/cloudwego/eino-ext/adk/backend/local/go.mod` requires `github.com/cloudwego/eino v0.9.1`
- `cloudwego/eino` local commit used for checking current `plantask`: `ad1d0af`
**Environment:**
Relevant `go env` output:
```text
GOOS='linux'
GOARCH='amd64'
GOVERSION='go1.25.0'
GOTOOLCHAIN='go1.24.11+auto'
CGO_ENABLED='1'
GOMOD='/home/yanxu.666/projects/github/eino-ext/adk/backend/local/go.mod'
GOMODCACHE='/home/yanxu.666/go/pkg/mod'
GOWORK=''
```
**Additional context**
`filesystem.FileInfo.Path` is documented as allowing a filename, relative path, or absolute path. Therefore `local.Local.LsInfo` returning `entry.Name()` is valid for the shared filesystem backend contract.
The mismatch seems to come from `plantask` assuming a stronger contract than `filesystem.FileInfo.Path` documents: it expects `LsInfo` results to be directly readable with `Read`.
Possible fixes:
- Provide a `plantask` adapter that wraps a `filesystem.Backend`, implements `Delete`, and normalizes non-absolute `LsInfo` paths by joining them with the requested directory.
- Or normalize paths inside `plantask` before calling `Read`, for example:
```go
filePath := file.Path
if !filepath.IsAbs(filePath) {
filePath = filepath.Join(baseDir, filePath)
}
```
This would make `plantask` compatible with all valid `filesystem.FileInfo.Path` forms.
Contributor guide
Research direction
Start by inspecting the adk/backend/local package and the plantask.Backend and filesystem.Backend interfaces, then reproduce the compile-time assertion and the LsInfo/Read path mismatch described here. Determine whether compatibility should come from a plantask adapter or path normalization, and verify that the chosen approach supports Delete and makes listed files readable from BaseDir.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100