Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 60 additions & 1 deletion e2b/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ Applied via `e2b.NewConnectionConfig(opts...)` or embedded in `Create/Connect` w
| `WithAPIURL(url string)` | **Highest priority**: directly overrides API base URL |
| `WithSandboxBaseURL(url string)` | **Highest priority**: directly overrides sandbox envd base URL |
| `WithRequestTimeout(d time.Duration)` | HTTP request timeout, defaults to 60s |
| `WithHTTPClient(client *http.Client)` | Custom HTTP client for API requests |

#### Priority

Expand Down Expand Up @@ -193,14 +194,72 @@ e2b.WithDomain("example.com"),

| Method | Description |
|------------------------------------------------------------------------------|-----------------------------------------------|
| `List(ctx) ([]SandboxInfo, error)` | List all running sandboxes |
| `List(ctx, opts ...ListSandboxOpts) (*ListResult, error)` | List sandboxes with pagination support |
| `GetInfo(ctx, sandboxID) (*SandboxInfo, error)` | Get sandbox details; 404 returns `not found` |
| `Kill(ctx, sandboxID) (bool, error)` | Destroy sandbox; returns `true` in Debug mode |
| `SetTimeout(ctx, sandboxID, timeout int32) error` | Update timeout |
| `CreateSandbox(ctx, opts CreateSandboxOpts) (*SandboxCreateResponse, error)` | Low-level create API |
| `ConnectSandbox(ctx, sandboxID, timeout int32) (*client.Sandbox, error)` | Low-level connect API |
| `Pause(ctx, sandboxID) (string, error)` | Pause sandbox |

### ListSandboxOpts

Options for paginated listing:

```go
type ListSandboxOpts struct {
// Metadata filters sandboxes by metadata key-value pairs.
// Keys and values will be URL encoded automatically.
Metadata map[string]string
// State filters sandboxes by one or more states (e.g., "running", "paused").
State []api.SandboxState
// NextToken is the cursor to start the list from (for pagination).
NextToken string
// Limit is the maximum number of items to return per page.
Limit int32
}
```

### ListResult

Result of a list operation with pagination support:

```go
type ListResult struct {
Sandboxes []SandboxInfo // List of sandboxes in this page
NextToken string // Token for fetching the next page (empty if no more pages)
}
```

### Pagination Example

```go
// Fetch all sandboxes with pagination
var allSandboxes []e2b.SandboxInfo
nextToken := ""
pageSize := int32(10)

for {
result, err := api.List(ctx, e2b.ListSandboxOpts{
Limit: pageSize,
NextToken: nextToken,
})
if err != nil {
log.Fatal(err)
}

allSandboxes = append(allSandboxes, result.Sandboxes...)

// Check if there are more pages
if result.NextToken == "" {
break
}
nextToken = result.NextToken
}

fmt.Printf("Total: %d sandboxes\n", len(allSandboxes))
```

---

