Add sandbox filesystem methods (list_dir, mkdir, remove, upload, download, stream_upload, stream_download) and interactive PTY sessions (PtySession, AsyncPtySession) with reconnect support per FILE_TERMINAL.md spec. Refactor error handling into exceptions.py as shared handle_response(). Replace API-key-only proxy auth with unified _proxy_headers() supporting both API key and JWT. Fix stream_upload to build multipart manually instead of relying on httpx files= with generators. Switch Makefile SPEC_URL from main to dev branch. Regenerate models from updated OpenAPI spec (adds teams, channels, metrics, PTY endpoints). Add comprehensive unit and integration tests. Trim AGENTS.md to verified facts only.
81 lines
4.0 KiB
Markdown
81 lines
4.0 KiB
Markdown
# AGENTS.md
|
|
|
|
## What this repo is
|
|
|
|
Python SDK for **Wrenn** (microVM code execution platform). Communicates with the Control Plane via REST + WebSockets only — no gRPC. The `envd` and `HostAgentService` are internal to the Go backend and never reachable from this SDK.
|
|
|
|
## Build & dev commands
|
|
|
|
All commands go through `uv` and the `Makefile`. Never use raw `pip`, `venv`, or `python -m venv`.
|
|
|
|
```bash
|
|
make generate # Fetch openapi.yaml → src/wrenn/models/_generated.py
|
|
make lint # ruff check + ruff format --check on src/
|
|
make test # runs ONLY tests/test_client.py
|
|
make test-integration # runs ALL tests (unit + integration, needs live server)
|
|
make check # lint + test (test_client.py only)
|
|
```
|
|
|
|
To run all unit tests (not just test_client.py):
|
|
|
|
```bash
|
|
uv run pytest tests/test_client.py tests/test_sandbox_features.py tests/test_filesystem_pty.py -v
|
|
```
|
|
|
|
To run a single test:
|
|
|
|
```bash
|
|
uv run pytest tests/test_client.py::TestAuth::test_signup -v
|
|
```
|
|
|
|
## Code generation (CRITICAL)
|
|
|
|
Models in `src/wrenn/models/_generated.py` are generated by `datamodel-codegen` from `api/openapi.yaml`.
|
|
|
|
1. **Never edit `_generated.py`** — overwritten on next `make generate`.
|
|
2. All user-facing models must be re-exported in `src/wrenn/models/__init__.py` via `__all__`.
|
|
3. To extend a generated model with custom methods, subclass it (e.g. `Sandbox` in `sandbox.py` subclasses the generated `SandboxModel`).
|
|
|
|
## Dependency management
|
|
|
|
```bash
|
|
uv add <package> # runtime dep
|
|
uv add --dev <package> # dev dep
|
|
uv run <command> # run in managed .venv
|
|
```
|
|
|
|
## Implemented resource namespaces
|
|
|
|
Only these are currently implemented in `client.py`:
|
|
|
|
- **`client.auth`** — `signup`, `login`
|
|
- **`client.api_keys`** — `create`, `list`, `delete`
|
|
- **`client.sandboxes`** — `create`, `list`, `get`, `destroy`
|
|
- **`client.snapshots`** — `create`, `list`, `delete`
|
|
- **`client.hosts`** — `create`, `list`, `get`, `delete`, `regenerate_token`, `list_tags`, `add_tag`, `remove_tag`
|
|
|
|
Both sync and async variants exist for every resource.
|
|
|
|
## Architecture notes
|
|
|
|
- **Sync/async parity**: `WrennClient` + `AsyncWrennClient` in `client.py`, using `httpx.Client`/`httpx.AsyncClient`. Async methods on `Sandbox` are prefixed `async_` (e.g. `async_exec`, `async_upload`).
|
|
- **WebSocket library**: `httpx-ws` (not `websockets`). Used for `exec_stream`, `pty`, and `run_code`.
|
|
- **Sandbox proxy URL**: `get_url(port)` returns `ws://` or `wss://` scheme. The `http_client` property converts to `http://`/`https://` automatically.
|
|
- **`Sandbox`** (in `sandbox.py`) is the main developer-facing class — subclasses generated model, adds lifecycle methods (`exec`, `upload`, `download`, `list_dir`, `mkdir`, `remove`, `pty`, `run_code`, `wait_ready`, `pause`, `resume`, `destroy`, `ping`, `metrics`), context manager support, and proxy helpers.
|
|
- **Error handling**: `handle_response()` in `exceptions.py` maps server error `code` field to typed exceptions (not just HTTP status). All inherit from `WrennError` with `.code`, `.message`, `.status_code`.
|
|
|
|
## Testing
|
|
|
|
- **HTTP mocking**: `respx` library (not `responses` or `pytest-httpx`). Mock routes with `@respx.mock` decorator or `respx.mock` context manager.
|
|
- **Async tests**: use `@pytest.mark.asyncio` (backed by `pytest-asyncio`).
|
|
- **Integration tests**: in `test_integration.py`, require env vars `WRENN_API_KEY` or `WRENN_TOKEN` (plus optional `WRENN_BASE_URL`, `WRENN_TEST_EMAIL`, `WRENN_TEST_PASSWORD`). They are skipped via `@requires_auth` if credentials are absent.
|
|
- **Fixtures**: test fixtures create `WrennClient(api_key="wrn_test1234567890abcdef12345678")` with context manager cleanup.
|
|
|
|
## Coding conventions
|
|
|
|
- **Python 3.13+** with modern syntax (`|` unions, `list[str]` generics).
|
|
- **Strict typing** throughout. `pyright`/`mypy` available but not in CI.
|
|
- **`ruff`** is the sole linter and formatter. Do not use `black`, `isort`, or `flake8`.
|
|
- **Google-style docstrings** on all public APIs.
|
|
- **No comments** unless explicitly asked.
|