Add Tenki Sandboxes provider#25
Open
francoluxor wants to merge 1 commit into
Open
Conversation
* Add Tenki Sandboxes provider Implement a SandboxProvider for Tenki (managed microVM sandboxes) as a thin adapter over the official tenki-sandbox async SDK (AsyncClient / AsyncSandbox), which speaks Tenki's Connect/gRPC control plane and data-plane gateway. - Lifecycle: create / get / list / destroy sessions - Command execution and stdout streaming over the data plane - File upload / download via the SDK fs API - Label-based reuse (labels map to Tenki session metadata) - Capabilities: persistent, snapshot, streaming, file_upload, interactive_shell Wire the provider into the registry, CLI, and auto-configuration (enabled when TENKI_API_KEY is set). Add unit tests using an injected fake async client plus a live integration test (skipped without TENKI_API_KEY), and register the tenki-sandbox optional dependency. * Address code review feedback on Tenki provider - Map SDK command timeouts to SandboxTimeoutError in _map_error (used by stream_execution); execute_command keeps returning a timed_out result - Evict cached handle before close() in destroy_sandbox so concurrent callers can't observe a terminating sandbox - Guard aclose() with the provider lock - Default unknown session states to ERROR instead of RUNNING - stream_execution: try/finally kills the remote process if the generator is abandoned, and routes close_stdin/wait/stdout errors through _map_error - Live integration test: create inside try, guard teardown, always aclose - Add stream cleanup and error-mapping unit tests * Honor TENKI_AUTH_TOKEN in provider auto-config and CLI status Auto-registration and the CLI providers command only checked TENKI_API_KEY, so a user with only TENKI_AUTH_TOKEN set (which TenkiProvider.__init__ accepts) saw the provider unregistered / reported as not configured. Check both. * Address second review pass on Tenki provider - _resolve/destroy_sandbox: track in-flight destroys via a _destroying set and read the cache under the lock, so a handle can't be returned or re-cached mid-termination - stream_execution: bound proc.wait() with asyncio.wait_for and raise SandboxTimeoutError on timeout; _map_error is now idempotent for library errors - aclose(): clear state under the lock, run client.close() outside it - create_sandbox: cpu_cores uses `is not None` so an explicit 0 is not dropped - Add tests for the destroy guard and the stream wait-timeout
francoluxor
marked this pull request as ready for review
July 20, 2026 16:47
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a Tenki Sandboxes provider (managed microVM sandboxes for agentic
workloads, https://tenki.cloud) implemented as a thin adapter over the official
tenki-sandboxasync SDK (AsyncClient/AsyncSandbox). Tenki's real APIis a Connect/gRPC control plane plus a data-plane gateway for command
execution — there is no plain REST surface — so the SDK handles the protocol,
data-plane priming, and auth.
Features
SandboxProviderlifecycle: create / get / list / destroysb.shell) and stdout streaming (sb.start) over the data planefsAPITENKI_API_KEYis set;Sandbox.configure(tenki_api_key=...)persistent,snapshot,streaming,file_upload,interactive_shellRequirements
TENKI_API_KEY(orTENKI_AUTH_TOKEN)TENKI_PROJECT_ID/TENKI_WORKSPACE_IDfor scoped listing,TENKI_API_ENDPOINTpip install "cased-sandboxes[tenki]"(pullstenki-sandbox)Test plan
ruffclean on changed filestests/test_tenki_provider.pydrive the provider via an injectedfake async client (create/get/list/exec/stream/destroy/files/timeout/auth)
RUNNING, confirmed via an independent raw Connect
GetSession), real shellcommands executed on an Ubuntu 24.04 guest (
echo,hostname,uname),then terminated (state flipped to
TERMINATED, no leaked session)