Commit Graph

43 Commits

Author SHA1 Message Date
devin-ai-integration[bot] f89f8c3f96 Add secrets management to JS and Python SDKs (#1728)
## Summary

Implements Secrets Management in the SDK per the [Secrets Vault SDK
proposal](https://app.notion.com/p/3bab8c29687380b6a8f3e2ecae3f1b50) and
the backend Secrets API. Linear:
[SDK-133](https://linear.app/e2b/issue/SDK-133/sdk-for-managing-secrets).
Docs: [e2b-dev/docs#379](https://github.com/e2b-dev/docs/pull/379).

Spec sync: bumps `spec/infra-ref` to `e19a12b8` (the commit that adds
the Secrets API), adds the `secrets` tag to the `redocly.yaml` filters,
and regenerates via `make codegen` (the regen also pulls in unrelated
upstream spec updates, e.g. the `Error.errorCode` field). The js-sdk
envd schema generation now bundles through a new `envd` redocly api that
filters out operations the upstream spec marks `x-internal: true`
(orchestrator control plane: `/init`, `/freeze`, `/unfreeze`,
`/collapse`, `/fsfreeze`, `/fsthaw`) plus their now-unused component
schemas, so they no longer appear in `src/envd/schema.gen.ts`.

The existing `Secret` class (previously only the `iamToken`/`iam_token`
workload-identity helper) becomes the secrets management surface,
equivalent across JS, sync Python (`Secret`), and async Python
(`AsyncSecret`):

```typescript
Secret.create(name, value, opts?): Promise<SecretInfo>   // POST /secrets
Secret.update(secret, value, opts?): Promise<SecretInfo> // POST /secrets/{secretID} (rotates to a new version)
Secret.getInfo(secret, opts?): Promise<SecretInfo>       // GET /secrets/{secretID}
Secret.list(opts?): SecretPaginator                      // GET /secrets (cursor-paginated)
Secret.exists(secret, opts?): Promise<boolean>           // 200 → true, 404 → false
Secret.destroy(secret, opts?): Promise<boolean>          // 204 → true, 404 → false
Secret.fill(secret): string                              // local marker formatting, no network call
```

Design decisions per the proposal:
- **Values are write-only**: `SecretInfo` carries only metadata
(`secretId`, `name`, `version`, `metadata`, `createdAt`, `updatedAt`);
no read surface or error message includes a value.
- `update`/`getInfo` throw `SecretNotFoundError` /
`SecretNotFoundException` on 404 (subclass of `NotFoundError` /
`NotFoundException`, so generic not-found catches keep working; general
failures throw the new `SecretError` / `SecretException`);
`exists`/`destroy` map 404 to `false` instead.
- `secret` selector accepts either the `sec_` ID or the canonical
lowercase name (backend resolves both).
- `fill` returns the `${e2b.secrets.name}` marker for use in a network
rule's request transform — always the current version, purely local. The
egress proxy replaces the marker with the secret's current value when it
forwards a matching request; unresolvable markers fail open (the request
is forwarded with the affected headers omitted).
- Version-management endpoints from the proposal are marked TBD and not
in the committed backend contract, so they are intentionally not
implemented.

Python moves `e2b/secret.py` to an `e2b/secret/` package (`base.py`
shares `fill`/`iam_token`, `secret_sync.py` / `secret_async.py` mirror
each other); `from e2b import Secret` is unchanged.

Usage:

```typescript
import { Sandbox, Secret } from 'e2b'

const info = await Secret.create('stripe_api_key', 'sk_live_...', { metadata: { env: 'prod' } })
await Secret.update('stripe_api_key', 'sk_live_new...') // rotate → version 2

// Inject into matching outbound requests via a network rule's transform:
const sandbox = await Sandbox.create({
  network: {
    allowOut: ({ rules }) => [...rules.keys()],
    denyOut: ({ allTraffic }) => [allTraffic],
    rules: {
      'api.stripe.com': [
        {
          transform: {
            headers: { Authorization: `Bearer ${Secret.fill('stripe_api_key')}` },
          },
        },
      ],
    },
  },
})

await Secret.destroy('stripe_api_key')
```

```python
from e2b import AsyncSecret

info = await AsyncSecret.create("stripe_api_key", "sk_live_...", metadata={"env": "prod"})
paginator = AsyncSecret.list(limit=100)
while paginator.has_next:
    secrets = await paginator.next_items()
print(AsyncSecret.fill("stripe_api_key"))  # ${e2b.secrets.stripe_api_key}
```

Tests: msw-mocked JS suite (`tests/secret/secret.test.ts`) and
monkeypatched sync/async Python suites covering CRUD, pagination, 404
semantics, and `fill`. `pnpm run format/lint/typecheck` pass; changeset
included (minor for `e2b` and `@e2b/python-sdk`).

Link to Devin session:
https://app.devin.ai/sessions/175095f75cbe42df8710718a1ff2a6a3
Requested by: @mishushakov

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: mish@e2b.dev <mish@e2b.dev>
2026-08-20 14:49:14 +00:00
Mish Ushakov 4fcf7cb150 feat: sync API specs from infra and belt with Copybara (#1564)
The specs in `spec/` were copied from their source repos by hand and had
drifted ~2,400 lines behind infra, so they are now imported with
Copybara (`copy.bara.sky`, run in a pinned Docker image by
`scripts/fetch-spec.sh`): `make codegen` re-fetches them at the commits
pinned in `spec/infra-ref` and `spec/belt-ref` before generating, and
the generated-files CI check fails if the tracked copies don't match the
pins. Regenerating from the current pins picks up the accumulated spec
changes in the generated JS/Python clients (renamed request schemas,
`SandboxNetworkConfig`, `SandboxIam` workload identity,
`FILE_TYPE_SYMLINK`, access-token auth deprecation, volume path-metadata
tweaks). The one handwritten SDK change follows from that: the public
`FileType` enums gain a `SYMLINK` member (JS and both Python surfaces)
so entries envd reports as symlinks show up in `files.list()` and
`getInfo()`/`get_info()` instead of being silently skipped as unknown
types. The custom `spec/remove_extra_tags.py` tag-filtering script is
replaced by Redocly CLI's `filter-in` decorator (`redocly.yaml`), which
produces identical generated JS output; a `filter-out` decorator
additionally drops any operation or component schema the upstream specs
mark `x-not-implemented: true` (currently the SOCKS5
`SandboxEgressProxyConfig`/`egressProxy` surface, which infra flagged as
spec-only); each SDK's bundle now goes to its own gitignored
`spec/openapi_generated.<api>.yml` instead of both pipelines overwriting
one shared file; Python client models now list fields in spec order
instead of alphabetical (mechanical reordering only — construct models
with keyword args). Spec fetches try whatever GitHub token is available
and fall back to the tracked copies with a warning (the public infra
specs also fetch anonymously); in CI a short-lived belt-scoped token is
minted from the org-wide Autofixer GitHub App (no new secrets), so fork
PRs simply fall back for the belt spec; the CI workflows also cache the
Copybara image alongside the codegen image, and the previously ignored
`CODEGEN_IMAGE` env is honored by the Makefile.

## Usage

```sh
# update the specs: bump a pin, then regenerate
echo <infra-commit-sha> > spec/infra-ref
make codegen

# fetch a single spec without regenerating
pnpm fetch:api-spec     # spec/openapi.yml from infra
pnpm fetch:envd-spec    # spec/envd/ from infra
pnpm fetch:volume-spec  # spec/openapi-volumecontent.yml from belt

# try the latest spec without touching the pin
E2B_INFRA_REF=main pnpm fetch:api-spec

# change which endpoint tags an SDK exposes
$EDITOR redocly.yaml && make codegen
```

```ts
// symlinks are now visible in the filesystem API (JS; same shape in Python)
const entries = await sandbox.files.list('/home/user')
const link = entries.find((e) => e.type === FileType.SYMLINK)
console.log(link?.symlinkTarget)
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 16:37:02 +02:00
Mish Ushakov 00253c39cc feat(python-sdk): migrate envd RPC to the official connectrpc client (#1558)
Replaces the vendored `e2b_connect` client and the custom Go
`protoc-gen-connect-python` plugin with the official Connect RPC client
for Python ([`connectrpc`](https://github.com/connectrpc/connect-py),
transport: `pyqwest`/Rust hyper), and switches the envd messages from
Google's `protobuf` runtime to Buf's
[`protobuf-py`](https://github.com/bufbuild/protobuf-py) (which
`connectrpc` already requires) — the SDK no longer depends on the
conflict-prone `protobuf` package at all, and the protoc binary drops
out of the codegen image. The wire format (same protos, same JSON) is
unchanged. Closing a command or watch stream early now sends
`RST_STREAM`, fixing abandoned streams leaking on the shared HTTP/2
connection, and peer resets surface as typed `ConnectError`s. The
plumbing mirrors the `e2b.api` layout: shared pieces (a JSON codec that
ignores unknown response fields, proxy narrowing, pool tuning) live in
`e2b/envd/client_shared.py`, the flavor-specific pyqwest transports
(wrapped in pyqwest's retry middleware, see the retry note below) and
`create_rpc_client` factories in `e2b/envd/client_sync/` and
`e2b/envd/client_async/`, and the default-header/logging interceptors in
`e2b/envd/interceptors.py`; `e2b/envd/rpc.py` maps `connectrpc` error
codes onto the existing SDK exceptions, so the public API is unchanged
(`sandbox.commands.run(...)`, `files.watch_dir(...)`, etc. work exactly
as before). The REST API and file upload/download keep using `httpx`.

The `proxy` connection option now applies to sandbox RPC calls too —
[pyqwest
0.7.0](https://github.com/curioswitch/pyqwest/releases/tag/v0.7.0) added
an httpx-style `proxy` parameter to its transports, so commands, PTY,
and filesystem watch traffic follow the same proxy as the REST API and
file transfers (an earlier revision of this PR could only fall back to
`http_proxy`/`https_proxy` env vars for RPC):

```python
sandbox = Sandbox.create(proxy="http://user:pass@localhost:8030")
# REST *and* RPC (commands, PTY, watch) traffic goes through the proxy
result = sandbox.commands.run("echo through-the-proxy")
```

Notes:
- `e2b_connect` is no longer shipped in the wheel; code importing it
directly should switch to `connectrpc` (`ConnectError`, `Code`) — SDK
exception types are unchanged.
- The generated `e2b.envd.*.*_pb2` modules are replaced by `protobuf-py`
equivalents (`process_pb`, `filesystem_pb`) with a different message API
(`Oneof` objects, `has_field`); these are internal modules —
`e2b-code-interpreter` and `e2b-desktop` were verified not to import
them.
- RPC transports are cached per proxy URL. `httpx.URL` and `httpx.Proxy`
proxies keep working for RPC calls when they reduce to a proxy URL
(`httpx.Proxy` auth is folded back into the URL userinfo); `httpx.Proxy`
extras that pyqwest can't express — custom headers, an `ssl_context` —
raise `InvalidArgumentException` rather than being silently dropped.
- Plain (non-Connect-encoded) HTTP error responses — an edge proxy or
gateway answering for envd — keep the vendored client's status mapping
even when they carry a JSON body that isn't a valid Connect error (e.g.
a gateway's `{"code": 429}` raises `RateLimitException`, not a
misleading sandbox-timeout); only JSON bodies with a valid Connect
`code` string are left to connectrpc to parse. An envd response that
fails to decode surfaces as a `SandboxException` with a clear message —
the SDK's JSON codec raises a typed `ConnectError(INTERNAL)` at the
source (connectrpc re-raises codec-raised `ConnectError`s unchanged),
rather than the error being reconstructed from `__cause__` heuristics in
the exception mapper.
- pyqwest 0.7.0 explicit transports default to an **empty TLS root
store** (0.6.2 used reqwest's defaults), so the envd transports pass
`tls_include_system_certs=True`; the dependency floor is
`pyqwest>=0.7.0` accordingly.
- Connection retries (`E2B_CONNECTION_RETRIES`, default 3) use pyqwest's
transport-level retry middleware (`pyqwest.middleware.retry`), narrowed
to retry only the builtin `ConnectionError` — raised solely while
establishing the connection, before the request could have reached envd
— with exponential backoff. A retry can therefore never replay a
delivered request, for unary and streaming RPCs alike; the previous
stack's replay of unary calls whose connection dropped mid-request is
dropped deliberately, since it could re-execute a delivered call (e.g.
`SendInput`). Pinned by unit tests plus end-to-end tests driving the
generated stubs through the middleware
(`tests/test_envd_retry_transport.py`).
- For async streaming calls (`commands.run`/`connect`, PTY,
`watch_dir`), `request_timeout` bounds opening the stream — the wait
until envd confirms with a start event, matching the JS SDK's
`requestTimeoutMs` — raising `TimeoutException` and cancelling the
HTTP/2 stream when exceeded (pinned frame-level in
`tests/test_envd_stream_reset.py`). The running stream stays bounded by
the command/watch `timeout`. The sync SDK cannot interrupt its blocking
wait, so `request_timeout` is not applied to sync stream setup — both
setup and the running stream are bounded by `timeout` (unlimited when
`0`).
- The RPC logging interceptor was upstreamed to pyqwest as a logging
middleware
([curioswitch/pyqwest#192](https://github.com/curioswitch/pyqwest/pull/192));
the SDK keeps its own `LoggingInterceptor` until that merges and ships
in a release the SDK can depend on.
- `pyqwest` ships binary wheels for manylinux/musllinux (x86_64,
aarch64), macOS arm64 + x86_64 (Intel wheels landed in 0.7.0), Windows
x64, and PyPy.
- The `RST_STREAM`-on-early-close behavior is pinned by frame-level
regression tests (`tests/test_envd_stream_reset.py`): a plaintext HTTP/2
server records the frames the real generated clients (with the SDK's
codec and interceptors) send — early close via `disconnect()`, close
through the logging interceptor, and abandoning the stream must all send
`RST_STREAM(CANCEL)`; normal completion must send none (sync + async).
- `E2B_MAX_CONNECTIONS` no longer applies to sandbox RPC traffic:
reqwest's pool bounds only idle connections per host
(`E2B_KEEPALIVE_EXPIRY`, `E2B_MAX_KEEPALIVE_CONNECTIONS`), not the total
number of open connections. It still applies to the REST API and file
transfers.
- The sync sandbox modules build one RPC client each and share it across
threads — the connectrpc sync client is stateless per call over the
process-global transport (verified with a 16-thread frame-level test);
only the httpx envd API clients stay per-thread with their transports.
- Also fixes numeric env-var parsing (`E2B_KEEPALIVE_EXPIRY`,
`E2B_MAX_KEEPALIVE_CONNECTIONS`, `E2B_MAX_CONNECTIONS`,
`E2B_CONNECTION_RETRIES`): an empty-string value now falls back to the
default instead of raising `ValueError` at import time.
2026-07-24 05:41:04 -07:00
Mish Ushakov e873ee94b6 feat(sdk): add allowNetworkMounts option to filesystem watch (#1420)
Client-side counterpart to
[e2b-dev/infra#2982](https://github.com/e2b-dev/infra/pull/2982): adds
an `allowNetworkMounts`/`allow_network_mounts` option to filesystem
directory watching across the JS and Python (sync + async) SDKs, so
clients can explicitly opt into watching paths on network filesystem
mounts (NFS, CIFS, SMB, FUSE), which envd rejects by default. Events on
network mounts may be unreliable or not delivered at all, hence the
explicit opt-in.

This regenerates the filesystem proto code from the updated spec and
threads the flag through `watchDir`/`watch_dir` (streaming `WatchDir`
and polling `CreateWatcher`). The option requires envd 0.6.4 (shipped by
the infra PR); using it against an older sandbox throws a
`TemplateError`/`TemplateException`. Default behavior is unchanged.

Includes new watch tests for all three SDKs and a minor-bump changeset
for `e2b` and `@e2b/python-sdk`.

> Note: the new tests exercise the flag on a regular directory (a
network mount can't be set up from SDK tests) and require envd 0.6.4, so
this should land with/after the infra deploy. All pre-existing watch
tests pass; the new ones currently fail with the expected
`TemplateError` against the deployed envd.

### Usage

**JavaScript**
```ts
const handle = await sandbox.files.watchDir(
  '/mnt/nfs-share/my-dir',
  (event) => console.log(event.type, event.name),
  { allowNetworkMounts: true }
)
```

**Python (async)**
```python
handle = await sandbox.files.watch_dir(
    "/mnt/nfs-share/my-dir",
    on_event=lambda e: print(e.type, e.name),
    allow_network_mounts=True,
)
```

**Python (sync)**
```python
handle = sandbox.files.watch_dir("/mnt/nfs-share/my-dir", allow_network_mounts=True)
for e in handle.get_new_events():
    print(e.type, e.name)
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-15 15:34:02 +02:00
Mish Ushakov da85b1e33c feat(sdk): add includeEntry option to filesystem watch (#1385)
Client-side counterpart to
[e2b-dev/infra#2930](https://github.com/e2b-dev/infra/pull/2930): adds
an `includeEntry`/`include_entry` option to filesystem directory
watching across the JS and Python (sync + async) SDKs, so each
`FilesystemEvent` can carry the affected entry's `EntryInfo`
(best-effort — unset for remove/rename-away events where the path no
longer exists). This regenerates the filesystem proto code from the
updated spec, threads the flag through `watchDir`/`watch_dir` (streaming
`WatchDir` and polling `CreateWatcher`), maps the new `entry` field onto
the event, and extracts a shared entry-mapping helper reused by
`list`/`getInfo`/`rename`. The option degrades gracefully: older
sandboxes (< envd 0.6.2) ignore it and leave `entry` unset, so there's
no hard version gate. Includes new watch tests for all three SDKs and a
minor-bump changeset for `e2b` and `@e2b/python-sdk`.

> Note: the entry-info tests require envd 0.6.2 (shipped by the infra
PR), so this should land with/after that deploy.

### Usage

**JavaScript**
```ts
const handle = await sandbox.files.watchDir(
  'my-dir',
  (event) => {
    console.log(event.type, event.name, event.entry?.path, event.entry?.type)
  },
  { includeEntry: true }
)
```

**Python (async)**
```python
def on_event(e):
    print(e.type, e.name, e.entry.path if e.entry else None)

handle = await sandbox.files.watch_dir("my-dir", on_event=on_event, include_entry=True)
```

**Python (sync)**
```python
handle = sandbox.files.watch_dir("my-dir", include_entry=True)
for e in handle.get_new_events():
    print(e.type, e.name, e.entry.path if e.entry else None)
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 19:02:09 +02:00
Mish Ushakov 961ffbae84 feat(sdks): expose user-defined file metadata on sandbox.files (#1383)
Adds a `metadata` option to file uploads and surfaces persisted metadata
on every `EntryInfo` / `WriteInfo` returned by `getInfo`, `list`,
`rename`, and write responses, across the JS and Python (sync + async)
SDKs.

Metadata is sent as `X-Metadata-<key>: <value>` request headers and
persisted by envd as `user.e2b.*` extended attributes; the same map is
applied to every file in a multi-file upload. Keys and values must be
printable US-ASCII and keys are lowercased by the sandbox, so they may
differ in case when read back. Requires **envd 0.6.2 or later**.

This syncs the envd OpenAPI spec and filesystem proto with
[infra#2732](https://github.com/e2b-dev/infra/pull/2732) and regenerates
the JS/Python clients.

## Usage

**JavaScript / TypeScript**
```ts
// Single file
const info = await sandbox.files.write('report.txt', 'hello', {
  metadata: { author: 'mish', purpose: 'demo' },
})
console.log(info.metadata) // { author: 'mish', purpose: 'demo' }

// Multiple files (same metadata applied to each)
await sandbox.files.writeFiles(
  [
    { path: 'a.txt', data: 'A' },
    { path: 'b.txt', data: 'B' },
  ],
  { metadata: { source: 'import' } }
)

// Read it back
const stat = await sandbox.files.getInfo('report.txt')
console.log(stat.metadata) // { author: 'mish', purpose: 'demo' }
```

**Python**
```python
# Single file
info = sandbox.files.write("report.txt", "hello", metadata={"author": "mish"})
print(info.metadata)  # {"author": "mish"}

# Multiple files (same metadata applied to each)
sandbox.files.write_files(
    [
        WriteEntry(path="a.txt", data="A"),
        WriteEntry(path="b.txt", data="B"),
    ],
    metadata={"source": "import"},
)

# Read it back
stat = sandbox.files.get_info("report.txt")
print(stat.metadata)  # {"author": "mish"}
```

The async Python API is identical with `await`.

## Tests

Integration tests cover the round-trip across `write` / `getInfo` /
`list` / `rename`, octet-stream uploads, multi-file uploads,
overwrite-clears-stale-metadata, and metadata written directly as
`user.e2b.*` xattrs via `sandbox.commands.run` surfacing in `getInfo`.
They require a sandbox running envd 0.6.2+.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 16:05:34 +00:00
Matt Brockman 87ceec29d9 feat: enable piping on the e2b cli (#1127)
Adds stdin piping support to `e2b sandbox exec`, so users can do:

  ```bash
  echo "data" | e2b sandbox exec <id> -- cat
cat file.bin | e2b sandbox exec <id> -- python3 -c 'import sys;
print(len(sys.stdin.buffer.read()))'
```

  Included:
  - JS SDK updates:
      - closeStdin()
      - supportsStdinClose
  - CLI updates:
      - detects piped stdin
      - streams stdin in 64 KiB chunks
      - closes remote stdin on EOF
  - graceful fallback for older sandbox versions (requires `envd` >= 0.5.2, warn + ignore piped input)


  ### Example Usage

  #### non-piped exec still works
```
  e2b sandbox exec <sandbox_id> -- 'echo backend-non-pipe'
```
  #### piped stdin path (supported envd) should deliver bytes
```
  echo "hello" | e2b sandbox exec <sandbox_id> -- 'wc -c'   # expect 6
printf '\x00\x01\x02\xff' | $e2b sandbox exec <sandbox_id> -- 'wc -c' #
expect 4
```
  #### optional: legacy template behavior should warn + ignore piped stdin
```
echo "hello" | e2b sandbox exec <legacy_sandbox_id> -- 'wc -c' # expect
0 + "Ignoring piped stdin."
```
2026-02-11 16:18:28 -08:00
Jakub Dobry de771ea3eb feat: keep user and workdir from the template in the sandbox (#944) 2025-10-15 00:23:01 -07:00
Jakub Novák e142c23c31 Set stdin to /dev/null by default (#919)
Disable stdin (setting it to `/dev/null` for `command.run()`, but enable
to setting it to pipe, which you can send the input via
`command.sendStdin()`
This fixes issues with tools checking for stdin and then hanging
indefinitely

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Disables stdin by default and introduces a new `StartRequest.stdin`
flag to opt-in to stdin piping, updating JS/Python SDKs, version gating,
and tests.
> 
> - **Spec/Protobuf**:
> - Add `optional bool stdin` to `process.StartRequest` in
`spec/envd/process/process.proto` and regenerate JS/Python protos.
> - **JS SDK**:
> - Add `ENVD_COMMANDS_STDIN = '0.3.0'` and version check; error if
`stdin === false` on older envd.
> - Extend `CommandStartOpts` with `stdin` (default `false`); pass
`stdin` to `rpc.start`.
> - **Python SDK**:
> - Add `ENVD_COMMANDS_STDIN = Version("0.3.0")` and version check
mirroring JS.
> - Extend async/sync `commands.run()` with `stdin` (default `False`);
pass to `StartRequest`.
>   - Update generated `process_pb2`/`.pyi` with `StartRequest.stdin`.
> - **Tests**:
> - Update send-stdin tests to run commands with `stdin:
true`/`stdin=True`.
> - **Changeset**:
>   - Minor bump for `@e2b/python-sdk` and `e2b`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
458a15187e6eadccd43540e6b8972c4d45e1bb78. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
2025-09-29 05:34:16 -07:00
Mish Ushakov edeafb1cdd Adds files.getInfo / files.get_info methods to retrieve information about directory/files (#724)
**Changelog**

- Adds `files.getInfo`, `files.get_info` methods to the SDKs.
- Adds tests for the new methods
- Adds documentation for the above.

**Examples**

JavaScript

```js
import { Sandbox } from '@e2b/code-interpreter'

const sandbox = await Sandbox.create()

// Create a new file
await sandbox.files.write('test_file.txt', 'Hello, world!')

// Get information about the file
const info = await sandbox.files.getInfo('test_file.txt')

console.log(info)
// {
//   name: 'test_file.txt',
//   type: 'file',
//   path: '/home/user/test_file.txt'
// }
```

Python

```py
from e2b_code_interpreter import Sandbox

sandbox = Sandbox()

# Create a new file
sandbox.files.write('test_file', 'Hello, world!')

# Get information about the file
info = sandbox.files.get_info('test_file')

print(info)
# EntryInfo(name='test_file.txt', type=<FileType.FILE: 'file'>, path='/home/user/test_file.txt')
```

---------

Co-authored-by: Jakub Novak <jakub@e2b.dev>
2025-07-29 03:39:42 -07:00
Jiri Sveceny 2def1305f3 Flag for securing envd access with auth token (#688)
Waiting until secure flag will be available in production cluster.

---------

Co-authored-by: Jakub Novák <jakub@e2b.dev>
2025-05-14 15:15:18 +00:00
0div a5b08de85f Add optional depth parameter to SDK file listing methods. (#649)
# Description

Do not merge before https://github.com/e2b-dev/infra/pull/524 is merged
and deployed.

The DX would look like this:
```js
const files = await sandbox.files.list(dirName, { depth: 3 })
```
- [x] update `envd` pb spec 
- [x] generate for `js-sdk`
- [x] update `js-sdk` `file.list` method to include optional depth param
- [x] update `js-sdk` tests
- [x] generate for `python-sdk`
- [x] update `python-sdk` `file.list` method to include optional depth
param
  - [x] sync
  - [x] async
- [x] update `python-sdk` tests
  - [x] sync
  - [x] async

---------

Co-authored-by: Mish <10400064+mishushakov@users.noreply.github.com>
2025-05-05 09:17:08 -07:00
0div e0c1bc752d Make codegen robust and deterministic for js and python SDKs (#664)
# Description 

This PR allows to codegen without worrying about your environment and
dependencies for consistent outcomes in what code is generated from
openapi and envd protobuf spec. Will generate files for `js-sdk` and
`python-sdk`

- [x] create Docker image with all the pinned deps needed to codegen
- [x] create codegen script using this container with mapped volumes
- [x] adapt Makefiles to this new approach
- [x] adapt where we install the connect-python protobuf binary for this
to work

# Test

```sh
make codegen # this command is similar to `make generate` but w/o the hassle

Generating SDK code from openapi and envd spec
cd packages/js-sdk && pnpm generate

> e2b@1.2.1 generate /workspace/packages/js-sdk
> python ./../../spec/remove_extra_tags.py sandboxes templates && openapi-typescript ../../spec/openapi_generated.yml -x api_key --arr
ay-length --alphabetize --output src/api/schema.gen.ts

 openapi-typescript 7.6.1
🚀 ../../spec/openapi_generated.yml → src/api/schema.gen.ts [44.2ms]
cd packages/js-sdk && pnpm generate-envd-api

> e2b@1.2.1 generate-envd-api /workspace/packages/js-sdk
> openapi-typescript ../../spec/envd/envd.yaml -x api_key --array-length --alphabetize --output src/envd/schema.gen.ts

 openapi-typescript 7.6.1
🚀 ../../spec/envd/envd.yaml → src/envd/schema.gen.ts [22.7ms]

[...]

cd packages/python-sdk && make generate-api

All done!  🍰 
```

---------

Co-authored-by: Jiri Sveceny <jiri.sveceny@icloud.com>
2025-04-07 17:00:31 +02:00
Jakub Dobrý 25c4539de6 Add watch dir recursive option (missing python client regeneration) 2025-01-28 11:25:42 -08:00
Jakub Novak 23ea4adfb1 Rename rpc methods for watcher 2024-10-14 19:51:05 -07:00
Jakub Novak bc42ba1e66 Refactor watch dir 2024-10-14 13:01:59 -07:00
Jakub Novak c5aa13ea86 Fix command for generating from rpc spec 2024-10-14 11:29:20 -07:00
Jakub Novak 81db2b1466 Add sync watch handler 2024-10-11 11:54:00 +02:00
Tomas Valenta b1c3e01c96 Split buf generation 2024-08-20 14:29:57 -07:00
Jakub Novak 2357fa3da7 Add possibility to add env vars on sandbox create 2024-08-14 11:08:25 +02:00
Jakub Novak e882d152bc Improve spec 2024-08-06 17:54:24 +02:00
Jakub Novak 0976c10a21 Remove file info from remove method 2024-08-06 15:47:03 +02:00
Jakub Novak 08fc1e4c8a Get paths for filesystem operations from envd 2024-08-06 14:48:48 +02:00
Tomas Valenta 6291c13adb Update generated clients; Ensure script cleanup 2024-06-28 16:13:54 -07:00
Tomas Valenta 6b32979f0f Fix python request timeout error; Change auth 2024-06-28 15:01:48 -07:00
Tomas Valenta 955876ef29 Fix openapi specs 2024-06-24 21:59:12 -07:00
Tomas Valenta 206d6744f0 Fix testing config; [WIP] Add tests; Fix python debug opt; Fix enum mapping 2024-06-24 20:51:47 -07:00
Tomas Valenta d8251e79c7 Client keepalive 2024-06-17 17:47:39 +02:00
Tomas Valenta 8f1839c710 Regenerate envd rpc clients 2024-06-16 21:24:44 +02:00
Tomas Valenta af449d7f5d Fix watch init error 2024-06-13 17:17:43 +02:00
Tomas Valenta 229c13524a Update scripts; Fix dir watch; Improve naming 2024-06-13 15:08:54 +02:00
Tomas Valenta b3617d99d9 [WIP] Fix bug and add proper errors 2024-06-11 13:11:36 +02:00
Tomas Valenta c18ada0b9d Python file handling 2024-06-08 23:22:19 +02:00
Tomas Valenta ef19d8f822 Regenrate RPC; Fix namespacing 2024-06-07 21:35:34 +02:00
Tomas Valenta b04342cbff Fix input stream; [WIP] Python SDK 2024-06-04 00:50:23 +02:00
Tomas Valenta ecf318a3ed Update spec and JS 2024-06-03 13:42:00 +02:00
Tomas Valenta b022dcfb80 [WIP] Upload and download handling 2024-06-02 23:06:37 +02:00
Tomas Valenta 9b83de35f2 Remove old deps; [WIP] JS SDK file handling 2024-06-02 14:28:25 +02:00
Tomas Valenta 1a6d34ea11 Improve types 2024-06-02 03:00:22 +02:00
Tomas Valenta 69744145fd Export types in TS SDK; [WIP] Python SDK process handling 2024-06-01 23:35:31 +02:00
Tomas Valenta 5bfcc9a20e Imrpove connection config; [WIP] Rework Python SDK 2024-06-01 21:07:13 +02:00
Tomas Valenta 068ff5613f Regenerate APIs 2024-05-31 06:40:42 +02:00
Tomas Valenta 3b4c915a48 Generate clients 2024-05-17 02:05:12 -07:00