Skip to content

Commit 290fccd

Browse files
feat(adk): optimize filesystem
1 parent 2adf661 commit 290fccd

File tree

5 files changed

+33
-91
lines changed

5 files changed

+33
-91
lines changed

adk/filesystem/backend.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -272,16 +272,10 @@ type ExecuteResponse struct {
272272
Truncated bool // Whether the output was truncated
273273
}
274274

275-
// ShellBackend is a shell backend interface that extends Backend and adds command execution functionality.
276-
type ShellBackend interface {
277-
Backend
278-
// Execute executes a command and returns the result.
275+
type Shell interface {
279276
Execute(ctx context.Context, input *ExecuteRequest) (result *ExecuteResponse, err error)
280277
}
281278

282-
// StreamingShellBackend is a streaming shell backend interface that supports streaming command execution results.
283-
type StreamingShellBackend interface {
284-
Backend
285-
// ExecuteStreaming executes a command in streaming mode and returns the result.
279+
type StreamingShell interface {
286280
ExecuteStreaming(ctx context.Context, input *ExecuteRequest) (result *schema.StreamReader[*ExecuteResponse], err error)
287281
}

adk/middlewares/filesystem/backend.go

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
package filesystem
1919

2020
import (
21-
"context"
22-
2321
"github.com/cloudwego/eino/adk/filesystem"
2422
)
2523

@@ -31,49 +29,3 @@ type GrepRequest = filesystem.GrepRequest
3129
type GlobInfoRequest = filesystem.GlobInfoRequest
3230
type WriteRequest = filesystem.WriteRequest
3331
type EditRequest = filesystem.EditRequest
34-
35-
// Backend is a pluggable, unified file backend protocol interface.
36-
//
37-
// All methods use struct-based parameters to allow future extensibility
38-
// without breaking backward compatibility.
39-
type Backend interface {
40-
// LsInfo lists file information under the given path.
41-
//
42-
// Returns:
43-
// - []FileInfo: List of matching file information
44-
// - error: Error if the operation fails
45-
LsInfo(ctx context.Context, req *LsInfoRequest) ([]FileInfo, error)
46-
47-
// Read reads file content with support for line-based offset and limit.
48-
//
49-
// Returns:
50-
// - string: The file content read
51-
// - error: Error if file does not exist or read fails
52-
Read(ctx context.Context, req *ReadRequest) (string, error)
53-
54-
// GrepRaw searches for content matching the specified pattern in files.
55-
//
56-
// Returns:
57-
// - []GrepMatch: List of all matching results
58-
// - error: Error if the search fails
59-
GrepRaw(ctx context.Context, req *GrepRequest) ([]GrepMatch, error)
60-
61-
// GlobInfo returns file information matching the glob pattern.
62-
//
63-
// Returns:
64-
// - []FileInfo: List of matching file information
65-
// - error: Error if the pattern is invalid or operation fails
66-
GlobInfo(ctx context.Context, req *GlobInfoRequest) ([]FileInfo, error)
67-
68-
// Write creates or updates file content.
69-
//
70-
// Returns:
71-
// - error: Error if the write operation fails
72-
Write(ctx context.Context, req *WriteRequest) error
73-
74-
// Edit replaces string occurrences in a file.
75-
//
76-
// Returns:
77-
// - error: Error if file does not exist, OldString is empty, or OldString is not found
78-
Edit(ctx context.Context, req *EditRequest) error
79-
}

adk/middlewares/filesystem/filesystem.go

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,17 @@ import (
3737
// Config is the configuration for the filesystem middleware
3838
type Config struct {
3939
// Backend provides filesystem operations used by tools and offloading.
40-
// If the Backend also implements ShellBackend, an additional execute tool
41-
// will be registered to support shell command execution.
4240
// required
43-
Backend Backend
41+
Backend filesystem.Backend
42+
43+
// Shell provides shell command execution capability.
44+
// If set, an execute tool will be registered to support shell command execution.
45+
// optional, mutually exclusive with StreamingShell
46+
Shell filesystem.Shell
47+
// StreamingShell provides streaming shell command execution capability.
48+
// If set, a streaming execute tool will be registered for real-time output.
49+
// optional, mutually exclusive with Shell
50+
StreamingShell filesystem.StreamingShell
4451

4552
// WithoutLargeToolResultOffloading disables automatic offloading of large tool result to Backend
4653
// optional, false(enabled) by default
@@ -86,6 +93,9 @@ func (c *Config) Validate() error {
8693
if c.Backend == nil {
8794
return errors.New("backend should not be nil")
8895
}
96+
if c.StreamingShell != nil && c.Shell != nil {
97+
return errors.New("shell and streaming shell should not be both set")
98+
}
8999
return nil
90100
}
91101

@@ -109,18 +119,16 @@ func NewMiddleware(ctx context.Context, config *Config) (adk.AgentMiddleware, er
109119
if config.CustomSystemPrompt != nil {
110120
systemPrompt = *config.CustomSystemPrompt
111121
} else {
112-
var err error
113122
systemPrompt, err = internal.SelectPrompt(internal.I18nPrompts{
114123
English: ToolsSystemPrompt,
115124
Chinese: ToolsSystemPromptChinese,
116125
})
117126
if err != nil {
118127
return adk.AgentMiddleware{}, err
119128
}
120-
_, ok1 := config.Backend.(filesystem.StreamingShellBackend)
121-
_, ok2 := config.Backend.(filesystem.ShellBackend)
122-
if ok1 || ok2 {
123-
executePrompt, err := internal.SelectPrompt(internal.I18nPrompts{
129+
if config.Shell != nil || config.StreamingShell != nil {
130+
var executePrompt string
131+
executePrompt, err = internal.SelectPrompt(internal.I18nPrompts{
124132
English: ExecuteToolsSystemPrompt,
125133
Chinese: ExecuteToolsSystemPromptChinese,
126134
})
@@ -187,10 +195,9 @@ func NewChatModelAgentMiddleware(ctx context.Context, config *Config) (adk.ChatM
187195
if err != nil {
188196
return nil, err
189197
}
190-
_, ok1 := config.Backend.(filesystem.StreamingShellBackend)
191-
_, ok2 := config.Backend.(filesystem.ShellBackend)
192-
if ok1 || ok2 {
193-
executePrompt, err := internal.SelectPrompt(internal.I18nPrompts{
198+
if config.Shell != nil || config.StreamingShell != nil {
199+
var executePrompt string
200+
executePrompt, err = internal.SelectPrompt(internal.I18nPrompts{
194201
English: ExecuteToolsSystemPrompt,
195202
Chinese: ExecuteToolsSystemPromptChinese,
196203
})
@@ -324,16 +331,16 @@ func getFilesystemTools(_ context.Context, validatedConfig *Config) ([]tool.Base
324331
}
325332
tools = append(tools, grepTool)
326333

327-
if sb, ok := validatedConfig.Backend.(filesystem.StreamingShellBackend); ok {
334+
if validatedConfig.StreamingShell != nil {
328335
var executeTool tool.BaseTool
329-
executeTool, err = newStreamingExecuteTool(sb, validatedConfig.CustomExecuteToolDesc)
336+
executeTool, err = newStreamingExecuteTool(validatedConfig.StreamingShell, validatedConfig.CustomExecuteToolDesc)
330337
if err != nil {
331338
return nil, err
332339
}
333340
tools = append(tools, executeTool)
334-
} else if sb, ok := validatedConfig.Backend.(filesystem.ShellBackend); ok {
341+
} else if validatedConfig.Shell != nil {
335342
var executeTool tool.BaseTool
336-
executeTool, err = newExecuteTool(sb, validatedConfig.CustomExecuteToolDesc)
343+
executeTool, err = newExecuteTool(validatedConfig.Shell, validatedConfig.CustomExecuteToolDesc)
337344
if err != nil {
338345
return nil, err
339346
}
@@ -641,7 +648,7 @@ type executeArgs struct {
641648
Command string `json:"command"`
642649
}
643650

644-
func newExecuteTool(sb filesystem.ShellBackend, desc *string) (tool.BaseTool, error) {
651+
func newExecuteTool(sb filesystem.Shell, desc *string) (tool.BaseTool, error) {
645652
d, err := selectToolDesc(desc, ExecuteToolDesc, ExecuteToolDescChinese)
646653
if err != nil {
647654
return nil, err
@@ -658,7 +665,7 @@ func newExecuteTool(sb filesystem.ShellBackend, desc *string) (tool.BaseTool, er
658665
})
659666
}
660667

661-
func newStreamingExecuteTool(sb filesystem.StreamingShellBackend, desc *string) (tool.BaseTool, error) {
668+
func newStreamingExecuteTool(sb filesystem.StreamingShell, desc *string) (tool.BaseTool, error) {
662669
d, err := selectToolDesc(desc, ExecuteToolDesc, ExecuteToolDescChinese)
663670
if err != nil {
664671
return nil, err

adk/middlewares/filesystem/filesystem_test.go

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -561,18 +561,6 @@ func TestNewMiddleware(t *testing.T) {
561561
assert.Nil(t, m.WrapToolCall.Invokable)
562562
assert.Nil(t, m.WrapToolCall.Streamable)
563563
})
564-
565-
t.Run("ShellBackend adds execute tool", func(t *testing.T) {
566-
shellBackend := &mockShellBackend{
567-
Backend: backend,
568-
resp: &filesystem.ExecuteResponse{Output: "ok"},
569-
}
570-
m, err := NewMiddleware(ctx, &Config{Backend: shellBackend})
571-
assert.NoError(t, err)
572-
573-
// ShellBackend should have 7 tools (6 + execute)
574-
assert.Len(t, m.AdditionalTools, 7)
575-
})
576564
}
577565

578566
func TestGetFilesystemTools(t *testing.T) {
@@ -598,12 +586,12 @@ func TestGetFilesystemTools(t *testing.T) {
598586
assert.Contains(t, toolNames, "grep")
599587
})
600588

601-
t.Run("returns 7 tools for ShellBackend", func(t *testing.T) {
589+
t.Run("returns 7 tools for Shell", func(t *testing.T) {
602590
shellBackend := &mockShellBackend{
603591
Backend: backend,
604592
resp: &filesystem.ExecuteResponse{Output: "ok"},
605593
}
606-
tools, err := getFilesystemTools(ctx, &Config{Backend: shellBackend})
594+
tools, err := getFilesystemTools(ctx, &Config{Backend: shellBackend, Shell: shellBackend})
607595
assert.NoError(t, err)
608596
assert.Len(t, tools, 7)
609597

@@ -699,7 +687,7 @@ func TestNewChatModelAgentMiddleware(t *testing.T) {
699687
Backend: backend,
700688
resp: &filesystem.ExecuteResponse{Output: "ok"},
701689
}
702-
m, err := NewChatModelAgentMiddleware(ctx, &Config{Backend: shellBackend})
690+
m, err := NewChatModelAgentMiddleware(ctx, &Config{Backend: shellBackend, Shell: shellBackend})
703691
assert.NoError(t, err)
704692

705693
fm, ok := m.(*filesystemMiddleware)

adk/middlewares/filesystem/large_tool_result.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,14 @@ import (
2727

2828
"github.com/slongfield/pyfmt"
2929

30+
"github.com/cloudwego/eino/adk/filesystem"
3031
"github.com/cloudwego/eino/adk/internal"
3132
"github.com/cloudwego/eino/compose"
3233
"github.com/cloudwego/eino/schema"
3334
)
3435

3536
type toolResultOffloadingConfig struct {
36-
Backend Backend
37+
Backend filesystem.Backend
3738
TokenLimit int
3839
PathGenerator func(ctx context.Context, input *compose.ToolInput) (string, error)
3940
}
@@ -62,7 +63,7 @@ func newToolResultOffloading(ctx context.Context, config *toolResultOffloadingCo
6263
}
6364

6465
type toolResultOffloading struct {
65-
backend Backend
66+
backend filesystem.Backend
6667
tokenLimit int
6768
pathGenerator func(ctx context.Context, input *compose.ToolInput) (string, error)
6869
}

0 commit comments

Comments
 (0)