Skip to content

feat: add Tenki sandbox provider (@vibe-kit/tenki) - #256

Open
thomasacook wants to merge 6 commits into
superagent-ai:mainfrom
thomasacook:feat/tenki-sandbox-provider
Open

thomasacook wants to merge 6 commits into
superagent-ai:mainfrom
thomasacook:feat/tenki-sandbox-provider

Conversation

@thomasacook

Copy link
Copy Markdown

What

Adds @vibe-kit/tenki, a sandbox provider that runs coding agents inside Tenki disposable microVMs, alongside the existing providers (e2b, daytona, blaxel, modal, …).

Why

Tenki offers per-second microVMs with public preview URLs and pause/resume — a natural fit for VibeKit's "run an agent safely, watch it remotely" model.

How it works

  • Implements the standard SandboxProvider (create/resume) and SandboxInstance (commands.run, kill, pause, getHost) over @tenkicloud/sandbox, mirroring packages/daytona and packages/blaxel.
  • On Tenki's default base image, installs the requested agent's CLI at create() time (@anthropic-ai/claude-code, @openai/codex, @google/gemini-cli, opencode-ai, @vibe-kit/grok-cli). Optionally boots a pre-built Tenki registry image / snapshotId instead.
  • getHost(port) returns a public preview URL via exposePort.
  • Tenki's default image runs as a non-root user, so the provider creates VibeKit's working directory (/vibe0) with a sudo mkdir + chown fallback to keep it writable.

Reliability

  • create() is failure-atomic: if agent-CLI install or workdir setup fails, the sandbox is torn down rather than leaked.
  • Non-successful commands (e.g. signaled/timed-out with a 0 exit code) don't read as success; kill() surfaces teardown failures instead of swallowing them.
  • Optional maxDurationMs / idleTimeoutMinutes lifetime backstops.

Testing

  • Offline unit tests (mocked): config validation, create-failure cleanup, teardown-failure propagation, workspaceId passthrough.
  • Live integration tests (test/tenki-integration.test.ts, gated on TENKI_AUTH_TOKEN): create → run (piped shell + streaming) → exposePortkill; agent-CLI install + invoke; root-owned working-dir creation. All green.
  • Verified end-to-end through the VibeKit facade: new VibeKit().withSandbox(createTenkiProvider()) → Tenki VM → Claude Code (via a Claude Max OAuth token) held a real conversation and ran a command inside the VM.

Files

  • packages/tenki/* — new provider package (@tenkicloud/sandbox@^0.5.4)
  • docs/supported-sandboxes/tenki.mdx + docs/docs.json nav entry
  • test/tenki-integration.test.ts, test/tenki.test.ts, test/helpers/test-utils.ts

thomasacook added 6 commits July 22, 2026 16:42
Runs coding agents in Tenki disposable microVMs. Implements the SandboxProvider contract over @tenkicloud/sandbox with runtime agent-CLI install on the default image, preview URLs via exposePort, and failure-atomic create. Includes docs, offline lifecycle unit tests, and a live integration test. Mirrors packages/daytona and packages/blaxel.
…t-CLI e2e

- validateConfig(): reject out-of-range cpuCores/memoryMb at construction instead of failing minutes into provisioning

- create-failure cleanup now names the sandbox id, and warns to terminate manually if teardown itself also fails

- add live e2e test that installs @anthropic-ai/claude-code on the default image and invokes it; add unit tests for validation + cleanup-id
VibeKit defaults its working directory to the root-owned /vibe0, but Tenki's default image runs as a non-root user, so a plain mkdir fails with EACCES. create() now falls back to sudo mkdir + chown so the directory is owned by (and writable for) the sandbox user. Adds a live test asserting /vibe0 is created and writable.
generateCode() is deprecated in favor of executeCommand(); update the README and docs examples accordingly, and drop the stale pinned model (claude-sonnet-4-20250514) in favor of the 'sonnet' alias.
Addresses review feedback: if an executeCommand or getHost() call throws, the sandbox would otherwise leak until its timeout. Guard the example body with try/finally so kill() always runs.
Bumps the Tenki SDK to the latest release. 0.5.x infers workspace/project scope from the API key, so the previous projectId auto-resolution (via whoAmI) is removed; workspaceId stays as an optional passthrough for service-token callers. Rebuilt, type-checked, and re-verified against live sandboxes (7 unit + 3 integration tests green).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant