[PR #258] [CLOSED] fix(api): support official E2B SDK volume mounts #299

Closed
opened 2026-10-29 14:21:58 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/kvcache-ai/AgentENV/pull/258
Author: @yingdi-shan
Created: 9/7/2026
Status: ❌ Closed

Base: main ← Head: fix/e2b-volume-compat


📝 Commits (2)

  • 0bccee8 fix(api): support E2B SDK volume mounts
  • fc57306 fix(api): preserve legacy volume mount requests

📊 Changes

10 files changed (+464 additions, -65 deletions)

View changed files

📝 crates/aenv/src/client/sandboxes.rs (+33 -6)
📝 docs/src/concepts/volumes.md (+15 -3)
📝 scripts/tests/e2e/e2b_ts_sdk_compat.ts (+43 -3)
📝 scripts/tests/e2e/suites/09_e2b_compat.sh (+5 -4)
📝 scripts/tests/e2e/suites/15_volume.sh (+2 -1)
📝 scripts/tests/e2e/suites/16_volume_randomized.sh (+3 -2)
📝 src/api/generated/src/models.rs (+217 -28)
📝 src/api/impls/sandbox.rs (+96 -5)
📝 src/api/openapi.yml (+30 -3)
📝 src/api/proxy.rs (+20 -10)

📄 Description

What

  • use the official E2B SandboxVolumeMount[] wire representation for responses and new clients while accepting legacy map requests
  • translate both request forms into AgentENV's internal path-to-volume map and reject duplicate array paths
  • extend the TypeScript SDK E2E test with volume create, inspect, connect, bounded list, mount, and guest write/read coverage using e2b@2.38.0
  • update the bundled CLI client, native volume E2E suites, and volume documentation for the array representation

Why

The official TypeScript SDK serializes volumeMounts as an array of {name, path} objects. AgentENV expected a map, so otherwise valid SDK sandbox creation failed with HTTP 422 after volume control-plane calls succeeded.

Closes #257

Scope and non-goals

This PR fixes SDK-managed volume mounting and documents the supported boundary. It does not add E2B's standalone /volumecontent data plane, so AgentENV does not return a volume token or domain. In particular, it does not return an empty, placeholder, or API-key-derived token. Volume contents remain accessible through a sandbox mount.

Volume.list() sends no pagination parameters and does not consume X-Next-Token. AgentENV intentionally keeps its existing bounded default page of 100 volumes instead of returning the full catalog; the SDK therefore sees the first page only.

Design and behavior changes

The OpenAPI response schema uses an array of SandboxVolumeMount objects. Request models use an untagged oneOf that accepts either that array or the legacy path-to-volume map. API handlers convert both forms to the existing internal mount map before volume reservation and convert stored maps back to deterministically sorted arrays in responses. Duplicate array paths are rejected with HTTP 400 before any volume is reserved.

The E2E test uses the same SDK path as applications: Volume.create, Volume.getInfo, Volume.connect, Volume.list, and Sandbox.create with the connected volume. It writes and reads a marker through the guest mount to verify the mount is usable.

Compatibility and operations

  • Public API or generated protocol: volumeMounts requests accept both the AgentENV map and official E2B array representations. Responses and the bundled client use the E2B array. Generated server models were regenerated.
  • Configuration or defaults: no change; volume listing without parameters remains bounded at 100 records.
  • Snapshot manifest, artifact layout, or storage format: no change; internal mount maps and snapshot data are unchanged.
  • Upgrade and rollback: existing map callers continue to work; new callers should use {name, path}[]. Rolling back requires new clients to restore the map payload.
  • Host requirements, permissions, ports, or dependencies: no runtime change. The E2E suite pins e2b@2.38.0 as a test-only dependency.

Validation

  • make fmt
  • make clippy
  • make test-unit
  • Relevant Rust integration tests
  • Generated clients/server regenerated with the documented make target
  • Documentation updated
  • Benchmarks or performance comparison completed

Commands and results:

make agentenv-server
cargo test -p agentenv --lib volume_mount
cargo test -p aenv
make fmt
make clippy
make test-unit
bash -n scripts/tests/e2e/suites/09_e2b_compat.sh scripts/tests/e2e/suites/15_volume.sh scripts/tests/e2e/suites/16_volume_randomized.sh
shellcheck scripts/tests/e2e/suites/09_e2b_compat.sh scripts/tests/e2e/suites/15_volume.sh scripts/tests/e2e/suites/16_volume_randomized.sh
(cd scripts/tests/e2e && npm install --no-save --package-lock=false e2b@2.38.0 typescript)
(cd scripts/tests/e2e && ./node_modules/.bin/tsc --noEmit)
make test-e2e SUITE_FILTER='09_e2b_compat.sh' AENV_PORT=18158 AENV_HOME_PATH=/tmp/aenv-issue257-compat-e2e/sdk-home AENV_RUNTIME_PATH=/tmp/aenv-issue257-compat-e2e/sdk-run AENV_DEPS_PATH=/var/lib/aenv/deps E2B_COMPAT_TS_SDK_VERSION=2.38.0
make test-e2e SUITE_FILTER='15_volume.sh' AENV_PORT=18159 AENV_HOME_PATH=/tmp/aenv-issue257-compat-e2e/legacy-home AENV_RUNTIME_PATH=/tmp/aenv-issue257-compat-e2e/legacy-run AENV_DEPS_PATH=/var/lib/aenv/deps

All listed commands passed. The SDK E2E suite passed all 8 checks, and the legacy-map volume lifecycle suite passed all 39 checks while validating array responses. An initial SDK E2E retry timed out during base-template setup after repeated GHCR EOFs; the same command passed once the registry recovered.

Skipped checks and reasons:

  • make -C services test: no services/ changes.
  • dedicated Rust integration targets: the focused official-SDK VM E2E directly exercises the changed API and mount path.
  • benchmarks: no performance-sensitive implementation change.

Risks and reviewer notes

The request compatibility model is intentionally limited to the two documented representations. Responses always use the E2B array, and the core volume reservation, snapshot, and storage paths remain unchanged behind the API conversion.

E2B's volume token is used only by its separate volume-content client as a Bearer token for /volumecontent/{volumeID} requests. Sandbox mount serialization uses the volume name and does not consume that token, which is why mounted access is supported without inventing data-plane credentials.

Checklist

  • The PR contains one coherent change and no unrelated formatting or refactoring.
  • New behavior is covered by tests, or I explained why testing is impractical.
  • Logs and examples contain no credentials, tokens, or private registry information.
  • I did not manually edit generated code without updating its source and regenerating it.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/kvcache-ai/AgentENV/pull/258 **Author:** [@yingdi-shan](https://github.com/yingdi-shan) **Created:** 9/7/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/e2b-volume-compat` --- ### 📝 Commits (2) - [`0bccee8`](https://github.com/kvcache-ai/AgentENV/commit/0bccee8d58e9b8ed3c6f565e98c5f2db4667d1dd) fix(api): support E2B SDK volume mounts - [`fc57306`](https://github.com/kvcache-ai/AgentENV/commit/fc57306588d68a8a273e8eda51f36bec51cd5b3e) fix(api): preserve legacy volume mount requests ### 📊 Changes **10 files changed** (+464 additions, -65 deletions) <details> <summary>View changed files</summary> 📝 `crates/aenv/src/client/sandboxes.rs` (+33 -6) 📝 `docs/src/concepts/volumes.md` (+15 -3) 📝 `scripts/tests/e2e/e2b_ts_sdk_compat.ts` (+43 -3) 📝 `scripts/tests/e2e/suites/09_e2b_compat.sh` (+5 -4) 📝 `scripts/tests/e2e/suites/15_volume.sh` (+2 -1) 📝 `scripts/tests/e2e/suites/16_volume_randomized.sh` (+3 -2) 📝 `src/api/generated/src/models.rs` (+217 -28) 📝 `src/api/impls/sandbox.rs` (+96 -5) 📝 `src/api/openapi.yml` (+30 -3) 📝 `src/api/proxy.rs` (+20 -10) </details> ### 📄 Description ## What - use the official E2B `SandboxVolumeMount[]` wire representation for responses and new clients while accepting legacy map requests - translate both request forms into AgentENV's internal path-to-volume map and reject duplicate array paths - extend the TypeScript SDK E2E test with volume create, inspect, connect, bounded list, mount, and guest write/read coverage using `e2b@2.38.0` - update the bundled CLI client, native volume E2E suites, and volume documentation for the array representation ## Why The official TypeScript SDK serializes `volumeMounts` as an array of `{name, path}` objects. AgentENV expected a map, so otherwise valid SDK sandbox creation failed with HTTP 422 after volume control-plane calls succeeded. ## Related issue Closes #257 ## Scope and non-goals This PR fixes SDK-managed volume mounting and documents the supported boundary. It does not add E2B's standalone `/volumecontent` data plane, so AgentENV does not return a volume token or domain. In particular, it does not return an empty, placeholder, or API-key-derived token. Volume contents remain accessible through a sandbox mount. `Volume.list()` sends no pagination parameters and does not consume `X-Next-Token`. AgentENV intentionally keeps its existing bounded default page of 100 volumes instead of returning the full catalog; the SDK therefore sees the first page only. ## Design and behavior changes The OpenAPI response schema uses an array of `SandboxVolumeMount` objects. Request models use an untagged `oneOf` that accepts either that array or the legacy path-to-volume map. API handlers convert both forms to the existing internal mount map before volume reservation and convert stored maps back to deterministically sorted arrays in responses. Duplicate array paths are rejected with HTTP 400 before any volume is reserved. The E2E test uses the same SDK path as applications: `Volume.create`, `Volume.getInfo`, `Volume.connect`, `Volume.list`, and `Sandbox.create` with the connected volume. It writes and reads a marker through the guest mount to verify the mount is usable. ## Compatibility and operations - Public API or generated protocol: `volumeMounts` requests accept both the AgentENV map and official E2B array representations. Responses and the bundled client use the E2B array. Generated server models were regenerated. - Configuration or defaults: no change; volume listing without parameters remains bounded at 100 records. - Snapshot manifest, artifact layout, or storage format: no change; internal mount maps and snapshot data are unchanged. - Upgrade and rollback: existing map callers continue to work; new callers should use `{name, path}[]`. Rolling back requires new clients to restore the map payload. - Host requirements, permissions, ports, or dependencies: no runtime change. The E2E suite pins `e2b@2.38.0` as a test-only dependency. ## Validation - [x] `make fmt` - [x] `make clippy` - [x] `make test-unit` - [ ] Relevant Rust integration tests - [x] Generated clients/server regenerated with the documented `make` target - [x] Documentation updated - [ ] Benchmarks or performance comparison completed Commands and results: ```text make agentenv-server cargo test -p agentenv --lib volume_mount cargo test -p aenv make fmt make clippy make test-unit bash -n scripts/tests/e2e/suites/09_e2b_compat.sh scripts/tests/e2e/suites/15_volume.sh scripts/tests/e2e/suites/16_volume_randomized.sh shellcheck scripts/tests/e2e/suites/09_e2b_compat.sh scripts/tests/e2e/suites/15_volume.sh scripts/tests/e2e/suites/16_volume_randomized.sh (cd scripts/tests/e2e && npm install --no-save --package-lock=false e2b@2.38.0 typescript) (cd scripts/tests/e2e && ./node_modules/.bin/tsc --noEmit) make test-e2e SUITE_FILTER='09_e2b_compat.sh' AENV_PORT=18158 AENV_HOME_PATH=/tmp/aenv-issue257-compat-e2e/sdk-home AENV_RUNTIME_PATH=/tmp/aenv-issue257-compat-e2e/sdk-run AENV_DEPS_PATH=/var/lib/aenv/deps E2B_COMPAT_TS_SDK_VERSION=2.38.0 make test-e2e SUITE_FILTER='15_volume.sh' AENV_PORT=18159 AENV_HOME_PATH=/tmp/aenv-issue257-compat-e2e/legacy-home AENV_RUNTIME_PATH=/tmp/aenv-issue257-compat-e2e/legacy-run AENV_DEPS_PATH=/var/lib/aenv/deps ``` All listed commands passed. The SDK E2E suite passed all 8 checks, and the legacy-map volume lifecycle suite passed all 39 checks while validating array responses. An initial SDK E2E retry timed out during base-template setup after repeated GHCR EOFs; the same command passed once the registry recovered. Skipped checks and reasons: - `make -C services test`: no `services/` changes. - dedicated Rust integration targets: the focused official-SDK VM E2E directly exercises the changed API and mount path. - benchmarks: no performance-sensitive implementation change. ## Risks and reviewer notes The request compatibility model is intentionally limited to the two documented representations. Responses always use the E2B array, and the core volume reservation, snapshot, and storage paths remain unchanged behind the API conversion. E2B's volume token is used only by its separate volume-content client as a Bearer token for `/volumecontent/{volumeID}` requests. Sandbox mount serialization uses the volume name and does not consume that token, which is why mounted access is supported without inventing data-plane credentials. ## Checklist - [x] The PR contains one coherent change and no unrelated formatting or refactoring. - [x] New behavior is covered by tests, or I explained why testing is impractical. - [x] Logs and examples contain no credentials, tokens, or private registry information. - [x] I did not manually edit generated code without updating its source and regenerating it. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-29 14:21:58 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
kvcache-ai/AgentENV#299
No description provided.