## Command Execution (Commands)
Expand Down
61 changes: 60 additions & 1 deletion e2b/README_zh-CH.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ func main() {
| `WithAPIURL(url string)` | **最高优先级**:直接覆盖 API base URL,绕过 Protocol/Domain 拼装 |
| `WithSandboxBaseURL(url string)` | **最高优先级**:直接覆盖 sandbox envd base URL |
| `WithRequestTimeout(d time.Duration)` | HTTP 请求超时,默认 60s |
| `WithHTTPClient(client *http.Client)` | 自定义 HTTP 客户端用于 API 请求 |

#### 优先级

Expand Down Expand Up @@ -188,14 +189,72 @@ e2b.WithDomain("example.com"),

| 方法 | 说明 |
|------------------------------------------------------------------------------|-------------------------------------|
| `List(ctx) ([]SandboxInfo, error)` | 列出所有运行中的 sandbox |
| `List(ctx, opts ...ListSandboxOpts) (*ListResult, error)` | 列出 sandbox,支持分页查询 |
| `GetInfo(ctx, sandboxID) (*SandboxInfo, error)` | 获取 sandbox 详情,404 返回 `not found` 错误 |
| `Kill(ctx, sandboxID) (bool, error)` | 销毁 sandbox;`Debug` 模式下直接返回 `true` |
| `SetTimeout(ctx, sandboxID, timeout int32) error` | 修改超时时间 |
| `CreateSandbox(ctx, opts CreateSandboxOpts) (*SandboxCreateResponse, error)` | 底层创建接口 |
| `ConnectSandbox(ctx, sandboxID, timeout int32) (*client.Sandbox, error)` | 底层连接接口 |
| `Pause(ctx, sandboxID) (string, error)` | 暂停 sandbox |

### ListSandboxOpts

分页查询选项:

```go
type ListSandboxOpts struct {
// Metadata 通过元数据键值对过滤 sandbox。
// 键和值会自动进行 URL 编码。
Metadata map[string]string
// State 按一个或多个状态过滤 sandbox(如 "running", "paused")。
State []api.SandboxState
// NextToken 分页游标,用于从指定位置开始查询。
NextToken string
// Limit 每页返回的最大数量。
Limit int32
}
```

### ListResult

分页查询结果:

```go
type ListResult struct {
Sandboxes []SandboxInfo // 当前页的 sandbox 列表
NextToken string // 下一页的游标(为空表示没有更多页)
}
```

### 分页查询示例

```go
// 分页获取所有 sandbox
var allSandboxes []e2b.SandboxInfo
nextToken := ""
pageSize := int32(10)

for {
result, err := api.List(ctx, e2b.ListSandboxOpts{
Limit: pageSize,
NextToken: nextToken,
})
if err != nil {
log.Fatal(err)
}

allSandboxes = append(allSandboxes, result.Sandboxes...)

// 检查是否还有更多页
if result.NextToken == "" {
break
}
nextToken = result.NextToken
}

fmt.Printf("总计: %d 个 sandbox\n", len(allSandboxes))
```

---

## 命令执行(Commands)
Expand Down
31 changes: 23 additions & 8 deletions e2b/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ type ConnectionConfig struct {
RuntimePort int
// Headers contains additional headers to send with sandbox requests.
Headers map[string]string
// HTTPClient is a custom HTTP client to use for API requests.
// If nil, a default client with RequestTimeout will be created.
HTTPClient *http.Client

// apiClient is a lazily-initialized shared API client.
apiClient *api.APIClient
Expand Down Expand Up @@ -159,6 +162,13 @@ func WithSandboxBaseURL(sandboxBaseURL string) ConnectionConfigOption {
}
}

// WithHTTPClient sets a custom HTTP client for API requests.
func WithHTTPClient(httpClient *http.Client) ConnectionConfigOption {
return func(c *ConnectionConfig) {
c.HTTPClient = httpClient
}
}

// GetAPIURL returns the base API URL.
func (c *ConnectionConfig) GetAPIURL() string {
if c.APIURL != "" {
Expand Down Expand Up @@ -194,12 +204,13 @@ func (c *ConnectionConfig) getScheme() string {
// toEnvdConfig converts this ConnectionConfig into a runtime.Config for the envd client.
func (c *ConnectionConfig) toEnvdConfig(sandboxID string) *runtime.Config {
cfg := &runtime.Config{
Domain: c.Domain,
Scheme: c.Scheme,
RuntimePort: c.RuntimePort,
APIKey: c.APIKey,
RequestTimeout: c.RequestTimeout,
RuntimeToken: c.AccessToken,
Domain: c.Domain,
Scheme: c.Scheme,
RuntimePort: c.RuntimePort,
APIKey: c.APIKey,
RequestTimeout: c.RequestTimeout,
RuntimeToken: c.AccessToken,
CustomHTTPClient: c.HTTPClient,
}

// Pre-compute the full sandbox URL using the Protocol-aware logic so
Expand All @@ -224,8 +235,12 @@ func (c *ConnectionConfig) NewAPIClient() *api.APIClient {
cfg.Servers = api.ServerConfigurations{
{URL: c.GetAPIURL()},
}
cfg.HTTPClient = &http.Client{
Timeout: c.RequestTimeout,
if c.HTTPClient != nil {
cfg.HTTPClient = c.HTTPClient
} else {
cfg.HTTPClient = &http.Client{
Timeout: c.RequestTimeout,
}
}
if c.APIKey != "" {
cfg.DefaultHeader["X-API-Key"] = c.APIKey
Expand Down
68 changes: 57 additions & 11 deletions e2b/sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"

"github.com/openkruise/agents-api/e2b/api"
"github.com/openkruise/agents-api/runtime"
)

Expand All @@ -16,11 +17,16 @@ type sandboxOptions struct {
configOpts []ConnectionConfigOption

// Create-specific options
timeout int32
autoPause *bool
metadata map[string]string
envVars map[string]string
secure bool
timeout int32
autoPause *bool
autoResume *api.SandboxAutoResumeConfig
secure bool
allowInternetAccess *bool
network *api.SandboxNetworkConfig
metadata map[string]string
envVars map[string]string
mcp map[string]interface{}
volumeMounts []api.SandboxVolumeMount
}

// WithTimeout sets the sandbox timeout in seconds.
Expand Down Expand Up @@ -58,6 +64,41 @@ func WithSecure(secure bool) SandboxOption {
}
}

// WithAutoResume sets the auto-resume configuration for the sandbox.
func WithAutoResume(autoResume *api.SandboxAutoResumeConfig) SandboxOption {
return func(o *sandboxOptions) {
o.autoResume = autoResume
}
}

// WithAllowInternetAccess controls whether the sandbox can access the internet.
func WithAllowInternetAccess(allow bool) SandboxOption {
return func(o *sandboxOptions) {
o.allowInternetAccess = &allow
}
}

// WithNetwork sets the network configuration for the sandbox.
func WithNetwork(network *api.SandboxNetworkConfig) SandboxOption {
return func(o *sandboxOptions) {
o.network = network
}
}

// WithMcp sets the MCP configuration for the sandbox.
func WithMcp(mcp map[string]interface{}) SandboxOption {
return func(o *sandboxOptions) {
o.mcp = mcp
}
}

// WithVolumeMounts sets the volume mounts for the sandbox.
func WithVolumeMounts(volumeMounts []api.SandboxVolumeMount) SandboxOption {
return func(o *sandboxOptions) {
o.volumeMounts = volumeMounts
}
}

// WithConfig applies one or more ConnectionConfigOption to the sandbox.
func WithConfig(configOpts ...ConnectionConfigOption) SandboxOption {
return func(o *sandboxOptions) {
Expand Down Expand Up @@ -86,12 +127,17 @@ func Create(ctx context.Context, template string, opts ...SandboxOption) (*Sandb
}

createOpts := CreateSandboxOpts{
Template: template,
Timeout: options.timeout,
AutoPause: options.autoPause,
Metadata: options.metadata,
EnvVars: options.envVars,
Secure: options.secure,
Template: template,
Timeout: options.timeout,
AutoPause: options.autoPause,
AutoResume: options.autoResume,
Secure: options.secure,
AllowInternetAccess: options.allowInternetAccess,
Network: options.network,
Metadata: options.metadata,
EnvVars: options.envVars,
Mcp: options.mcp,
VolumeMounts: options.volumeMounts,
}
if createOpts.Timeout <= 0 {
createOpts.Timeout = int32(defaultSandboxTimeout)
Expand Down
Loading
Loading