Skip to content

Commit d00cc03

Browse files
committed
refactor: export backend struct types for external access
Export struct types to enable direct type references from external packages. Main changes: - Rename sandboxToolBackend to SandboxToolBackend in agentkit package - Rename backend to Backend in local package - Update NewSandboxToolBackend() return type from filesystem.Backend interface to concrete *SandboxToolBackend - Update NewBackend() return type from filesystem.Backend interface to concrete *Backend - Update all method receivers and test assertions to use the exported type names Impact: - External packages can now access the concrete backend types directly - Enables type assertions and direct struct field access when needed - Maintains backward compatibility since the types still implement filesystem.Backend interface
1 parent 1f91f54 commit d00cc03

File tree

4 files changed

+42
-51
lines changed

4 files changed

+42
-51
lines changed

adk/backend/agentkit/sandbox.go

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ type Config struct {
104104
ExecutionTimeout int
105105
}
106106

107-
type sandboxToolBackend struct {
107+
type SandboxToolBackend struct {
108108
secretAccessKey string
109109
accessKeyID string
110110
baseURL string
@@ -117,14 +117,14 @@ type sandboxToolBackend struct {
117117
executionTimeout int
118118
}
119119

120-
// NewSandboxToolBackend creates a new sandboxToolBackend instance.
121-
// sandboxToolBackend refers to the sandbox running instance created by the sandbox tool in Volcengine.
120+
// NewSandboxToolBackend creates a new SandboxToolBackend instance.
121+
// SandboxToolBackend refers to the sandbox running instance created by the sandbox tool in Volcengine.
122122
// For creating a sandbox tool environment, please refer to: https://www.volcengine.com/docs/86681/1847934?lang=zh;
123123
// For creating a sandbox tool running instance, please refer to: https://www.volcengine.com/docs/86681/1860266?lang=zh.
124124
// Note: The execution paths within the sandbox environment may be subject to permission restrictions (read, write, execute, etc.).
125125
// Improper path selection can result in operation failures or permission errors.
126126
// It is recommended to perform operations within paths where the sandbox environment has explicit permissions to mitigate permission-related risks.
127-
func NewSandboxToolBackend(config *Config) (filesystem.Backend, error) {
127+
func NewSandboxToolBackend(config *Config) (*SandboxToolBackend, error) {
128128
if config.AccessKeyID == "" {
129129
return nil, fmt.Errorf("AccessKeyID is required")
130130
}
@@ -159,7 +159,7 @@ func NewSandboxToolBackend(config *Config) (filesystem.Backend, error) {
159159
return nil, fmt.Errorf("invalid region: %s", region)
160160
}
161161

162-
return &sandboxToolBackend{
162+
return &SandboxToolBackend{
163163
accessKeyID: config.AccessKeyID,
164164
secretAccessKey: config.SecretAccessKey,
165165
httpClient: httpClient,
@@ -174,7 +174,7 @@ func NewSandboxToolBackend(config *Config) (filesystem.Backend, error) {
174174
}
175175

176176
// LsInfo lists file information under the given path.
177-
func (s *sandboxToolBackend) LsInfo(ctx context.Context, req *filesystem.LsInfoRequest) ([]filesystem.FileInfo, error) {
177+
func (s *SandboxToolBackend) LsInfo(ctx context.Context, req *filesystem.LsInfoRequest) ([]filesystem.FileInfo, error) {
178178
path, err := formatPath(req.Path, "/", true)
179179
if err != nil {
180180
return nil, err
@@ -216,7 +216,7 @@ func (s *sandboxToolBackend) LsInfo(ctx context.Context, req *filesystem.LsInfoR
216216
}
217217

218218
// Read reads file content with support for line-based offset and limit.
219-
func (s *sandboxToolBackend) Read(ctx context.Context, req *filesystem.ReadRequest) (string, error) {
219+
func (s *SandboxToolBackend) Read(ctx context.Context, req *filesystem.ReadRequest) (string, error) {
220220
path, err := formatPath(req.FilePath, "", true)
221221
if err != nil {
222222
return "", err
@@ -251,7 +251,7 @@ func (s *sandboxToolBackend) Read(ctx context.Context, req *filesystem.ReadReque
251251
}
252252

253253
// GrepRaw searches for content matching the specified pattern in files.
254-
func (s *sandboxToolBackend) GrepRaw(ctx context.Context, req *filesystem.GrepRequest) ([]filesystem.GrepMatch, error) {
254+
func (s *SandboxToolBackend) GrepRaw(ctx context.Context, req *filesystem.GrepRequest) ([]filesystem.GrepMatch, error) {
255255
path, _ := formatPath(req.Path, "", false)
256256
params := map[string]any{
257257
"pattern": req.Pattern,
@@ -292,7 +292,7 @@ func (s *sandboxToolBackend) GrepRaw(ctx context.Context, req *filesystem.GrepRe
292292
}
293293

294294
// GlobInfo returns file information matching the glob pattern.
295-
func (s *sandboxToolBackend) GlobInfo(ctx context.Context, req *filesystem.GlobInfoRequest) ([]filesystem.FileInfo, error) {
295+
func (s *SandboxToolBackend) GlobInfo(ctx context.Context, req *filesystem.GlobInfoRequest) ([]filesystem.FileInfo, error) {
296296
path, _ := formatPath(req.Path, "/", false)
297297
params := map[string]any{
298298
"path_b64": base64.StdEncoding.EncodeToString([]byte(path)),
@@ -330,7 +330,7 @@ func (s *sandboxToolBackend) GlobInfo(ctx context.Context, req *filesystem.GlobI
330330
}
331331

332332
// Write creates file content.
333-
func (s *sandboxToolBackend) Write(ctx context.Context, req *filesystem.WriteRequest) error {
333+
func (s *SandboxToolBackend) Write(ctx context.Context, req *filesystem.WriteRequest) error {
334334
path, err := formatPath(req.FilePath, "", true)
335335
if err != nil {
336336
return err
@@ -358,7 +358,7 @@ func (s *sandboxToolBackend) Write(ctx context.Context, req *filesystem.WriteReq
358358
}
359359

360360
// Edit replaces string occurrences in a file.
361-
func (s *sandboxToolBackend) Edit(ctx context.Context, req *filesystem.EditRequest) error {
361+
func (s *SandboxToolBackend) Edit(ctx context.Context, req *filesystem.EditRequest) error {
362362
path, err := formatPath(req.FilePath, "", true)
363363
if err != nil {
364364
return err
@@ -401,7 +401,7 @@ func (s *sandboxToolBackend) Edit(ctx context.Context, req *filesystem.EditReque
401401
}
402402

403403
// execute executes a command in the sandbox.
404-
func (s *sandboxToolBackend) execute(ctx context.Context, command string) (text string, exitCode *int, err error) {
404+
func (s *SandboxToolBackend) execute(ctx context.Context, command string) (text string, exitCode *int, err error) {
405405
var operationPayload string
406406
if s.executionTimeout <= 0 {
407407
operationPayload, err = sonic.MarshalString(map[string]any{
@@ -473,7 +473,7 @@ func (s *sandboxToolBackend) execute(ctx context.Context, command string) (text
473473
return text, exitCode, nil
474474
}
475475

476-
func (s *sandboxToolBackend) invokeTool(ctx context.Context, method string, body []byte) ([]byte, error) {
476+
func (s *SandboxToolBackend) invokeTool(ctx context.Context, method string, body []byte) ([]byte, error) {
477477
queries := make(url.Values)
478478
queries.Set("Action", "InvokeTool")
479479
queries.Set("Version", "2025-10-30")
@@ -506,7 +506,7 @@ func (s *sandboxToolBackend) invokeTool(ctx context.Context, method string, body
506506
return responseBody, nil
507507
}
508508

509-
func (s *sandboxToolBackend) signRequest(request *http.Request, queries url.Values, body []byte) {
509+
func (s *SandboxToolBackend) signRequest(request *http.Request, queries url.Values, body []byte) {
510510
now := time.Now()
511511
date := now.UTC().Format("20060102T150405Z")
512512
authDate := date[:8]
@@ -558,7 +558,7 @@ func (s *sandboxToolBackend) signRequest(request *http.Request, queries url.Valu
558558
request.Header.Set("Authorization", authorization)
559559
}
560560

561-
func (s *sandboxToolBackend) Execute(ctx context.Context, input *filesystem.ExecuteRequest) (result *filesystem.ExecuteResponse, err error) {
561+
func (s *SandboxToolBackend) Execute(ctx context.Context, input *filesystem.ExecuteRequest) (result *filesystem.ExecuteResponse, err error) {
562562
if input.Command == "" {
563563
return nil, fmt.Errorf("command is required")
564564
}

adk/backend/agentkit/sandbox_test.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ func TestNewArkSandbox(t *testing.T) {
4040
SessionTTL: 3600,
4141
ExecutionTimeout: 60,
4242
}
43-
ss, err := NewSandboxToolBackend(config)
44-
s := ss.(*sandboxToolBackend)
43+
s, err := NewSandboxToolBackend(config)
44+
4545
require.NoError(t, err)
4646
require.NotNil(t, s)
4747
assert.Equal(t, "test-ak", s.accessKeyID)
@@ -61,8 +61,8 @@ func TestNewArkSandbox(t *testing.T) {
6161
ToolID: "test-tool",
6262
UserSessionID: "test-session",
6363
}
64-
ss, err := NewSandboxToolBackend(config)
65-
s := ss.(*sandboxToolBackend)
64+
s, err := NewSandboxToolBackend(config)
65+
6666
require.NoError(t, err)
6767
require.NotNil(t, s)
6868
assert.Equal(t, RegionOfBeijing, s.region)
@@ -115,7 +115,7 @@ func TestNewArkSandbox(t *testing.T) {
115115
var mockAPIHandler http.HandlerFunc
116116

117117
// setupTest creates a mock server and an ArkSandbox client configured to use it.
118-
func setupTest(t *testing.T) (*sandboxToolBackend, *httptest.Server) {
118+
func setupTest(t *testing.T) (*SandboxToolBackend, *httptest.Server) {
119119
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
120120
if mockAPIHandler != nil {
121121
mockAPIHandler(w, r)
@@ -131,8 +131,7 @@ func setupTest(t *testing.T) (*sandboxToolBackend, *httptest.Server) {
131131
UserSessionID: "test-session",
132132
HTTPClient: server.Client(),
133133
}
134-
ss, err := NewSandboxToolBackend(config)
135-
sandbox := ss.(*sandboxToolBackend)
134+
sandbox, err := NewSandboxToolBackend(config)
136135
require.NoError(t, err)
137136
sandbox.baseURL = server.URL // Override to point to the mock server
138137

adk/backend/local/local.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,22 @@ type Config struct {
4040
ValidateCommand func(string) error
4141
}
4242

43-
type backend struct {
43+
type Backend struct {
4444
validateCommand func(string) error
4545
}
4646

4747
var defaultValidateCommand = func(string) error {
4848
return nil
4949
}
5050

51-
// NewBackend creates a new local filesystem backend instance.
51+
// NewBackend creates a new local filesystem Backend instance.
5252
//
5353
// IMPORTANT - System Compatibility:
5454
// - Supported: Unix/MacOS only
5555
// - NOT Supported: Windows (requires custom implementation of Backend)
5656
// - Command Execution: Uses /bin/sh by default for Execute method
5757
// - If /bin/sh does not meet your requirements, please implement your own Backend
58-
func NewBackend(_ context.Context, cfg *Config) (filesystem.Backend, error) {
58+
func NewBackend(_ context.Context, cfg *Config) (*Backend, error) {
5959
if cfg == nil {
6060
return nil, errors.New("config is required")
6161
}
@@ -65,12 +65,12 @@ func NewBackend(_ context.Context, cfg *Config) (filesystem.Backend, error) {
6565
validateCommand = cfg.ValidateCommand
6666
}
6767

68-
return &backend{
68+
return &Backend{
6969
validateCommand: validateCommand,
7070
}, nil
7171
}
7272

73-
func (s *backend) LsInfo(ctx context.Context, req *filesystem.LsInfoRequest) ([]filesystem.FileInfo, error) {
73+
func (s *Backend) LsInfo(ctx context.Context, req *filesystem.LsInfoRequest) ([]filesystem.FileInfo, error) {
7474
if req.Path == "" {
7575
req.Path = defaultRootPath
7676
}
@@ -105,7 +105,7 @@ func (s *backend) LsInfo(ctx context.Context, req *filesystem.LsInfoRequest) ([]
105105
return files, nil
106106
}
107107

108-
func (s *backend) Read(ctx context.Context, req *filesystem.ReadRequest) (string, error) {
108+
func (s *Backend) Read(ctx context.Context, req *filesystem.ReadRequest) (string, error) {
109109
path := filepath.Clean(req.FilePath)
110110
if !filepath.IsAbs(path) {
111111
return "", fmt.Errorf("path must be an absolute path: %s", path)
@@ -160,7 +160,7 @@ func (s *backend) Read(ctx context.Context, req *filesystem.ReadRequest) (string
160160
return result.String(), nil
161161
}
162162

163-
func (s *backend) GrepRaw(ctx context.Context, req *filesystem.GrepRequest) ([]filesystem.GrepMatch, error) {
163+
func (s *Backend) GrepRaw(ctx context.Context, req *filesystem.GrepRequest) ([]filesystem.GrepMatch, error) {
164164
path := filepath.Clean(req.Path)
165165

166166
var matches []filesystem.GrepMatch
@@ -232,7 +232,7 @@ func (s *backend) GrepRaw(ctx context.Context, req *filesystem.GrepRequest) ([]f
232232
return matches, nil
233233
}
234234

235-
func (s *backend) GlobInfo(ctx context.Context, req *filesystem.GlobInfoRequest) ([]filesystem.FileInfo, error) {
235+
func (s *Backend) GlobInfo(ctx context.Context, req *filesystem.GlobInfoRequest) ([]filesystem.FileInfo, error) {
236236
if req.Path == "" {
237237
req.Path = defaultRootPath
238238
}
@@ -337,7 +337,7 @@ func globToRegex(pattern string) (*regexp.Regexp, error) {
337337
return regexp.Compile(pattern)
338338
}
339339

340-
func (s *backend) Write(ctx context.Context, req *filesystem.WriteRequest) error {
340+
func (s *Backend) Write(ctx context.Context, req *filesystem.WriteRequest) error {
341341
if !filepath.IsAbs(req.FilePath) {
342342
return fmt.Errorf("path must be an absolute path: %s", req.FilePath)
343343
}
@@ -364,7 +364,7 @@ func (s *backend) Write(ctx context.Context, req *filesystem.WriteRequest) error
364364
return nil
365365
}
366366

367-
func (s *backend) Edit(ctx context.Context, req *filesystem.EditRequest) error {
367+
func (s *Backend) Edit(ctx context.Context, req *filesystem.EditRequest) error {
368368
path := filepath.Clean(req.FilePath)
369369
if !filepath.IsAbs(path) {
370370
return fmt.Errorf("path must be an absolute path: %s", path)
@@ -403,7 +403,7 @@ func (s *backend) Edit(ctx context.Context, req *filesystem.EditRequest) error {
403403
return os.WriteFile(path, []byte(newText), 0644)
404404
}
405405

406-
func (s *backend) ExecuteStreaming(ctx context.Context, input *filesystem.ExecuteRequest) (result *schema.StreamReader[*filesystem.ExecuteResponse], err error) {
406+
func (s *Backend) ExecuteStreaming(ctx context.Context, input *filesystem.ExecuteRequest) (result *schema.StreamReader[*filesystem.ExecuteResponse], err error) {
407407
if input.Command == "" {
408408
return nil, fmt.Errorf("command is required")
409409
}

adk/backend/local/local_test.go

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"context"
2121
"fmt"
2222
"os"
23-
"os/exec"
2423
"path/filepath"
2524
"strings"
2625
"testing"
@@ -465,7 +464,7 @@ func TestExecuteStreaming(t *testing.T) {
465464

466465
t.Run("ExecuteStreaming with echo", func(t *testing.T) {
467466
req := &filesystem.ExecuteRequest{Command: "echo line1 && echo line2 && echo line3"}
468-
sr, err := s.(*backend).ExecuteStreaming(ctx, req)
467+
sr, err := s.ExecuteStreaming(ctx, req)
469468
assert.NoError(t, err)
470469

471470
var outputs []string
@@ -487,7 +486,7 @@ func TestExecuteStreaming(t *testing.T) {
487486

488487
t.Run("ExecuteStreaming with ping", func(t *testing.T) {
489488
req := &filesystem.ExecuteRequest{Command: "ping -c 3 127.0.0.1"}
490-
sr, err := s.(*backend).ExecuteStreaming(ctx, req)
489+
sr, err := s.ExecuteStreaming(ctx, req)
491490
assert.NoError(t, err)
492491

493492
var lineCount int
@@ -506,7 +505,7 @@ func TestExecuteStreaming(t *testing.T) {
506505

507506
t.Run("ExecuteStreaming with seq command", func(t *testing.T) {
508507
req := &filesystem.ExecuteRequest{Command: "seq 1 5"}
509-
sr, err := s.(*backend).ExecuteStreaming(ctx, req)
508+
sr, err := s.ExecuteStreaming(ctx, req)
510509
assert.NoError(t, err)
511510

512511
var numbers []string
@@ -530,7 +529,7 @@ func TestExecuteStreaming(t *testing.T) {
530529
defer cancel()
531530

532531
req := &filesystem.ExecuteRequest{Command: "seq 1 1000000"}
533-
sr, err := s.(*backend).ExecuteStreaming(cancelCtx, req)
532+
sr, err := s.ExecuteStreaming(cancelCtx, req)
534533
assert.NoError(t, err)
535534

536535
var lineCount int
@@ -552,7 +551,7 @@ func TestExecuteStreaming(t *testing.T) {
552551

553552
t.Run("ExecuteStreaming with command failure", func(t *testing.T) {
554553
req := &filesystem.ExecuteRequest{Command: "echo output && exit 1"}
555-
sr, err := s.(*backend).ExecuteStreaming(ctx, req)
554+
sr, err := s.ExecuteStreaming(ctx, req)
556555
assert.NoError(t, err)
557556

558557
var hasOutput bool
@@ -575,7 +574,7 @@ func TestExecuteStreaming(t *testing.T) {
575574

576575
t.Run("ExecuteStreaming with stderr output", func(t *testing.T) {
577576
req := &filesystem.ExecuteRequest{Command: "echo stdout && echo stderr >&2 && exit 1"}
578-
sr, err := s.(*backend).ExecuteStreaming(ctx, req)
577+
sr, err := s.ExecuteStreaming(ctx, req)
579578
assert.NoError(t, err)
580579

581580
var outputs []string
@@ -600,14 +599,14 @@ func TestExecuteStreaming(t *testing.T) {
600599

601600
t.Run("ExecuteStreaming with empty command", func(t *testing.T) {
602601
req := &filesystem.ExecuteRequest{Command: ""}
603-
_, err := s.(*backend).ExecuteStreaming(ctx, req)
602+
_, err := s.ExecuteStreaming(ctx, req)
604603
assert.Error(t, err)
605604
assert.Contains(t, err.Error(), "command is required")
606605
})
607606

608607
t.Run("ExecuteStreaming with large output", func(t *testing.T) {
609608
req := &filesystem.ExecuteRequest{Command: "seq 1 100"}
610-
sr, err := s.(*backend).ExecuteStreaming(ctx, req)
609+
sr, err := s.ExecuteStreaming(ctx, req)
611610
assert.NoError(t, err)
612611

613612
var lineCount int
@@ -626,7 +625,7 @@ func TestExecuteStreaming(t *testing.T) {
626625

627626
t.Run("ExecuteStreaming with normal completion", func(t *testing.T) {
628627
req := &filesystem.ExecuteRequest{Command: "echo test"}
629-
sr, err := s.(*backend).ExecuteStreaming(ctx, req)
628+
sr, err := s.ExecuteStreaming(ctx, req)
630629
assert.NoError(t, err)
631630

632631
var receivedOutput bool
@@ -645,7 +644,7 @@ func TestExecuteStreaming(t *testing.T) {
645644

646645
t.Run("ExecuteStreaming with invalid command", func(t *testing.T) {
647646
req := &filesystem.ExecuteRequest{Command: "/nonexistent/command"}
648-
sr, err := s.(*backend).ExecuteStreaming(ctx, req)
647+
sr, err := s.ExecuteStreaming(ctx, req)
649648
assert.NoError(t, err)
650649

651650
var lastErr error
@@ -663,10 +662,3 @@ func TestExecuteStreaming(t *testing.T) {
663662
assert.Error(t, lastErr, "should receive error for invalid command")
664663
})
665664
}
666-
667-
func TestExecute1(t *testing.T) {
668-
fs := strings.Fields("ls -al")
669-
bs, err := exec.Command(fs[0], fs[1:]...).Output()
670-
assert.NoError(t, err)
671-
fmt.Println(string(bs))
672-
}

0 commit comments

Comments
 (0)