From 3ec1b7215e79290e71c1a568cced5faadfe4cda9 Mon Sep 17 00:00:00 2001 From: Nabhag Motivaras <65061890+Nabhag8848@users.noreply.github.com> Date: Thu, 5 Nov 2026 21:35:58 +0530 Subject: [PATCH 1/5] Rewrite website docs as user-facing SDK guides. Scope samples by language and provider, show concrete code under each heading, and keep failure examples on the Errors page. Co-authored-by: Cursor --- website/README.md | 18 +- website/content/docs/concepts.mdx | 409 ++++++++++++++++++++++-- website/content/docs/configuration.mdx | 369 ++++++++++++++++++++-- website/content/docs/create.mdx | 368 ++++++++++++++++++++-- website/content/docs/daytona.mdx | 132 ++++++-- website/content/docs/errors.mdx | 219 +++++++++++-- website/content/docs/examples.mdx | 415 ++++++++++++++++++++++--- website/content/docs/filesystem.mdx | 193 ++++++------ website/content/docs/index.mdx | 55 ++-- website/content/docs/lifecycle.mdx | 162 ++++++---- website/content/docs/modal.mdx | 154 +++++++-- website/content/docs/process.mdx | 338 ++++++++++---------- website/package-lock.json | 228 +------------- website/package.json | 3 +- website/scripts/publish-pages.mjs | 8 +- website/src/lib/providers.ts | 32 ++ website/src/lib/seo.ts | 62 ++++ website/src/lib/shared.ts | 13 +- website/src/routeTree.gen.ts | 21 -- website/src/routes/__root.tsx | 7 +- website/src/routes/docs/$.tsx | 50 +-- website/src/routes/index.tsx | 10 +- website/src/routes/og/docs/$.ts | 23 -- 23 files changed, 2417 insertions(+), 872 deletions(-) create mode 100644 website/src/lib/seo.ts delete mode 100644 website/src/routes/og/docs/$.ts diff --git a/website/README.md b/website/README.md index 5761abed..34ff5c1c 100644 --- a/website/README.md +++ b/website/README.md @@ -1,6 +1,6 @@ -# Sandbox Kit docs site +# Docs site -User guide for the Sandbox Kit SDK—a lightweight, provider-pluggable client for cloud sandboxes. Fumadocs + TanStack Start. Source pages: `content/docs`. +Fumadocs + TanStack Start site for the Sandbox Kit SDK user guide. Pages live in `content/docs`. ```sh npm install @@ -13,16 +13,6 @@ Open http://localhost:3000. npm run build:pages ``` -GitHub Actions publishes from `main` to https://sandbox-kit.github.io/kit/. Set Pages to deploy from GitHub Actions. +GitHub Actions deploys `main` to https://sandbox-kit.github.io/kit/. Set Pages to deploy from GitHub Actions. -## Structure - -| Section | Pages | -| ---------- | ------------------------------------------------------------------------- | -| Quickstart | `index` | -| Concepts | `concepts` | -| Providers | `daytona`, `modal` | -| Guides | `configuration`, `create`, `lifecycle`, `filesystem`, `process`, `errors` | -| Examples | `examples` | - -Language tabs (TypeScript / Go) persist in the browser. Behavior reference for the same API lives in the repository `docs/` directory. Runnable projects live in `examples/`. +Language and provider tabs persist in the browser. Runnable samples are linked from the Examples page into the repo `examples/` tree. diff --git a/website/content/docs/concepts.mdx b/website/content/docs/concepts.mdx index 85985927..5b198e5d 100644 --- a/website/content/docs/concepts.mdx +++ b/website/content/docs/concepts.mdx @@ -1,62 +1,411 @@ --- title: Concepts -description: Lightweight SDK model—client, handle, pluggable providers, capabilities, close. +description: Client, sandbox handle, providers, capabilities, and close. --- -Sandbox Kit is a lightweight SDK over provider native clients. Depend on `@sandbox-kit/sandbox` (or the Go `sandbox` module) plus a provider module. Swap the provider; keep the same client surface. +Sandbox Kit is an SDK. You construct a client with a provider and config; the client calls that provider for create, lifecycle, filesystem, and process work. Application code stays on the shared client surface. ## Client -Construct one client with a provider and config. Invalid config fails immediately. Credentials are not verified until the first provider request. +Credentials are checked on the first provider call, not at construction. Details: [Configuration](/docs/configuration). -| Language | Construct | -| ---------- | --------------------------------------------------- | -| TypeScript | `new Client({ provider, ... })` | -| Go | `sandbox.NewClient(provider, &sandbox.Config{...})` | + + -Shared config fields: `auth`, `scope`, `endpoint`, `region`, `timeout`. See [Configuration](/docs/configuration). + + +```ts +import { daytona } from "@sandbox-kit/daytona"; +import { Client } from "@sandbox-kit/sandbox"; + +await using client = new Client({ + provider: daytona(), + auth: { apiKey: { key: process.env.DAYTONA_API_KEY! } }, + region: process.env.DAYTONA_TARGET, + timeout: 120_000, // milliseconds +}); +``` + + + + + +```ts +import { modal } from "@sandbox-kit/modal"; +import { Client } from "@sandbox-kit/sandbox"; + +await using client = new Client({ + provider: modal(), + auth: { + tokenPair: { + id: process.env.MODAL_TOKEN_ID!, + secret: process.env.MODAL_TOKEN_SECRET!, + }, + }, + scope: { + appName: process.env.MODAL_APP_NAME!, + environment: "main", + }, + region: process.env.MODAL_REGION, + timeout: 120_000, // milliseconds +}); +``` + + + + + + + + +```go +import ( + "os" + "time" + + "github.com/sandbox-kit/kit/sdks/go/providers/daytona" + "github.com/sandbox-kit/kit/sdks/go/sandbox" +) + +client, err := sandbox.NewClient(daytona.New(), &sandbox.Config{ + Auth: &sandbox.AuthConfig{Credentials: &sandbox.APIKey{ + ApiKey: &sandbox.APIKeyCredentials{Key: os.Getenv("DAYTONA_API_KEY")}, + }}, + Region: sandbox.Value(os.Getenv("DAYTONA_TARGET")), + Timeout: sandbox.Duration(2 * time.Minute), +}) +if err != nil { + return err +} +``` + + + + + +```go +import ( + "os" + "time" + + "github.com/sandbox-kit/kit/sdks/go/providers/modal" + "github.com/sandbox-kit/kit/sdks/go/sandbox" +) + +client, err := sandbox.NewClient(modal.New(), &sandbox.Config{ + Auth: &sandbox.AuthConfig{Credentials: &sandbox.TokenPair{ + TokenPair: &sandbox.TokenPairCredentials{ + Id: os.Getenv("MODAL_TOKEN_ID"), + Secret: os.Getenv("MODAL_TOKEN_SECRET"), + }, + }}, + Scope: &sandbox.Scope{ + AppName: sandbox.Value(os.Getenv("MODAL_APP_NAME")), + Environment: sandbox.Value("main"), + }, + Region: sandbox.Value(os.Getenv("MODAL_REGION")), + Timeout: sandbox.Duration(2 * time.Minute), +}) +if err != nil { + return err +} +``` + + + + + ## Sandbox handle -`create` and the provider's open method (for example Daytona `get`, Modal `attach`) return a handle. Use that handle for lifecycle, filesystem, and process calls. +`create` and the provider's open-by-id method return a handle. Use that handle for lifecycle, filesystem, and process calls. + + + -| Language | Handle API | -| ---------- | --------------------------------------------------------------------------------- | -| TypeScript | `sandbox.id`, `sandbox.filesystem`, `sandbox.process`, lifecycle methods | -| Go | `instance.ID()`, `instance.Filesystem()`, `instance.Process()`, lifecycle methods | + + +```ts +const sandbox = await client.create({ + source: { image: { reference: "daytonaio/playground:latest" } }, +}); +console.log(sandbox.id); + +await sandbox.filesystem.writeFile("/tmp/note.txt", data); +const result = await sandbox.process.run({ argv: ["echo", "hi"] }); +console.log(result.exitCode); +console.log(new TextDecoder().decode(result.stdout)); +console.log(new TextDecoder().decode(result.stderr)); +``` + + + + + +```ts +const sandbox = await client.create({ + source: { image: { reference: "alpine:3.21" } }, +}); +console.log(sandbox.id); + +await sandbox.filesystem.writeFile("/tmp/note.txt", data); +const result = await sandbox.process.run({ argv: ["echo", "hi"] }); +console.log(result.exitCode); +console.log(new TextDecoder().decode(result.stdout)); +console.log(new TextDecoder().decode(result.stderr)); +``` + + + + + + + + +```go +instance, err := client.Create(ctx, &sandbox.CreateOptions{ + Source: &sandbox.SandboxSource{Kind: &sandbox.Image{ + Image: &sandbox.ImageSource{Reference: "daytonaio/playground:latest"}, + }}, +}) +if err != nil { + return err +} +fmt.Println(instance.ID()) + +err = instance.Filesystem().WriteFile(ctx, "/tmp/note.txt", data, nil) +result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ + Argv: []string{"echo", "hi"}, +}) +if err != nil { + return err +} +fmt.Println(result.GetExitCode()) +fmt.Println(string(result.GetStdout())) +fmt.Println(string(result.GetStderr())) +``` + + + + + +```go +instance, err := client.Create(ctx, &sandbox.CreateOptions{ + Source: &sandbox.SandboxSource{Kind: &sandbox.Image{ + Image: &sandbox.ImageSource{Reference: "alpine:3.21"}, + }}, +}) +if err != nil { + return err +} +fmt.Println(instance.ID()) + +err = instance.Filesystem().WriteFile(ctx, "/tmp/note.txt", data, nil) +result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ + Argv: []string{"echo", "hi"}, +}) +if err != nil { + return err +} +fmt.Println(result.GetExitCode()) +fmt.Println(string(result.GetStdout())) +fmt.Println(string(result.GetStderr())) +``` + + + + + ## Providers -Providers are pluggable. Each one is its own package that adapts a native SDK to the shared client. Depend only on the provider you need; add another module when you add a backend. +Each provider is its own package. Pass it into the client. Auth, create defaults, and which lifecycle calls exist depend on the provider; the client methods stay the same. + +The client invokes the provider's native SDK—it does not sit in front of a separate Kit service. + + + -| Provider | Open existing sandbox | Native SDK | -| ------------------------ | ------------------------- | -------------------- | -| [Daytona](/docs/daytona) | `get` (provider-verified) | Daytona SDK v0.225.0 | -| [Modal](/docs/modal) | `attach` (id only) | Modal SDK v0.11.1 | + -Apps construct `Client` / `NewClient` with the chosen provider. Provider modules stay outside the core SDK. +```ts +import { daytona } from "@sandbox-kit/daytona"; +import { Client } from "@sandbox-kit/sandbox"; + +await using client = new Client({ + provider: daytona(), + auth: { apiKey: { key: process.env.DAYTONA_API_KEY! } }, +}); +``` + +Setup: [Daytona](/docs/daytona). + + + + + +```ts +import { modal } from "@sandbox-kit/modal"; +import { Client } from "@sandbox-kit/sandbox"; + +await using client = new Client({ + provider: modal(), + auth: { + tokenPair: { + id: process.env.MODAL_TOKEN_ID!, + secret: process.env.MODAL_TOKEN_SECRET!, + }, + }, + scope: { appName: process.env.MODAL_APP_NAME!, environment: "main" }, +}); +``` + +Setup: [Modal](/docs/modal). + + + + + + + + +```go +import ( + "github.com/sandbox-kit/kit/sdks/go/providers/daytona" + "github.com/sandbox-kit/kit/sdks/go/sandbox" +) + +client, err := sandbox.NewClient(daytona.New(), &sandbox.Config{ + Auth: &sandbox.AuthConfig{Credentials: &sandbox.APIKey{ + ApiKey: &sandbox.APIKeyCredentials{Key: os.Getenv("DAYTONA_API_KEY")}, + }}, +}) +``` + +Setup: [Daytona](/docs/daytona). + + + + + +```go +import ( + "github.com/sandbox-kit/kit/sdks/go/providers/modal" + "github.com/sandbox-kit/kit/sdks/go/sandbox" +) + +client, err := sandbox.NewClient(modal.New(), &sandbox.Config{ + Auth: &sandbox.AuthConfig{Credentials: &sandbox.TokenPair{ + TokenPair: &sandbox.TokenPairCredentials{ + Id: os.Getenv("MODAL_TOKEN_ID"), + Secret: os.Getenv("MODAL_TOKEN_SECRET"), + }, + }}, + Scope: &sandbox.Scope{ + AppName: sandbox.Value(os.Getenv("MODAL_APP_NAME")), + Environment: sandbox.Value("main"), + }, +}) +``` + +Setup: [Modal](/docs/modal). + + + + + ## Capabilities -`supports` / `Supports` reports whether the provider implements an operation. An unsupported call fails in Kit before any provider request. Daytona can still reject a supported lifecycle call for a specific sandbox; that rejection returns as a provider error. +Kit rejects unsupported calls before talking to the provider. A provider can still refuse a supported call for a particular sandbox; that comes back as a provider error. + + + + +```ts +import { LifecycleCapability } from "@sandbox-kit/sandbox"; + +if (!sandbox.supports(LifecycleCapability.Stop)) { + throw new Error(`sandbox ${sandbox.id} cannot be stopped`); +} +``` + + + + +```go +import "github.com/sandbox-kit/kit/sdks/go/sandbox" + +if !instance.Supports(sandbox.LifecycleCapabilityStop) { + return fmt.Errorf("sandbox %s cannot be stopped", instance.ID()) +} +``` + + + ## Concurrency -Calls on one handle run one at a time (lifecycle, filesystem, and process). A second handle for the same sandbox id does not serialize with the first. Abort or deadline rejects the TypeScript `await` (and ends the Go wait), but the handle stays busy until that provider call settles. +Calls on one handle run one at a time. A second handle for the same sandbox id does not share that queue. + + + + +```ts +const ac = new AbortController(); +const pending = sandbox.process.run({ + argv: ["sleep", "30"], + signal: ac.signal, +}); +ac.abort(); // rejects the await; handle stays busy until the provider call settles +await pending.catch(() => {}); +``` + + + + +```go +ctx, cancel := context.WithCancel(ctx) +defer cancel() + +go func() { + time.Sleep(10 * time.Millisecond) + cancel() // ends the wait; handle stays busy until the provider call settles +}() + +_, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ + Argv: []string{"sleep", "30"}, +}) +``` + + + ## Close -| Call | Effect | -| ------------------------ | ---------------------------------------- | -| Client `close` / `Close` | Closes the local provider SDK connection | -| Handle `close` / `Close` | Releases local handle resources | +Neither call stops, archives, or deletes the cloud sandbox. Use an explicit lifecycle method for that. -Neither call stops, terminates, archives, or deletes the cloud sandbox. You can keep using the handle after handle `close` fails only if the provider still accepts calls; prefer an explicit lifecycle method to reclaim the sandbox. + + -## Errors +```ts +await client.close(); // local provider connection +await sandbox.close(); // local handle resources only +``` -Failed calls throw `SandboxError` in TypeScript and return `*sandbox.Error` in Go. Both expose `kind`, `field`, `operation`, and `message`. See [Errors](/docs/errors). + + + +```go +defer client.Close(context.Background()) // local provider connection +_ = instance.Close(context.Background()) // local handle resources only +``` + + + + +## Errors -## Out of scope +Kinds, field paths, and handling: [Errors](/docs/errors). -Streaming stdin/stdout, long-lived process sessions, PTY, Daytona `code_run`, GPU requests, resizing, and browsers are not part of this client. +Streaming I/O, interactive sessions, PTY, GPU, resize, and browsers are outside this SDK. diff --git a/website/content/docs/configuration.mdx b/website/content/docs/configuration.mdx index 29306757..14f2363a 100644 --- a/website/content/docs/configuration.mdx +++ b/website/content/docs/configuration.mdx @@ -1,20 +1,56 @@ --- title: Configuration -description: Auth, scope, endpoint, region, and default timeouts on Client construction. +description: Auth, scope, endpoint, region, and timeouts on the client. --- -Pass provider + config at construction. Later mutations of the config object do not affect a running client. TypeScript throws on invalid config; Go returns `(*Client, error)`. +Pass a provider and config at construction. Changing the config object afterward does not update a running client. Invalid config: [Errors](/docs/errors#invalid-config). -| Field | Purpose | -| ---------- | ----------------------------------------------------------------------------------------------------- | -| `provider` | `daytona()` / `modal()` (or Go `New()`) | -| `auth` | One of `apiKey`, `tokenPair`, `bearerToken`, `oauthRefresh`. Omit to use provider SDK env credentials | -| `scope` | App, environment, or organization | -| `endpoint` | API URL when the provider allows it | -| `region` | Target / default placement | -| `timeout` | Default deadline (TS: ms, Go: `sandbox.Duration`) | + + + +```ts +import { Client } from "@sandbox-kit/sandbox"; + +await using client = new Client({ + provider, + timeout: 120_000, // milliseconds +}); +``` + + + + +```go +import ( + "time" + + "github.com/sandbox-kit/kit/sdks/go/sandbox" +) + +client, err := sandbox.NewClient(provider, &sandbox.Config{ + Timeout: sandbox.Duration(2 * time.Minute), +}) +if err != nil { + return err +} +``` -Switch Daytona or Modal above for auth and scope samples. First client walkthrough: [Daytona](/docs/daytona) or [Modal](/docs/modal). + + + +| Field | Purpose | +| ---------- | ------------------------------------------------------------------------------------------- | +| `provider` | Provider constructor | +| `auth` | One of `apiKey`, `tokenPair`, `bearerToken`, `oauthRefresh`. Omit to use provider env creds | +| `scope` | App, environment, or organization | +| `endpoint` | Provider control-plane URL when that provider allows it | +| `region` | Target / default placement | +| `timeout` | Default deadline | + + + Provider setup: [Daytona](/docs/daytona). + +Provider setup: [Modal](/docs/modal). ## Client @@ -127,46 +163,313 @@ client, err := sandbox.NewClient(modal.New(), config) -| Setting | What to pass | -| ------------ | -------------------------------------------------------------------- | -| API key | `auth.apiKey.key` / `APIKey` | -| Bearer token | `auth.bearerToken.token` / `BearerToken`, plus an organization id | -| Endpoint | `endpoint` / `Config.Endpoint`. Default `https://app.daytona.io/api` | -| Target | `region` / `Config.Region`. Leave it unset for the default target | -| Organization | `scope.organizationId` / `Scope.OrganizationId` | + + + +| Setting | What to pass | +| ------------ | ------------------------------------------------- | +| API key | `auth.apiKey.key` | +| Bearer token | `auth.bearerToken.token`, plus an organization id | +| Endpoint | `endpoint`. Default `https://app.daytona.io/api` | +| Target | `region`. Omit for the default target | +| Organization | `scope.organizationId` | + +```ts +await using client = new Client({ + provider: daytona(), + auth: { bearerToken: { token: process.env.DAYTONA_JWT! } }, + scope: { organizationId: process.env.DAYTONA_ORG_ID! }, + endpoint: "https://app.daytona.io/api", + region: process.env.DAYTONA_TARGET, + timeout: 120_000, +}); +``` + + + + +| Setting | What to pass | +| ------------ | ------------------------------------------------------- | +| API key | `APIKey` | +| Bearer token | `BearerToken`, plus an organization id | +| Endpoint | `Config.Endpoint`. Default `https://app.daytona.io/api` | +| Target | `Config.Region`. Omit for the default target | +| Organization | `Scope.OrganizationId` | + +```go +config := &sandbox.Config{ + Auth: &sandbox.AuthConfig{Credentials: &sandbox.BearerToken{ + BearerToken: &sandbox.BearerTokenCredentials{Token: os.Getenv("DAYTONA_JWT")}, + }}, + Scope: &sandbox.Scope{ + OrganizationId: sandbox.Value(os.Getenv("DAYTONA_ORG_ID")), + }, + Endpoint: sandbox.Value("https://app.daytona.io/api"), + Region: sandbox.Value(os.Getenv("DAYTONA_TARGET")), + Timeout: sandbox.Duration(2 * time.Minute), +} +client, err := sandbox.NewClient(daytona.New(), config) +``` + + + -A remote endpoint uses HTTPS. HTTP is accepted for localhost and loopback. A URL with a username, password, or fragment is rejected. Sandbox Kit does not read the Daytona URL from the environment. +Remote endpoints must be HTTPS. HTTP is fine for localhost and loopback. URLs with a username, password, or fragment are rejected. Sandbox Kit does not read the Daytona URL from the environment. -| Setting | What to pass | -| ------------- | ------------------------------------------------------------------------ | -| Token pair | `auth.tokenPair` / `TokenPair` | -| OAuth refresh | Client id, plus one client secret or one JWT key | -| App | `scope.appName` / `Scope.AppName`, required | -| Environment | `scope.environment` / `Scope.Environment`, often `main` | -| Region | `region` / `Config.Region`. Leave it unset for Modal's default placement | + + + +| Setting | What to pass | +| ------------- | ------------------------------------------------ | +| Token pair | `auth.tokenPair` | +| OAuth refresh | Client id, plus one client secret or one JWT key | +| App | `scope.appName`, required | +| Environment | `scope.environment`, often `main` | +| Region | `region`. Omit for Modal's default placement | + +```ts +await using client = new Client({ + provider: modal(), + auth: { + oauthRefresh: { + refreshToken: process.env.MODAL_REFRESH_TOKEN!, + clientId: process.env.MODAL_CLIENT_ID!, + clientSecret: process.env.MODAL_CLIENT_SECRET!, + }, + }, + scope: { + appName: process.env.MODAL_APP_NAME!, + environment: "main", + }, + region: process.env.MODAL_REGION, + timeout: 120_000, +}); +``` -`endpoint` is rejected. You can still set cloud and region on a single [create](/docs/create) request. + + + +| Setting | What to pass | +| ------------- | --------------------------------------------------- | +| Token pair | `TokenPair` | +| OAuth refresh | Client id, plus one client secret or one JWT key | +| App | `Scope.AppName`, required | +| Environment | `Scope.Environment`, often `main` | +| Region | `Config.Region`. Omit for Modal's default placement | + +```go +config := &sandbox.Config{ + Auth: &sandbox.AuthConfig{Credentials: &sandbox.OAuthRefresh{ + OauthRefresh: &sandbox.OAuthCredentials{ + RefreshToken: os.Getenv("MODAL_REFRESH_TOKEN"), + ClientId: os.Getenv("MODAL_CLIENT_ID"), + ClientSecret: sandbox.Value(os.Getenv("MODAL_CLIENT_SECRET")), + }, + }}, + Scope: &sandbox.Scope{ + AppName: sandbox.Value(os.Getenv("MODAL_APP_NAME")), + Environment: sandbox.Value("main"), + }, + Region: sandbox.Value(os.Getenv("MODAL_REGION")), + Timeout: sandbox.Duration(2 * time.Minute), +} +client, err := sandbox.NewClient(modal.New(), config) +``` + + + + +`endpoint` is rejected. Set cloud and region on a single [create](/docs/create) request instead. ## Timeouts -`timeout` on the client is the default deadline. A create request can override it. A lifecycle call can override it again. +`timeout` on the client is the default deadline. Create and lifecycle calls can override it. -Explicit zero adds no deadline of Sandbox Kit's own. A context deadline or an abort signal that arrives earlier still applies. +Explicit zero adds no Kit deadline of its own. A context deadline or abort signal that fires earlier still wins. + + + + + + +```ts +await using client = new Client({ + provider: daytona(), + timeout: 120_000, // default deadline for calls that omit timeout +}); + +const sandbox = await client.create( + { source: { image: { reference: "daytonaio/playground:latest" } } }, + { timeout: 60_000 }, // override for this call; 0 = no Kit deadline +); +``` + + + + + +```ts +await using client = new Client({ + provider: modal(), + timeout: 120_000, // default deadline for calls that omit timeout +}); + +const sandbox = await client.create( + { source: { image: { reference: "alpine:3.21" } } }, + { timeout: 60_000 }, // override for this call; 0 = no Kit deadline +); +``` + + + + + + + + +```go +client, err := sandbox.NewClient(daytona.New(), &sandbox.Config{ + Timeout: sandbox.Duration(2 * time.Minute), // default deadline +}) +if err != nil { + return err +} + +instance, err := client.Create(ctx, &sandbox.CreateOptions{ + Source: &sandbox.SandboxSource{Kind: &sandbox.Image{ + Image: &sandbox.ImageSource{Reference: "daytonaio/playground:latest"}, + }}, + Provisioning: &sandbox.ProvisioningOptions{ + Timeout: sandbox.Duration(60 * time.Second), // override; 0 = no Kit deadline + }, +}) +``` + + + + + +```go +client, err := sandbox.NewClient(modal.New(), &sandbox.Config{ + Timeout: sandbox.Duration(2 * time.Minute), // default deadline +}) +if err != nil { + return err +} + +instance, err := client.Create(ctx, &sandbox.CreateOptions{ + Source: &sandbox.SandboxSource{Kind: &sandbox.Image{ + Image: &sandbox.ImageSource{Reference: "alpine:3.21"}, + }}, + Provisioning: &sandbox.ProvisioningOptions{ + Timeout: sandbox.Duration(60 * time.Second), // override; 0 = no Kit deadline + }, +}) +``` + + + + + Daytona keeps its 60-second default for create, start, stop, pause, and delete - when you omit the timeout, and when you pass explicit zero. A Daytona timeout - that is not a whole number of seconds is rejected. + when you omit the timeout or pass zero. Fractional-second Daytona timeouts are + rejected. ## Credentials -Do not log the config object—it contains secrets. TypeScript configs are plain objects (`JSON.stringify` includes keys). +Do not log the config object—it holds secrets. Construction does not contact the provider. Bad credentials fail on the first create or open. See [Errors](/docs/errors). -Construction does not contact the provider. Bad credentials fail on the first create/get/attach. See [Errors](/docs/errors). + + + + + +```ts +const config = { + provider: daytona(), + auth: { apiKey: { key: process.env.DAYTONA_API_KEY! } }, + timeout: 120_000, +}; + +await using client = new Client(config); +``` + +Keep secrets out of logs—do not `JSON.stringify(config)`. + + + + + +```ts +const config = { + provider: modal(), + auth: { + tokenPair: { + id: process.env.MODAL_TOKEN_ID!, + secret: process.env.MODAL_TOKEN_SECRET!, + }, + }, + scope: { appName: process.env.MODAL_APP_NAME!, environment: "main" }, + timeout: 120_000, +}; + +await using client = new Client(config); +``` + +Keep secrets out of logs—do not `JSON.stringify(config)`. + + + + + + + + +```go +config := &sandbox.Config{ + Auth: &sandbox.AuthConfig{Credentials: &sandbox.APIKey{ + ApiKey: &sandbox.APIKeyCredentials{Key: os.Getenv("DAYTONA_API_KEY")}, + }}, + Timeout: sandbox.Duration(2 * time.Minute), +} +client, err := sandbox.NewClient(daytona.New(), config) +``` + +Keep secrets out of logs—do not `fmt.Printf("%+v", config)`. + + + + + +```go +config := &sandbox.Config{ + Auth: &sandbox.AuthConfig{Credentials: &sandbox.TokenPair{ + TokenPair: &sandbox.TokenPairCredentials{ + Id: os.Getenv("MODAL_TOKEN_ID"), + Secret: os.Getenv("MODAL_TOKEN_SECRET"), + }, + }}, + Scope: &sandbox.Scope{ + AppName: sandbox.Value(os.Getenv("MODAL_APP_NAME")), + Environment: sandbox.Value("main"), + }, + Timeout: sandbox.Duration(2 * time.Minute), +} +client, err := sandbox.NewClient(modal.New(), config) +``` + +Keep secrets out of logs—do not `fmt.Printf("%+v", config)`. + + + + + diff --git a/website/content/docs/create.mdx b/website/content/docs/create.mdx index 927503ba..4b3c7e2a 100644 --- a/website/content/docs/create.mdx +++ b/website/content/docs/create.mdx @@ -1,20 +1,95 @@ --- title: Create a sandbox -description: Image or snapshot, resources, lifetime, and placement options for create. +description: Image or snapshot, resources, lifetime, and placement for create. --- -`client.create` / `Client.Create` returns a sandbox handle. Build the client first ([Daytona](/docs/daytona), [Modal](/docs/modal), or [Configuration](/docs/configuration)). +Create returns a sandbox handle. Build the client first. -Omitted fields keep provider defaults. Unsupported fields fail in Kit before the provider call ([Errors](/docs/errors)). + + Provider setup: [Daytona](/docs/daytona). + +Provider setup: [Modal](/docs/modal). + +Omitted fields keep provider defaults. Unsupported fields fail in Kit before the provider call. + + + + + + +```ts +const sandbox = await client.create( + { + source: { image: { reference: "daytonaio/playground:latest" } }, + resources: { cpuCores: 1, memoryMib: 512n }, + }, + { timeout: 60_000 }, // milliseconds +); +``` + + + + + +```ts +const sandbox = await client.create( + { + source: { image: { reference: "alpine:3.21" } }, + resources: { cpuCores: 1, memoryMib: 512n }, + }, + { timeout: 60_000 }, // milliseconds +); +``` + + -| Language | Durations | Optionals | -| ---------- | ---------------------------------------------------------------- | ------------------ | -| TypeScript | milliseconds; missing property = omitted | nested objects | -| Go | `sandbox.Duration`; numbers via `sandbox.Value` (including zero) | pointers / `Value` | + + + + + +```go +instance, err := client.Create(ctx, &sandbox.CreateOptions{ + Source: &sandbox.SandboxSource{Kind: &sandbox.Image{ + Image: &sandbox.ImageSource{Reference: "daytonaio/playground:latest"}, + }}, + Resources: &sandbox.Resources{ + CpuCores: sandbox.Value(1.0), + MemoryMib: sandbox.Value(uint64(512)), + }, + Provisioning: &sandbox.ProvisioningOptions{ + Timeout: sandbox.Duration(60 * time.Second), + }, +}) +``` + + + + + +```go +instance, err := client.Create(ctx, &sandbox.CreateOptions{ + Source: &sandbox.SandboxSource{Kind: &sandbox.Image{ + Image: &sandbox.ImageSource{Reference: "alpine:3.21"}, + }}, + Resources: &sandbox.Resources{ + CpuCores: sandbox.Value(1.0), + MemoryMib: sandbox.Value(uint64(512)), + }, + Provisioning: &sandbox.ProvisioningOptions{ + Timeout: sandbox.Duration(60 * time.Second), + }, +}) +``` + + + + + ## Units -Switch Daytona or Modal above for units and create samples. Account quotas, image names, regions, and capacity are checked by the provider. +Account quotas, image names, regions, and capacity are enforced by the provider. @@ -29,6 +104,60 @@ Switch Daytona or Modal above for units and create samples. Account quotas, imag A size override requires an image. A snapshot create keeps the snapshot's size. + + + +```ts +import { PolicyMode } from "@sandbox-kit/sandbox"; + +await client.create({ + source: { image: { reference: "daytonaio/playground:latest" } }, + resources: { + cpuCores: 2, // whole cores + memoryMib: 4096n, // 4 GiB as MiB + diskMib: 8192n, // 8 GiB as MiB + }, + lifetime: { + idlePause: { mode: PolicyMode.Disabled }, + stoppedDelete: { mode: PolicyMode.After, after: 10 * 60_000 }, + }, + runtime: { + workingDirectory: "/home/daytona", + entrypoint: ["sleep", "infinity"], + }, +}); +``` + + + + +```go +instance, err := client.Create(ctx, &sandbox.CreateOptions{ + Source: &sandbox.SandboxSource{Kind: &sandbox.Image{ + Image: &sandbox.ImageSource{Reference: "daytonaio/playground:latest"}, + }}, + Resources: &sandbox.Resources{ + CpuCores: sandbox.Value(2.0), // whole cores + MemoryMib: sandbox.Value(uint64(4096)), // 4 GiB as MiB + DiskMib: sandbox.Value(uint64(8192)), // 8 GiB as MiB + }, + Lifetime: &sandbox.LifetimePolicy{ + IdlePause: &sandbox.AutomaticAction{Mode: sandbox.PolicyModeDisabled}, + StoppedDelete: &sandbox.AutomaticAction{ + Mode: sandbox.PolicyModeAfter, + After: sandbox.Duration(10 * time.Minute), + }, + }, + Runtime: &sandbox.RuntimeConfig{ + WorkingDirectory: sandbox.Value("/home/daytona"), + Entrypoint: []string{"sleep", "infinity"}, + }, +}) +``` + + + + @@ -42,7 +171,64 @@ A size override requires an image. A snapshot create keeps the snapshot's size. | Lifetime | Maximum lifetime and idle termination | | Placement | `placement` on this request. Client `region` is the default | -Pass a registry image. The app name belongs on the client, not on this request. Leave a resource out to keep Modal's default. +Pass a registry image. Put the app name on the client, not on this request. Leave a resource out to keep Modal's default. + + + + +```ts +import { PolicyMode } from "@sandbox-kit/sandbox"; + +await client.create({ + source: { image: { reference: "alpine:3.21" } }, + resources: { + cpuCores: 0.5, // fractional, min 0.125 + memoryMib: 512n, // min 128 when set + }, + placement: { cloud: "aws", regions: ["us-east-1"] }, + lifetime: { + maximumLifetime: 5 * 60_000, // milliseconds + idleTerminate: { mode: PolicyMode.After, after: 60_000 }, + }, + runtime: { + workingDirectory: "/tmp", + entrypoint: ["sleep", "infinity"], + }, +}); +``` + + + + +```go +instance, err := client.Create(ctx, &sandbox.CreateOptions{ + Source: &sandbox.SandboxSource{Kind: &sandbox.Image{ + Image: &sandbox.ImageSource{Reference: "alpine:3.21"}, + }}, + Resources: &sandbox.Resources{ + CpuCores: sandbox.Value(0.5), // fractional, min 0.125 + MemoryMib: sandbox.Value(uint64(512)), // min 128 when set + }, + Placement: &sandbox.Placement{ + Cloud: sandbox.Value("aws"), + Regions: []string{"us-east-1"}, + }, + Lifetime: &sandbox.LifetimePolicy{ + MaximumLifetime: sandbox.Duration(5 * time.Minute), + IdleTerminate: &sandbox.AutomaticAction{ + Mode: sandbox.PolicyModeAfter, + After: sandbox.Duration(time.Minute), + }, + }, + Runtime: &sandbox.RuntimeConfig{ + WorkingDirectory: sandbox.Value("/tmp"), + Entrypoint: []string{"sleep", "infinity"}, + }, +}) +``` + + + @@ -54,13 +240,23 @@ Pass a registry image. The app name belongs on the client, not on this request. ```ts +import { PolicyMode } from "@sandbox-kit/sandbox"; + const sandbox = await client.create({ source: { image: { reference: "daytonaio/playground:latest" } }, resources: { - cpuCores: 2, - memoryMib: 4096n, + cpuCores: 2, // whole cores + memoryMib: 4096n, // 4 GiB as MiB diskMib: 8192n, }, + lifetime: { + idlePause: { mode: PolicyMode.Disabled }, + stoppedDelete: { mode: PolicyMode.After, after: 10 * 60_000 }, + }, + runtime: { + workingDirectory: "/home/daytona", + entrypoint: ["sleep", "infinity"], + }, }); ``` @@ -79,9 +275,10 @@ const sandbox = await client.create({ entrypoint: ["sleep", "infinity"], }, lifetime: { - maximumLifetime: 5 * 60_000, + maximumLifetime: 5 * 60_000, // milliseconds idleTerminate: { mode: PolicyMode.After, after: 60_000 }, }, + placement: { cloud: "aws", regions: ["us-east-1"] }, }); ``` @@ -95,7 +292,11 @@ const sandbox = await client.create({ ```go -import "github.com/sandbox-kit/kit/sdks/go/sandbox" +import ( + "time" + + "github.com/sandbox-kit/kit/sdks/go/sandbox" +) instance, err := client.Create(ctx, &sandbox.CreateOptions{ Source: &sandbox.SandboxSource{Kind: &sandbox.Image{ @@ -106,6 +307,17 @@ instance, err := client.Create(ctx, &sandbox.CreateOptions{ MemoryMib: sandbox.Value(uint64(4096)), DiskMib: sandbox.Value(uint64(8192)), }, + Lifetime: &sandbox.LifetimePolicy{ + IdlePause: &sandbox.AutomaticAction{Mode: sandbox.PolicyModeDisabled}, + StoppedDelete: &sandbox.AutomaticAction{ + Mode: sandbox.PolicyModeAfter, + After: sandbox.Duration(10 * time.Minute), + }, + }, + Runtime: &sandbox.RuntimeConfig{ + WorkingDirectory: sandbox.Value("/home/daytona"), + Entrypoint: []string{"sleep", "infinity"}, + }, }) ``` @@ -139,6 +351,10 @@ instance, err := client.Create(ctx, &sandbox.CreateOptions{ After: sandbox.Duration(time.Minute), }, }, + Placement: &sandbox.Placement{ + Cloud: sandbox.Value("aws"), + Regions: []string{"us-east-1"}, + }, }) ``` @@ -149,11 +365,38 @@ instance, err := client.Create(ctx, &sandbox.CreateOptions{ -Name a snapshot by its reference, for example `daytona-small`. In TypeScript that is `source: { snapshot: { reference } }`. Set the toolbox language and user on `runtime`. +Name a snapshot by reference (for example `daytona-small`). Set toolbox language and user on `runtime`. + + + + +```ts +const sandbox = await client.create({ + source: { + snapshot: { reference: "daytona-small" }, + }, +}); +``` + + + -A linked sandbox must be ephemeral. The client rejects the request otherwise. +```go +instance, err := client.Create(ctx, &sandbox.CreateOptions{ + Source: &sandbox.SandboxSource{Kind: &sandbox.Snapshot{ + Snapshot: &sandbox.SnapshotSource{Reference: "daytona-small"}, + }}, +}) +``` -Idle stop, idle pause, stopped archive, and stopped delete use `PolicyMode` from `@sandbox-kit/sandbox` (`sandbox.PolicyModeAfter` and `sandbox.PolicyModeDisabled` in Go). A positive stop delay and a positive pause delay cannot be combined. Projects for [snapshots](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-from-snapshot), [policies](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-policies), [labels](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-labels), and [network](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-network) are in the repository. Go projects sit beside them under `examples/go/daytona/`. + + + +A linked sandbox must be ephemeral; Kit rejects the request otherwise. + +Idle stop, idle pause, stopped archive, and stopped delete use `PolicyMode` (`After` / `Disabled`). You cannot combine a positive stop delay with a positive pause delay. + +Samples: [Examples](/docs/examples). @@ -161,14 +404,99 @@ Idle stop, idle pause, stopped archive, and stopped delete use `PolicyMode` from Set cloud and region on `placement`. A ready wait needs a probe and a positive timeout. -Modal rejects a disk size, an API endpoint, and Daytona stop or archive policies. Projects for [resources](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-resources), [idle timeout](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-idle), [placement](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-placement), and [readiness](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-ready) are in the repository. Go projects sit beside them under `examples/go/modal/`. +Disk size, a control-plane endpoint, and stop / pause / archive / delete policies are rejected. + + + + +```ts +import { WaitCondition } from "@sandbox-kit/sandbox"; + +await client.create({ + source: { image: { reference: "alpine:3.21" } }, + placement: { + cloud: "aws", + regions: ["us-east-1"], + }, + runtime: { entrypoint: ["sleep", "300"] }, + readiness: { command: { argv: ["true"] } }, + provisioning: { timeout: 120_000, waitFor: WaitCondition.Ready }, +}); +``` + + + + +```go +instance, err := client.Create(ctx, &sandbox.CreateOptions{ + Source: &sandbox.SandboxSource{Kind: &sandbox.Image{ + Image: &sandbox.ImageSource{Reference: "alpine:3.21"}, + }}, + Placement: &sandbox.Placement{ + Cloud: sandbox.Value("aws"), + Regions: []string{"us-east-1"}, + }, + Runtime: &sandbox.RuntimeConfig{ + Entrypoint: []string{"sleep", "300"}, + }, + Readiness: &sandbox.ReadinessProbe{ + Check: &sandbox.Command{ + Command: &sandbox.CommandProbe{Argv: []string{"true"}}, + }, + }, + Provisioning: &sandbox.ProvisioningOptions{ + Timeout: sandbox.Duration(2 * time.Minute), + WaitFor: sandbox.WaitConditionReady, + }, +}) +``` + + + + +Samples: [Examples](/docs/examples). ## Result -`info()` / `Info()` returns a **copy** of metadata. Mutating it does not change the sandbox. Reported CPU/memory can differ from requested values. +Metadata from info is a **copy**. Mutating it does not change the sandbox. Reported CPU and memory can differ from what you requested. -After create: [Filesystem](/docs/filesystem), [Run a command](/docs/process), [Lifecycle](/docs/lifecycle). + + + +```ts +const info = sandbox.info(); +console.log(info.id); +console.log(info.provider); +console.log(info.state); // portable lifecycle state +console.log(info.providerState); // provider's native string when set +console.log(info.name); +console.log(info.region); +console.log(info.resources?.cpuCores, info.resources?.memoryMib); +console.log(info.labels); +console.log(info.terminal); +``` + + + + +```go +info := instance.Info() +fmt.Println(info.Id) +fmt.Println(info.Provider) +fmt.Println(info.State) // portable lifecycle state +fmt.Println(info.GetProviderState()) // provider's native string when set +fmt.Println(info.GetName()) +fmt.Println(info.GetRegion()) +if info.Resources != nil { + fmt.Println(info.Resources.GetCpuCores(), info.Resources.GetMemoryMib()) +} +fmt.Println(info.Labels) +fmt.Println(info.GetTerminal()) +``` + + + -Not in this surface: streaming sessions, PTY, GPU, resize, extra storage, browsers. +After create: [Filesystem](/docs/filesystem) · [Run a command](/docs/process) · [Lifecycle](/docs/lifecycle). diff --git a/website/content/docs/daytona.mdx b/website/content/docs/daytona.mdx index b963db8c..4abb80df 100644 --- a/website/content/docs/daytona.mdx +++ b/website/content/docs/daytona.mdx @@ -1,9 +1,9 @@ --- title: Daytona -description: Install, authenticate, and create a Daytona sandbox with the shared client. +description: Install, authenticate, and create a Daytona sandbox. --- -Provider package for Daytona sandboxes. Default create uses Daytona's default snapshot. Native SDK: Daytona v0.225.0. +Use Daytona when you want default snapshots, verified `get`, and start / stop / pause / archive. ## Install @@ -27,7 +27,7 @@ go get github.com/sandbox-kit/kit/sdks/go/providers/daytona@latest ## Create -Set `DAYTONA_API_KEY`. +Set `DAYTONA_API_KEY`. Omit create options to use Daytona's default snapshot. @@ -46,7 +46,7 @@ const sandbox = await client.create(); console.log(sandbox.id); ``` -`timeout` is milliseconds. Prefer `await using`; otherwise `await client.close()` in `finally`. +`timeout` is milliseconds. Prefer `await using`; otherwise call `await client.close()` when finished. @@ -84,40 +84,118 @@ func main() { } ``` -Nil create options → default snapshot. Optional strings use `sandbox.Value`. +Optional strings use `sandbox.Value`. -Omit `auth` to let the Daytona SDK resolve credentials from its environment. Closing the client does not delete the sandbox. +Omit `auth` to let the Daytona SDK pick credentials from its environment. Closing the client does not delete the sandbox. ## Configuration -| Setting | TypeScript | Go | -| ------------ | ------------------------ | ---------------------- | -| API URL | `endpoint` | `Config.Endpoint` | -| Target | `region` | `Config.Region` | -| Organization | `scope.organizationId` | `Scope.OrganizationId` | -| Bearer token | `auth.bearerToken.token` | `BearerToken` | + + + +| Setting | Field | +| ------------ | ------------------------ | +| API URL | `endpoint` | +| Target | `region` | +| Organization | `scope.organizationId` | +| Bearer token | `auth.bearerToken.token` | + +```ts +await using client = new Client({ + provider: daytona(), + auth: { apiKey: { key: process.env.DAYTONA_API_KEY! } }, + endpoint: "https://app.daytona.io/api", // default; HTTPS required remotely + region: process.env.DAYTONA_TARGET, // optional target + scope: { organizationId: process.env.DAYTONA_ORG_ID }, + timeout: 120_000, +}); +``` + +Bearer token auth: + +```ts +await using client = new Client({ + provider: daytona(), + auth: { bearerToken: { token: process.env.DAYTONA_JWT! } }, + scope: { organizationId: process.env.DAYTONA_ORG_ID! }, + timeout: 120_000, +}); +``` + + + + +| Setting | Field | +| ------------ | ---------------------- | +| API URL | `Config.Endpoint` | +| Target | `Config.Region` | +| Organization | `Scope.OrganizationId` | +| Bearer token | `BearerToken` | -Default API URL: `https://app.daytona.io/api`. Remote URLs require HTTPS. HTTP is allowed for localhost/loopback. Bearer tokens require an organization id. Full rules: [Configuration](/docs/configuration). +```go +config := &sandbox.Config{ + Auth: &sandbox.AuthConfig{Credentials: &sandbox.APIKey{ + ApiKey: &sandbox.APIKeyCredentials{Key: os.Getenv("DAYTONA_API_KEY")}, + }}, + Endpoint: sandbox.Value("https://app.daytona.io/api"), // default; HTTPS remotely + Region: sandbox.Value(os.Getenv("DAYTONA_TARGET")), + Scope: &sandbox.Scope{ + OrganizationId: sandbox.Value(os.Getenv("DAYTONA_ORG_ID")), + }, + Timeout: sandbox.Duration(2 * time.Minute), +} +client, err := sandbox.NewClient(daytona.New(), config) +``` + +Bearer token auth: + +```go +config := &sandbox.Config{ + Auth: &sandbox.AuthConfig{Credentials: &sandbox.BearerToken{ + BearerToken: &sandbox.BearerTokenCredentials{Token: os.Getenv("DAYTONA_JWT")}, + }}, + Scope: &sandbox.Scope{ + OrganizationId: sandbox.Value(os.Getenv("DAYTONA_ORG_ID")), + }, + Timeout: sandbox.Duration(2 * time.Minute), +} +client, err := sandbox.NewClient(daytona.New(), config) +``` + + + + +Default API URL: `https://app.daytona.io/api`. Remote URLs need HTTPS; HTTP is allowed for localhost. Bearer tokens need an organization id. Full rules: [Configuration](/docs/configuration). -## Operations +## What works -| Area | Support | -| --------- | ----------------------------------------------------------------- | -| Create | Default snapshot, named snapshot, or image (+ resources) | -| Open | `get` (verified). `attach` unsupported | -| Lifecycle | `refresh`, `start`, `stop`, `pause`, `archive`, `delete`, `close` | -| Files | Full filesystem API — [Filesystem](/docs/filesystem) | -| Process | `run` — [Run a command](/docs/process) | +| Area | Notes | +| --------- | ----------------------------------------------------------- | +| Create | Default snapshot, named snapshot, or image (with resources) | +| Open | `get` — verified. `attach` is unsupported | +| Lifecycle | `refresh`, `start`, `stop`, `pause`, `archive`, `delete` | +| Files | Filesystem methods — [Filesystem](/docs/filesystem) | +| Process | `run` — [Run a command](/docs/process) | -CPU: whole cores. Memory/disk: whole GiB as MiB. Resource overrides require an image source. +CPU is whole cores. Memory and disk are whole GiB expressed as MiB. Resource overrides require an image source. ## Related -| Topic | Link | -| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Image, size, policies | [Create](/docs/create#daytona) | -| get / stop / delete | [Lifecycle](/docs/lifecycle) | -| Example project | [create-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-sandbox) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-sandbox) | +- Image, size, and policies — [Create](/docs/create) +- get / stop / delete — [Lifecycle](/docs/lifecycle) + + + + +Sample: [create-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-sandbox) + + + + +Sample: [create-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-sandbox) + + + diff --git a/website/content/docs/errors.mdx b/website/content/docs/errors.mdx index f50686e4..ef03d604 100644 --- a/website/content/docs/errors.mdx +++ b/website/content/docs/errors.mdx @@ -3,27 +3,81 @@ title: Errors description: SandboxError / *sandbox.Error kinds, fields, and provider causes. --- -TypeScript throws `SandboxError`. Go returns `*sandbox.Error`. Both include `kind`, `provider`, `operation`, `message`, and `field` when a setting was rejected. +Failed calls surface a typed error with `kind`, `provider`, `operation`, `message`, and `field` when a setting was rejected. -Kinds are shared across providers. A kind is a category—not a retry policy. Kit does not retry. +Kinds are categories, not retry advice. Kit does not retry. | Kind | What happened | | ------------------- | ------------------------------------------------------ | | `InvalidArgument` | The request shape is wrong | | `Unsupported` | This provider does not implement the call or the field | -| `Authentication` | The credentials were rejected | +| `Authentication` | Credentials were rejected | | `PermissionDenied` | The account cannot perform this operation | -| `NotFound` | The sandbox or the file path was not found | -| `RateLimited` | The provider rate limit was reached | -| `ResourceExhausted` | The provider quota or capacity was reached | +| `NotFound` | The sandbox or file path was not found | +| `RateLimited` | Provider rate limit reached | +| `ResourceExhausted` | Provider quota or capacity reached | | `Canceled` | The caller canceled the operation | | `Timeout` | The deadline fired | +## Invalid config + +Bad client config fails before any provider call. TypeScript throws; Go returns `(*Client, error)`. + + + + +```ts +import { Client, SandboxError } from "@sandbox-kit/sandbox"; + +try { + new Client({ provider, timeout: -1 }); +} catch (error) { + if (error instanceof SandboxError) { + console.error(error.kind); + console.error(error.field); + console.error(error.message); + } + throw error; +} +``` + + + + +```go +import ( + "errors" + "fmt" + "time" + + "github.com/sandbox-kit/kit/sdks/go/sandbox" +) + +client, err := sandbox.NewClient(provider, &sandbox.Config{ + Timeout: sandbox.Duration(-1 * time.Second), +}) +if err != nil { + var detail *sandbox.Error + if errors.As(err, &detail) { + fmt.Println(detail.Kind) + fmt.Println(detail.Field) + fmt.Println(detail.Message) + } + return err +} +_ = client +``` + + + + ## Handle by kind +Throws `SandboxError`. + ```ts import { ErrorKind, SandboxError } from "@sandbox-kit/sandbox"; @@ -41,22 +95,20 @@ try { console.error("Check your provider credentials."); break; case ErrorKind.PermissionDenied: - console.error( - "Your account does not have permission for this operation.", - ); + console.error("Your account cannot perform this operation."); break; case ErrorKind.NotFound: - console.error("The sandbox or file path was not found."); + console.error("Sandbox or file path not found."); break; case ErrorKind.RateLimited: case ErrorKind.ResourceExhausted: - console.error("The provider's rate or resource limit was reached."); + console.error("Provider rate or resource limit reached."); break; case ErrorKind.Canceled: - console.error("The operation was canceled."); + console.error("Operation canceled."); break; case ErrorKind.Timeout: - console.error("The operation timed out."); + console.error("Operation timed out."); break; default: console.error(error); @@ -69,6 +121,8 @@ The provider's own error is `error.cause`. +Returns `*sandbox.Error`. + ```go import ( "errors" @@ -85,15 +139,15 @@ if errors.As(err, &detail) { case sandbox.ErrorKindAuthentication: fmt.Println("Check your provider credentials.") case sandbox.ErrorKindPermissionDenied: - fmt.Println("Your account does not have permission for this operation.") + fmt.Println("Your account cannot perform this operation.") case sandbox.ErrorKindNotFound: - fmt.Println("The sandbox or file path was not found.") + fmt.Println("Sandbox or file path not found.") case sandbox.ErrorKindRateLimited, sandbox.ErrorKindResourceExhausted: - fmt.Println("The provider's rate or resource limit was reached.") + fmt.Println("Provider rate or resource limit reached.") case sandbox.ErrorKindCanceled: - fmt.Println("The operation was canceled.") + fmt.Println("Operation canceled.") case sandbox.ErrorKindTimeout: - fmt.Println("The operation timed out.") + fmt.Println("Operation timed out.") default: fmt.Println(err) } @@ -107,12 +161,135 @@ if errors.As(err, &detail) { ## Field paths -Field strings match across languages (for example `resources.cpu_cores`). Rules that cover several settings use the parent (`network`). TypeScript exports constants such as `CreateFieldResourcesCpuCores` for comparisons. +Field strings are shared (for example `resources.cpu_cores`). Rules that cover several settings use the parent (`network`). + + + + +```ts +import { + CreateFieldResourcesCpuCores, + SandboxError, +} from "@sandbox-kit/sandbox"; + +try { + await client.create({ resources: { cpuCores: -1 } }); +} catch (error) { + if ( + error instanceof SandboxError && + error.field === CreateFieldResourcesCpuCores + ) { + console.error("bad cpuCores:", error.message); + } +} +``` + + + + +```go +_, err := client.Create(ctx, &sandbox.CreateOptions{ + Resources: &sandbox.Resources{CpuCores: sandbox.Value(-1.0)}, +}) +var detail *sandbox.Error +if errors.As(err, &detail) && detail.Field == sandbox.CreateFieldResourcesCpuCores { + fmt.Println("bad cpuCores:", detail.Message) +} +``` + + + ## After failure An error does not prove no sandbox was created—the provider may have succeeded before a later step failed, and the error does not include that id. Lifecycle failures can occur after the provider already mutated state. -On Daytona, `get` before retry. Modal `attach` does not verify existence. + + +`get` before retry so you know whether the sandbox exists. + + + + +```ts +try { + await client.create(request); +} catch (error) { + // create may have succeeded before a later step failed — no id on the error + if (knownId) { + const sandbox = await client.get(knownId); + console.log(sandbox.info().state); + } + throw error; +} +``` + + + + +```go +instance, err := client.Create(ctx, opts) +if err != nil { + // create may have succeeded before a later step failed — no id on the error + if knownID != "" { + existing, getErr := client.Get(ctx, knownID) + if getErr == nil { + fmt.Println(existing.Info().State) + } + } + return err +} +_ = instance +``` + + + + +Samples: [Examples](/docs/examples). + + + + + +`attach` does not verify existence. + + + + +```ts +try { + await client.create(request); +} catch (error) { + // attach builds a handle from an id only — it does not check Modal + if (knownId) { + const sandbox = await client.attach(knownId); + console.log(sandbox.id); + } + throw error; +} +``` + + + + +```go +instance, err := client.Create(ctx, opts) +if err != nil { + // Attach builds a handle from an id only — it does not check Modal + if knownID != "" { + existing, attachErr := client.Attach(ctx, knownID) + if attachErr == nil { + fmt.Println(existing.ID()) + } + } + return err +} +_ = instance +``` + + + + +Samples: [Examples](/docs/examples). -Examples: [Daytona](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/errors/handle-daytona-errors) · [Modal](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/errors/handle-modal-errors) · Go twins under `examples/go/`. + diff --git a/website/content/docs/examples.mdx b/website/content/docs/examples.mdx index 72c280b3..2197321e 100644 --- a/website/content/docs/examples.mdx +++ b/website/content/docs/examples.mdx @@ -1,74 +1,401 @@ --- title: Examples -description: One runnable project per operation. Clone, set .env, run. +description: Clone a sample project, set .env, and run one operation. --- -Each example is a small project under `examples////`. It loads its own `.env` and demonstrates one call. +Each sample is a small project that loads its own `.env` and demonstrates one call against a provider. Creation samples provision a real sandbox. Filesystem, process, and lifecycle samples need a sandbox id in `.env`. Error samples fail locally. -| Area | Runtime | -| ------------------------------------ | ----------------------------- | -| `configuration` | Provisions a real sandbox | -| `filesystem`, `process`, `lifecycle` | Uses `*_SANDBOX_ID` in `.env` | -| `errors` | Fails locally; no cloud work | +Destructive ops (stop, terminate, archive, delete, remove) can destroy the sandbox or path you configure. -Destructive ops (stop, terminate, archive, delete, remove) can destroy the sandbox or path you configure. Full catalog: [examples/README.md](https://github.com/sandbox-kit/kit/blob/main/examples/README.md). - -## Daytona +## Run -| Operation | TypeScript | Go | -| ------------- | ------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- | -| Create | [project](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-sandbox) | [project](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-sandbox) | -| Run command | [project](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-command) | [project](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-command) | -| Read file | [project](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/read-daytona-file) | [project](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/read-daytona-file) | -| From image | [project](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-from-image) | [project](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-from-image) | -| From snapshot | [project](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-from-snapshot) | [project](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-from-snapshot) | -| Policies | [project](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-policies) | [project](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-policies) | -| Get | [project](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/get-daytona-sandbox) | [project](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/get-daytona-sandbox) | -| Stop | [project](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/stop-daytona-sandbox) | [project](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/stop-daytona-sandbox) | -| Delete | [project](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/delete-daytona-sandbox) | [project](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/delete-daytona-sandbox) | -| Errors | [project](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/errors/handle-daytona-errors) | [project](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/errors/handle-daytona-errors) | +Skip `cp` if `.env` already exists. -Process variants (shell, cwd, env, timeout, exit): [typescript/daytona/process](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process) · [go/daytona/process](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process). + + -## Modal +Requires Node.js 20/22/24.15+ and npm 11.19.0. -| Operation | TypeScript | Go | -| ----------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | -| Create | [project](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-sandbox) | [project](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-sandbox) | -| Run command | [project](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-command) | [project](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-command) | -| Read file | [project](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/read-modal-file) | [project](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/read-modal-file) | -| Resources | [project](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-resources) | [project](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-resources) | -| Attach | [project](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/lifecycle/attach-modal-sandbox) | [project](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/lifecycle/attach-modal-sandbox) | -| Terminate | [project](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/lifecycle/terminate-modal-sandbox) | [project](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/lifecycle/terminate-modal-sandbox) | -| Errors | [project](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/errors/handle-modal-errors) | [project](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/errors/handle-modal-errors) | + -Process variants: [typescript/modal/process](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process) · [go/modal/process](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process). +```sh +git clone https://github.com/sandbox-kit/kit.git +cd kit/examples/typescript/daytona/configuration/create-daytona-sandbox +cp .env.example .env # set DAYTONA_API_KEY +npm install && npm run build && npm start +``` -## Run + -Requirements: Node.js 20/22/24.15+ (npm 11.19.0) or Go 1.26.0+. `` is `filesystem`, `process`, `configuration`, `lifecycle`, or `errors`. Skip `cp` if `.env` exists. - - - + ```sh git clone https://github.com/sandbox-kit/kit.git -cd kit/examples/typescript/// -cp .env.example .env +cd kit/examples/typescript/modal/configuration/create-modal-sandbox +cp .env.example .env # set MODAL_TOKEN_ID, MODAL_TOKEN_SECRET, MODAL_APP_NAME npm install && npm run build && npm start ``` + + +Requires Go 1.26.0+. + + + ```sh git clone https://github.com/sandbox-kit/kit.git -cd kit/examples/go/// -cp .env.example .env +cd kit/examples/go/daytona/configuration/create-daytona-sandbox +cp .env.example .env # set DAYTONA_API_KEY go run . ``` + + + + +```sh +git clone https://github.com/sandbox-kit/kit.git +cd kit/examples/go/modal/configuration/create-modal-sandbox +cp .env.example .env # set MODAL_TOKEN_ID, MODAL_TOKEN_SECRET, MODAL_APP_NAME +go run . +``` + + + + + + + + +## Catalog + +### Create + + + + +| Example | Project | +| ------- | ------- | +| Creation | [create-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-sandbox) | +| Snapshot | [create-daytona-from-snapshot](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-from-snapshot) | +| Image | [create-daytona-from-image](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-from-image) | +| Runtime | [create-daytona-with-runtime](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-runtime) | +| Ephemeral | [create-daytona-ephemeral](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-ephemeral) | +| Linked | [create-daytona-linked](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-linked) | +| Policies | [create-daytona-with-policies](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-policies) | +| Network | [create-daytona-with-network](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-network) | +| Labels | [create-daytona-with-labels](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-labels) | +| Secrets | [create-daytona-with-secrets](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-secrets) | +| KVM | [create-daytona-with-kvm](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-kvm) | +| TTL | [create-daytona-with-ttl](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-ttl) | + + + + +| Example | Project | +| ------- | ------- | +| Creation | [create-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-sandbox) | +| Snapshot | [create-daytona-from-snapshot](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-from-snapshot) | +| Image | [create-daytona-from-image](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-from-image) | +| Runtime | [create-daytona-with-runtime](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-runtime) | +| Ephemeral | [create-daytona-ephemeral](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-ephemeral) | +| Linked | [create-daytona-linked](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-linked) | +| Policies | [create-daytona-with-policies](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-policies) | +| Network | [create-daytona-with-network](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-network) | +| Labels | [create-daytona-with-labels](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-labels) | +| Secrets | [create-daytona-with-secrets](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-secrets) | +| KVM | [create-daytona-with-kvm](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-kvm) | +| TTL | [create-daytona-with-ttl](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-ttl) | + + + + +### Process + + + + +| Example | Project | +| ------- | ------- | +| Run command | [run-daytona-command](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-command) | +| Shell command | [run-daytona-shell-command](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-shell-command) | +| Run with cwd | [run-daytona-with-cwd](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-with-cwd) | +| Run with env | [run-daytona-with-env](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-with-env) | +| Run with timeout | [run-daytona-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-with-timeout) | +| Check exit | [run-daytona-check-exit](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-check-exit) | + + + + +| Example | Project | +| ------- | ------- | +| Run command | [run-daytona-command](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-command) | +| Shell command | [run-daytona-shell-command](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-shell-command) | +| Run with cwd | [run-daytona-with-cwd](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-with-cwd) | +| Run with env | [run-daytona-with-env](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-with-env) | +| Run with timeout | [run-daytona-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-with-timeout) | +| Check exit | [run-daytona-check-exit](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-check-exit) | + + + + +### Filesystem + + + + +| Example | Project | +| ------- | ------- | +| Read file | [read-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/read-daytona-file) | +| Write file | [write-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/write-daytona-file) | +| Copy in | [copy-file-into-daytona](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/copy-file-into-daytona) | +| Copy out | [copy-file-from-daytona](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/copy-file-from-daytona) | +| Directory | [make-daytona-directory](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/make-daytona-directory) | +| List | [list-daytona-directory](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/list-daytona-directory) | +| Stat | [stat-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/stat-daytona-file) | +| Remove | [remove-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/remove-daytona-file) | + + + + +| Example | Project | +| ------- | ------- | +| Read file | [read-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/read-daytona-file) | +| Write file | [write-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/write-daytona-file) | +| Copy in | [copy-file-into-daytona](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/copy-file-into-daytona) | +| Copy out | [copy-file-from-daytona](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/copy-file-from-daytona) | +| Directory | [make-daytona-directory](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/make-daytona-directory) | +| List | [list-daytona-directory](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/list-daytona-directory) | +| Stat | [stat-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/stat-daytona-file) | +| Remove | [remove-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/remove-daytona-file) | + + + + +### Lifecycle + + + + +| Example | Project | +| ------- | ------- | +| Get | [get-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/get-daytona-sandbox) | +| Refresh | [refresh-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/refresh-daytona-sandbox) | +| Start | [start-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/start-daytona-sandbox) | +| Start timeout | [start-daytona-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/start-daytona-with-timeout) | +| Stop | [stop-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/stop-daytona-sandbox) | +| Force stop | [force-stop-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/force-stop-daytona-sandbox) | +| Pause | [pause-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/pause-daytona-sandbox) | +| Archive | [archive-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/archive-daytona-sandbox) | +| Delete | [delete-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/delete-daytona-sandbox) | +| Delete request | [request-daytona-deletion](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/request-daytona-deletion) | +| Close handle | [close-daytona-handle](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/close-daytona-handle) | + + + + +| Example | Project | +| ------- | ------- | +| Get | [get-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/get-daytona-sandbox) | +| Refresh | [refresh-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/refresh-daytona-sandbox) | +| Start | [start-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/start-daytona-sandbox) | +| Start timeout | [start-daytona-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/start-daytona-with-timeout) | +| Stop | [stop-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/stop-daytona-sandbox) | +| Force stop | [force-stop-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/force-stop-daytona-sandbox) | +| Pause | [pause-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/pause-daytona-sandbox) | +| Archive | [archive-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/archive-daytona-sandbox) | +| Delete | [delete-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/delete-daytona-sandbox) | +| Delete request | [request-daytona-deletion](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/request-daytona-deletion) | +| Close handle | [close-daytona-handle](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/close-daytona-handle) | + + + + +### Errors + + + + +| Example | Project | +| ------- | ------- | +| Errors | [handle-daytona-errors](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/errors/handle-daytona-errors) | + + + + +| Example | Project | +| ------- | ------- | +| Errors | [handle-daytona-errors](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/errors/handle-daytona-errors) | + + + + + + + + +## Catalog + +### Create + + + + +| Example | Project | +| ------- | ------- | +| Creation | [create-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-sandbox) | +| Resources | [create-modal-with-resources](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-resources) | +| Runtime | [create-modal-with-runtime](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-runtime) | +| GVisor | [create-modal-gvisor](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-gvisor) | +| Linux VM | [create-modal-linux-vm](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-linux-vm) | +| Placement | [create-modal-with-placement](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-placement) | +| Labels | [create-modal-with-labels](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-labels) | +| Network | [create-modal-with-network](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-network) | +| Idle timeout | [create-modal-idle](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-idle) | +| Readiness | [create-modal-ready](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-ready) | +| TCP readiness | [create-modal-tcp-ready](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-tcp-ready) | +| Client timeout wait | [create-modal-client-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-client-timeout) | +| Ports | [create-modal-with-ports](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-ports) | +| Allowlists | [create-modal-with-allowlists](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-allowlists) | +| Secrets | [create-modal-with-secrets](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-secrets) | +| Verbose | [create-modal-verbose](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-verbose) | +| Identity | [create-modal-with-identity](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-identity) | + + + + +| Example | Project | +| ------- | ------- | +| Creation | [create-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-sandbox) | +| Resources | [create-modal-with-resources](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-resources) | +| Runtime | [create-modal-with-runtime](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-runtime) | +| GVisor | [create-modal-gvisor](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-gvisor) | +| Linux VM | [create-modal-linux-vm](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-linux-vm) | +| Placement | [create-modal-with-placement](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-placement) | +| Labels | [create-modal-with-labels](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-labels) | +| Network | [create-modal-with-network](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-network) | +| Idle timeout | [create-modal-idle](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-idle) | +| Readiness | [create-modal-ready](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-ready) | +| TCP readiness | [create-modal-tcp-ready](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-tcp-ready) | +| Client timeout wait | [create-modal-client-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-client-timeout) | +| Ports | [create-modal-with-ports](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-ports) | +| Allowlists | [create-modal-with-allowlists](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-allowlists) | +| Secrets | [create-modal-with-secrets](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-secrets) | +| Verbose | [create-modal-verbose](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-verbose) | +| Identity | [create-modal-with-identity](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-identity) | + + + + +### Process + + + + +| Example | Project | +| ------- | ------- | +| Run command | [run-modal-command](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-command) | +| Shell command | [run-modal-shell-command](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-shell-command) | +| Run with cwd | [run-modal-with-cwd](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-with-cwd) | +| Run with env | [run-modal-with-env](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-with-env) | +| Run with timeout | [run-modal-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-with-timeout) | +| Check exit | [run-modal-check-exit](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-check-exit) | + + + + +| Example | Project | +| ------- | ------- | +| Run command | [run-modal-command](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-command) | +| Shell command | [run-modal-shell-command](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-shell-command) | +| Run with cwd | [run-modal-with-cwd](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-with-cwd) | +| Run with env | [run-modal-with-env](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-with-env) | +| Run with timeout | [run-modal-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-with-timeout) | +| Check exit | [run-modal-check-exit](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-check-exit) | + + + + +### Filesystem + + + + +| Example | Project | +| ------- | ------- | +| Read file | [read-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/read-modal-file) | +| Write file | [write-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/write-modal-file) | +| Copy in | [copy-file-into-modal](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/copy-file-into-modal) | +| Copy out | [copy-file-from-modal](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/copy-file-from-modal) | +| Directory | [make-modal-directory](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/make-modal-directory) | +| List | [list-modal-directory](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/list-modal-directory) | +| Stat | [stat-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/stat-modal-file) | +| Remove | [remove-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/remove-modal-file) | + + + + +| Example | Project | +| ------- | ------- | +| Read file | [read-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/read-modal-file) | +| Write file | [write-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/write-modal-file) | +| Copy in | [copy-file-into-modal](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/copy-file-into-modal) | +| Copy out | [copy-file-from-modal](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/copy-file-from-modal) | +| Directory | [make-modal-directory](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/make-modal-directory) | +| List | [list-modal-directory](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/list-modal-directory) | +| Stat | [stat-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/stat-modal-file) | +| Remove | [remove-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/remove-modal-file) | + + + + +### Lifecycle + + + + +| Example | Project | +| ------- | ------- | +| Attach | [attach-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/lifecycle/attach-modal-sandbox) | +| Terminate | [terminate-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/lifecycle/terminate-modal-sandbox) | +| Terminate timeout | [terminate-modal-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/lifecycle/terminate-modal-with-timeout) | +| Termination request | [request-modal-termination](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/lifecycle/request-modal-termination) | +| Close handle | [close-modal-handle](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/lifecycle/close-modal-handle) | + + + + +| Example | Project | +| ------- | ------- | +| Attach | [attach-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/lifecycle/attach-modal-sandbox) | +| Terminate | [terminate-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/lifecycle/terminate-modal-sandbox) | +| Terminate timeout | [terminate-modal-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/lifecycle/terminate-modal-with-timeout) | +| Termination request | [request-modal-termination](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/lifecycle/request-modal-termination) | +| Close handle | [close-modal-handle](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/lifecycle/close-modal-handle) | + + + + +### Errors + + + + +| Example | Project | +| ------- | ------- | +| Errors | [handle-modal-errors](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/errors/handle-modal-errors) | + + + + +| Example | Project | +| ------- | ------- | +| Errors | [handle-modal-errors](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/errors/handle-modal-errors) | + -Daytona create needs `DAYTONA_API_KEY`. Modal create needs `MODAL_TOKEN_ID`, `MODAL_TOKEN_SECRET`, and `MODAL_APP_NAME`. + diff --git a/website/content/docs/filesystem.mdx b/website/content/docs/filesystem.mdx index 91bd8124..29fab26d 100644 --- a/website/content/docs/filesystem.mdx +++ b/website/content/docs/filesystem.mdx @@ -3,7 +3,7 @@ title: Filesystem description: Read, write, copy, mkdir, list, stat, and remove paths inside a sandbox. --- -Use `sandbox.filesystem` / `Filesystem()` on an open handle. Providers implement the same methods; provider-specific timeout rules are below. +Use the filesystem methods on an open handle. | Method | Purpose | | --------------------------------------- | ------------------------ | @@ -16,11 +16,7 @@ Use `sandbox.filesystem` / `Filesystem()` on an open handle. Providers implement | [`stat`](#read-metadata) | Path metadata | | [`remove`](#delete-a-file-or-directory) | Delete a path | -Prerequisite: [create](/docs/create) or [open](/docs/lifecycle) a sandbox. - -Calls on one handle run one at a time with lifecycle and process. Abort or -deadline rejects the TypeScript `await` (and ends the Go wait), but the handle -stays busy until that provider call settles. +You need a sandbox from [create](/docs/create) or [lifecycle](/docs/lifecycle). ## Paths and bytes @@ -29,58 +25,83 @@ stays busy until that provider call settles. | Sandbox | Absolute (`/tmp/note.txt`). Relative, blank, or NUL rejected | `path` | | Local (copy) | May be relative (`./note.txt`). Non-blank, no NUL | `local_path` | -`readFile` / `writeFile` transfer bytes—encode/decode text in your app. Copy methods use files on disk. +`readFile` and `writeFile` transfer bytes—encode and decode text in your app. Copy methods use files on disk. -## Timeouts + + + +```ts +const body = new TextEncoder().encode("hello\n"); +await sandbox.filesystem.writeFile("/tmp/note.txt", body); // absolute sandbox path +await sandbox.filesystem.copyFromLocal("./note.txt", "/tmp/note.txt"); // local may be relative +``` -| Language | Unit | -| ---------- | --------------- | -| TypeScript | milliseconds | -| Go | `time.Duration` | + + + +```go +err := instance.Filesystem().WriteFile(ctx, "/tmp/note.txt", []byte("hello\n"), nil) +err = instance.Filesystem().CopyFromLocal(ctx, "note.txt", "/tmp/note.txt", nil) // local may be relative +``` + + + + +## Timeouts Omit timeout → client deadline. Explicit `0` → no extra Kit deadline. -| Method / language | Behavior | -| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -| TS `readFile`, `writeFile`, `copyFromLocal`, `copyToLocal` | Whole seconds to Daytona. `2000` OK; `1500` rejected (`timeout`). Omit/zero → `0` (no transfer limit). Abort signal still applies when omit | -| TS `makeDirectory`, `listDirectory`, `stat`, `remove` | Abort signal. `1500` ms ends at 1.5s | -| All Go file calls | Context deadline. `1500 * time.Millisecond` ends at 1.5s | + + - +Timeouts are milliseconds. - +| Method | Behavior | +| ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| `readFile`, `writeFile`, `copyFromLocal`, `copyToLocal` | Whole seconds to Daytona. `2000` OK; `1500` rejected (`timeout`). Omit/zero → `0` (no transfer limit). Abort signal still applies when omit | +| `makeDirectory`, `listDirectory`, `stat`, `remove` | Abort signal. `1500` ms ends at 1.5s | -| Method / language | Behavior | -| ----------------------------------------------------- | -------------------------------------------------------- | -| TS transfer and directory ops | Abort signal. `1500` ms ends at 1.5s | -| All Go file calls | Context deadline. `1500 * time.Millisecond` ends at 1.5s | +```ts +await sandbox.filesystem.readFile("/tmp/note.txt", { timeout: 2_000 }); +await sandbox.filesystem.listDirectory("/tmp", { timeout: 1_500 }); +``` + + + + +Timeouts use `time.Duration` via `sandbox.Duration`. Every file call honors the context deadline. `1500 * time.Millisecond` ends at 1.5s. + +```go +data, err := instance.Filesystem().ReadFile(ctx, "/tmp/note.txt", &sandbox.FileReadOptions{ + Timeout: sandbox.Duration(1500 * time.Millisecond), +}) +``` + + + + + +Timeouts are milliseconds. Transfer and directory ops use the abort signal. `1500` ms ends at 1.5s. + ```ts -await sandbox.filesystem.readFile("/tmp/note.txt", { timeout: 2_000 }); +await sandbox.filesystem.readFile("/tmp/note.txt", { timeout: 1_500 }); await sandbox.filesystem.listDirectory("/tmp", { timeout: 1_500 }); ``` - -`readFile` with `1500` is rejected on Daytona TypeScript. Use a whole-second value such as `2000`. - - -```go -import ( - "time" - - "github.com/sandbox-kit/kit/sdks/go/sandbox" -) +Timeouts use `time.Duration` via `sandbox.Duration`. Every file call honors the context deadline. `1500 * time.Millisecond` ends at 1.5s. +```go data, err := instance.Filesystem().ReadFile(ctx, "/tmp/note.txt", &sandbox.FileReadOptions{ Timeout: sandbox.Duration(1500 * time.Millisecond), }) @@ -89,11 +110,11 @@ data, err := instance.Filesystem().ReadFile(ctx, "/tmp/note.txt", &sandbox.FileR -Calls on one handle are serialized with lifecycle and process. Snippets below assume an open `sandbox` / `instance`. See [Examples](/docs/examples). + ## Read a file -`readFile` returns the bytes of one file. A missing file comes back as not found. A directory path fails at the provider. +Returns the bytes of one file. A missing file is not found. A directory path fails at the provider. @@ -120,17 +141,9 @@ fmt.Printf("%s\n", data) - -Examples: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/read-daytona-file) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/read-daytona-file) - - - -Examples: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/read-modal-file) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/read-modal-file) - - ## Write a file -`writeFile` replaces the file and creates missing parent directories. An existing file at that path is overwritten. +Replaces the file and creates missing parent directories. An existing file is overwritten. @@ -144,24 +157,15 @@ await sandbox.filesystem.writeFile("/tmp/kit-files/note.txt", body); ```go -body := []byte("hello\n") -err := instance.Filesystem().WriteFile(ctx, "/tmp/kit-files/note.txt", body, nil) +err := instance.Filesystem().WriteFile(ctx, "/tmp/kit-files/note.txt", []byte("hello\n"), nil) ``` - -Examples: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/write-daytona-file) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/write-daytona-file) - - - -Examples: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/write-modal-file) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/write-modal-file) - - ## Copy a file in -`copyFromLocal` reads a file on your machine and writes it in the sandbox. The local path is the first argument. The remote path is absolute. An existing remote file is replaced, and missing parent directories of that path are created. A missing local file is not found. The error field is `local_path`. A local directory is an invalid argument with the same field. +Reads a file on your machine and writes it in the sandbox. Local path first; remote path absolute. Replaces an existing remote file and creates missing parents. A missing local file or a local directory fails with field `local_path`. @@ -180,17 +184,9 @@ err := instance.Filesystem().CopyFromLocal(ctx, "note.txt", "/tmp/note.txt", nil - -Examples: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/copy-file-into-daytona) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/copy-file-into-daytona) - - - -Examples: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/copy-file-into-modal) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/copy-file-into-modal) - - ## Copy a file out -`copyToLocal` copies a sandbox file onto your disk. The remote path comes first. An existing local file is replaced. A missing local parent directory is created. A local directory is an invalid argument, and the field is `local_path`. +Copies a sandbox file onto your disk. Remote path first. Replaces an existing local file and creates a missing local parent. A local directory fails with field `local_path`. @@ -209,24 +205,18 @@ err := instance.Filesystem().CopyToLocal(ctx, "/tmp/note.txt", "note.txt", nil) - -Examples: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/copy-file-from-daytona) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/copy-file-from-daytona) - - - -Examples: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/copy-file-from-modal) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/copy-file-from-modal) - - ## Create a directory -`parents` defaults to true, so the call creates missing parents. +`parents` defaults to true. -Daytona returns an error when the directory already exists. Daytona rejects `parents: false` before the call (field `parents`). + Daytona errors if the directory already exists, and rejects `parents: false` + before the call (field `parents`). -Modal accepts a directory that already exists. With `parents: false`, Modal requires the parent and errors if the new directory is already there. + Modal accepts a directory that already exists. With `parents: false`, the + parent must exist and the new directory must not. @@ -268,17 +258,22 @@ err = instance.Filesystem().MakeDirectory(ctx, "/tmp/kit-files/nested", &sandbox - -Examples: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/make-daytona-directory) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/make-daytona-directory) - +## List a directory - -Examples: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/make-modal-directory) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/make-modal-directory) - +Returns entries in that one directory—no recursion. `size` is a byte count. -## List a directory + + + +`size` is a `bigint`. + + + -`listDirectory` returns the entries in that one directory. It does not walk into subdirectories. `size` is a byte count. In TypeScript it is a `bigint`. +`size` is an integer byte count on the entry. + + + @@ -306,18 +301,18 @@ for _, entry := range entries { +## Read metadata + +`stat` returns one path. `mode` is an octal string when supplied (`0644`). `permissions`, `owner`, `group`, and `modifiedAt` appear when the provider sends them. + -Examples: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/list-daytona-directory) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/list-daytona-directory) + A symlink path is reported as a file or a directory. -Examples: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/list-modal-directory) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/list-modal-directory) + A symlink result describes the symlink when Modal reports one. -## Read metadata - -`stat` returns one path. A symlink result describes the symlink. Modal can report a symlink. Daytona reports a file or a directory. `mode` is an octal string when the provider supplies one, such as `0644`. `permissions`, `owner`, and `group` are set when the provider supplies them. `modifiedAt` is set when the provider supplies a time. - @@ -342,17 +337,9 @@ fmt.Println(info.GetType(), info.GetSize(), info.GetMode()) - -Examples: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/stat-daytona-file) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/stat-daytona-file) - - - -Examples: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/stat-modal-file) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/stat-modal-file) - - ## Delete a file or directory -`remove` deletes a file, or an empty directory. Set `recursive` to delete a directory and its contents. A directory that still has entries fails when you leave the flag unset. A missing path comes back as not found. +Deletes a file or an empty directory. Set `recursive` to delete a directory and its contents. A non-empty directory fails without the flag. A missing path is not found. @@ -382,10 +369,6 @@ if err := files.Remove(ctx, "/tmp/kit-files", &sandbox.RemoveOptions{ - -Examples: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/remove-daytona-file) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/remove-daytona-file) - +## Samples - -Examples: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/remove-modal-file) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/remove-modal-file) - +Runnable projects: [Examples](/docs/examples). diff --git a/website/content/docs/index.mdx b/website/content/docs/index.mdx index 802e54c5..4605af12 100644 --- a/website/content/docs/index.mdx +++ b/website/content/docs/index.mdx @@ -3,18 +3,24 @@ title: Quickstart description: Install Sandbox Kit, create a sandbox, run a command, and write a file. --- -Sandbox Kit is a lightweight TypeScript and Go SDK for cloud sandboxes. The core package defines the client; providers plug in as separate packages. Install both, construct a client, then create or open sandboxes. +Sandbox Kit is an SDK for cloud sandboxes. Install the core package and a provider, create a sandbox, then run commands and read files through the same client. -| Requirement | Version | -| ----------- | ------------------------- | -| TypeScript | Node.js 20, 22, or 24.15+ | -| Go | Go 1.26.0+ | +Use the language tabs and the provider control to switch snippets. Your choices stick in the browser. -Language tabs and the Daytona / Modal menu keep your picks in the browser. The menu switches install snippets, create samples, and provider notes. + + -## 1. Install +Requires Node.js 20, 22, or 24.15+. -Install the core package and a provider. + + + +Requires Go 1.26.0+. + + + + +## 1. Install @@ -61,10 +67,10 @@ go get github.com/sandbox-kit/kit/sdks/go/providers/modal@latest ## 2. Create a sandbox -Set `DAYTONA_API_KEY`, then run: +Set `DAYTONA_API_KEY`, then: - Set a Modal token pair and app name (see [Modal](/docs/modal)), then run: + Set a Modal token pair and app name ([Modal](/docs/modal)), then: @@ -210,7 +216,10 @@ func main() { -Provider setup details: [Daytona](/docs/daytona) · [Modal](/docs/modal). + + Provider setup: [Daytona](/docs/daytona). + +Provider setup: [Modal](/docs/modal). ## 3. Run a command @@ -248,7 +257,7 @@ fmt.Println(result.GetExitCode(), string(result.GetStdout())) -A non-zero exit code is not an SDK error. Check `exitCode` / `exit_code` yourself. Details: [Run a command](/docs/process). +A non-zero exit code is not an SDK error—check `exitCode` yourself. More options: [Run a command](/docs/process). ## 4. Write a file @@ -279,20 +288,20 @@ err = instance.Filesystem().WriteFile( -Paths inside the sandbox are absolute. Details: [Filesystem](/docs/filesystem). +Sandbox paths are absolute. More: [Filesystem](/docs/filesystem). - `client.close()` / `Client.Close` and handle `close` release local resources - only. The cloud sandbox keeps running until you stop, terminate, archive, - delete, or a lifetime policy fires. See [Concepts](/docs/concepts). + `client.close()` and handle `close` only release local resources. The cloud + sandbox keeps running until you stop, terminate, archive, delete, or a + lifetime policy ends it. See [Concepts](/docs/concepts). ## Next -| Task | Page | -| ----------------------------------- | ------------------------------------ | -| Client, handle, and close semantics | [Concepts](/docs/concepts) | -| Daytona setup | [Daytona](/docs/daytona) | -| Modal setup | [Modal](/docs/modal) | -| Auth, timeout, region, scope | [Configuration](/docs/configuration) | -| Runnable projects | [Examples](/docs/examples) | +| | | +| ------------------------ | ------------------------------------ | +| How the client works | [Concepts](/docs/concepts) | +| Daytona setup | [Daytona](/docs/daytona) | +| Modal setup | [Modal](/docs/modal) | +| Auth, region, timeouts | [Configuration](/docs/configuration) | +| Runnable sample projects | [Examples](/docs/examples) | diff --git a/website/content/docs/lifecycle.mdx b/website/content/docs/lifecycle.mdx index 79af6d54..c4f2f35c 100644 --- a/website/content/docs/lifecycle.mdx +++ b/website/content/docs/lifecycle.mdx @@ -3,64 +3,64 @@ title: Lifecycle description: get, attach, start, stop, pause, archive, delete, terminate, and close. --- -Operate on a handle from `create`, or open one by id. Switch Daytona or Modal above for open, destroy, and capability notes. +Operate on a handle from `create`, or open one by id. Unsupported ops fail before the provider call. -| Operation | Daytona | Modal | -| ------------------------------ | ------------------------------------------ | ------------------------------------------------- | -| Open existing | [`get`](#open-a-sandbox) (provider lookup) | [`attach`](#open-a-sandbox) (id only, no lookup) | -| start / stop / pause / archive | [Supported](#stop-start-pause-and-archive) | Rejected in Kit | -| Destroy | [`delete`](#delete) | [`terminate`](#terminate) or create-time lifetime | -| Local disconnect | [`close`](#close-the-client) | [`close`](#close-the-client) | + + -Check support with `supports` / `Supports` (`LifecycleCapability*` in Go). Unsupported ops fail before the provider call. Daytona may still reject a supported op for a given sandbox. +Check support with `supports`. -Calls on one handle run one at a time with filesystem and process. Abort or -deadline rejects the TypeScript `await` (and ends the Go wait), but the handle -stays busy until that provider call settles. + + -Snippets assume a constructed `client` ([Daytona](/docs/daytona) / [Modal](/docs/modal)). +Check support with `Supports`. -## Open a sandbox + + -`get` loads a sandbox that already exists. `refresh` loads it again. `Attach` is not available. +| Operation | Support | +| ------------------------------ | ------------------------------------------ | +| Open existing | [`get`](#open-a-sandbox) (provider lookup) | +| start / stop / pause / archive | [Supported](#stop-start-pause-and-archive) | +| Destroy | [`delete`](#delete) | +| Local disconnect | [`close`](#close-the-client) | + +Daytona may still reject a supported op for a given sandbox. Snippets assume a constructed client — [Daytona](/docs/daytona). -`attach` builds a handle from an id. It does not ask Modal whether that sandbox exists. Modal has no `get` and no `refresh`. +| Operation | Support | +| ---------------- | ------------------------------------------------- | +| Open existing | [`attach`](#open-a-sandbox) (id only) | +| Destroy | [`terminate`](#terminate) or create-time lifetime | +| Local disconnect | [`close`](#close-the-client) | + +`start`, `stop`, `pause`, `archive`, and `delete` are rejected in Kit. Snippets assume a constructed client — [Modal](/docs/modal). - - +## Open a sandbox +`get` loads a sandbox that already exists. `refresh` loads it again. `attach` is not available. + + + + ```ts const sandbox = await client.get(process.env.DAYTONA_SANDBOX_ID!); const info = await sandbox.refresh(); console.log(sandbox.id, info.state); ``` - - - - -```ts -const sandbox = await client.attach(process.env.MODAL_SANDBOX_ID!); -console.log(sandbox.id); -``` - - - - - ```go import "os" @@ -73,10 +73,26 @@ if err := instance.Refresh(ctx); err != nil { } ``` + + + +`attach` builds a handle from an id. It does not ask Modal whether that sandbox exists. `get` and `refresh` are not available. + + + + +```ts +const sandbox = await client.attach(process.env.MODAL_SANDBOX_ID!); +console.log(sandbox.id); +``` + + + + ```go import "os" @@ -86,16 +102,16 @@ if err != nil { } ``` - - -## Stop, start, pause, and archive + -These four calls are Daytona calls. `stop` asks Daytona to stop the sandbox. The sandbox stays available to start again. `start` brings a stopped or archived sandbox back. `pause` keeps memory and stops the sandbox. `archive` moves a retained sandbox into archive storage. +## Stop, start, pause, and archive + +`stop` leaves the sandbox available to start again. `start` brings a stopped or archived sandbox back. `pause` keeps memory. `archive` moves a retained sandbox into archive storage. @@ -113,7 +129,7 @@ const info = await sandbox.stop({ timeout: 60_000 }); console.log(sandbox.id, info.state); ``` -`timeout` is milliseconds. Pass `force: true` to request an immediate stop. Check `supports` the same way before `start`, `pause`, or `archive`. +`timeout` is milliseconds. Pass `force: true` for an immediate stop. Check `supports` the same way before `start`, `pause`, or `archive`. @@ -141,25 +157,19 @@ if err := instance.Stop(ctx, &sandbox.StopOptions{ } ``` -`Start`, `Pause`, and `Archive` take the same kind of options. Check `Supports` before each one. +`Start`, `Pause`, and `Archive` take the same kind of options. -Daytona decides whether that sandbox can pause, archive, or stop. An ephemeral sandbox can still be removed by the lifetime you set at [create](/docs/create) time. +Daytona decides whether that sandbox can pause, archive, or stop. An ephemeral sandbox can still end via the lifetime you set at [create](/docs/create). - - -Modal rejects `stop`, `start`, `pause`, and `archive` in Kit. Use [terminate](#terminate) or create-time lifetime policies instead. - - + ## Delete - - `delete` removes a Daytona sandbox. @@ -199,15 +209,9 @@ if err := instance.Delete(ctx, &sandbox.DeleteOptions{ -Modal rejects `delete`. Use [terminate](#terminate) instead. - - - ## Terminate - - -`terminate` finishes a Modal sandbox. It is not a stop, and it is not a delete. A maximum lifetime or an idle timeout set at [create](/docs/create) time also ends the sandbox. +`terminate` finishes a Modal sandbox. A maximum lifetime or idle timeout set at [create](/docs/create) also ends it. @@ -225,7 +229,7 @@ const exit = await sandbox.terminate({ wait: true, timeout: 60_000 }); console.log(sandbox.id, exit.exitCode); ``` -`wait: true` polls until the sandbox exits or the timeout fires. The timeout is how long the client waits. Modal does not receive that duration as its own terminate timeout. +`wait: true` polls until the sandbox exits or the timeout fires. The timeout is how long the client waits—Modal does not receive it as its own terminate timeout. @@ -261,12 +265,6 @@ fmt.Println(exit.GetExitCode()) - - -Daytona rejects `terminate`. Use [delete](#delete) or create-time lifetime policies instead. - - - ## Close the client @@ -295,3 +293,51 @@ defer client.Close(context.Background()) ## Read the state `info.state` is the portable state; the provider's native string sits beside it. After a lifecycle call, refresh or re-fetch before assuming the sandbox is stopped or gone. A failed call can still mean the provider already changed state. See [Errors](/docs/errors). + + + + +```ts +const info = sandbox.info(); +console.log(info.id); +console.log(info.state); // portable lifecycle state +console.log(info.providerState); // provider's native string when set +console.log(info.terminal); +``` + + + +```ts +const refreshed = await sandbox.refresh(); +console.log(refreshed.state); +console.log(refreshed.providerState); +``` + + + + + + +```go +info := instance.Info() +fmt.Println(info.Id) +fmt.Println(info.State) // portable lifecycle state +fmt.Println(info.GetProviderState()) // provider's native string when set +fmt.Println(info.GetTerminal()) +``` + + + +```go +if err := instance.Refresh(ctx); err != nil { + return err +} +info = instance.Info() +fmt.Println(info.State) +fmt.Println(info.GetProviderState()) +``` + + + + + diff --git a/website/content/docs/modal.mdx b/website/content/docs/modal.mdx index 0f9ca39c..f94e02cf 100644 --- a/website/content/docs/modal.mdx +++ b/website/content/docs/modal.mdx @@ -3,7 +3,7 @@ title: Modal description: Install, authenticate, and create a Modal sandbox from a registry image. --- -Provider package for Modal sandboxes. Create requires a registry image, a token pair, and an existing Modal app. Native SDK: Modal v0.11.1. +Use Modal when you create from a registry image, attach by id, and terminate (or rely on create-time lifetime). ## Install @@ -27,7 +27,7 @@ go get github.com/sandbox-kit/kit/sdks/go/providers/modal@latest ## Create -Set `MODAL_TOKEN_ID`, `MODAL_TOKEN_SECRET`, and `MODAL_APP_NAME`. Default environment: `main`. +Set `MODAL_TOKEN_ID`, `MODAL_TOKEN_SECRET`, and `MODAL_APP_NAME`. Default environment is `main`. Create needs a registry image. @@ -119,37 +119,141 @@ func main() { -Omit `auth` to use Modal SDK / profile credentials. `scope.appName` remains required. `endpoint` is rejected. Closing the client does not terminate the sandbox. +Omit `auth` to use Modal SDK / profile credentials. `scope.appName` is still required. `endpoint` is rejected. Closing the client does not terminate the sandbox. ## Configuration -| Setting | Notes | -| ------------- | -------------------------------------------------- | -| Token pair | `auth.tokenPair` / `TokenPair` | -| OAuth refresh | Supported with client id and one secret or JWT key | -| App | `scope.appName` — required | -| Environment | `scope.environment` (often `main`) | -| Region | `region` — default placement preference | -| Endpoint | Unsupported | + + + +| Setting | Notes | +| ------------- | ------------------------------------ | +| Token pair | `auth.tokenPair` | +| OAuth refresh | Client id plus one secret or JWT key | +| App | `scope.appName` — required | +| Environment | `scope.environment` (often `main`) | +| Region | `region` — default placement | +| Endpoint | Unsupported | + +```ts +await using client = new Client({ + provider: modal(), + auth: { + tokenPair: { + id: process.env.MODAL_TOKEN_ID!, + secret: process.env.MODAL_TOKEN_SECRET!, + }, + }, + scope: { + appName: process.env.MODAL_APP_NAME!, // required + environment: "main", + }, + region: process.env.MODAL_REGION, // optional default placement + timeout: 120_000, +}); +``` + +OAuth refresh auth (exactly one of `clientSecret` or `jwtKey`): + +```ts +await using client = new Client({ + provider: modal(), + auth: { + oauthRefresh: { + refreshToken: process.env.MODAL_REFRESH_TOKEN!, + clientId: process.env.MODAL_CLIENT_ID!, + clientSecret: process.env.MODAL_CLIENT_SECRET!, + }, + }, + scope: { + appName: process.env.MODAL_APP_NAME!, + environment: "main", + }, + timeout: 120_000, +}); +``` + + + + +| Setting | Notes | +| ------------- | ------------------------------------ | +| Token pair | `TokenPair` | +| OAuth refresh | Client id plus one secret or JWT key | +| App | `Scope.AppName` — required | +| Environment | `Scope.Environment` (often `main`) | +| Region | `Config.Region` — default placement | +| Endpoint | Unsupported | + +```go +config := &sandbox.Config{ + Auth: &sandbox.AuthConfig{Credentials: &sandbox.TokenPair{ + TokenPair: &sandbox.TokenPairCredentials{ + Id: os.Getenv("MODAL_TOKEN_ID"), + Secret: os.Getenv("MODAL_TOKEN_SECRET"), + }, + }}, + Scope: &sandbox.Scope{ + AppName: sandbox.Value(os.Getenv("MODAL_APP_NAME")), // required + Environment: sandbox.Value("main"), + }, + Region: sandbox.Value(os.Getenv("MODAL_REGION")), // optional + Timeout: sandbox.Duration(2 * time.Minute), +} +client, err := sandbox.NewClient(modal.New(), config) +``` + +OAuth refresh auth (exactly one of `ClientSecret` or `JwtKey`): + +```go +config := &sandbox.Config{ + Auth: &sandbox.AuthConfig{Credentials: &sandbox.OAuthRefresh{ + OauthRefresh: &sandbox.OAuthCredentials{ + RefreshToken: os.Getenv("MODAL_REFRESH_TOKEN"), + ClientId: os.Getenv("MODAL_CLIENT_ID"), + ClientSecret: sandbox.Value(os.Getenv("MODAL_CLIENT_SECRET")), + }, + }}, + Scope: &sandbox.Scope{ + AppName: sandbox.Value(os.Getenv("MODAL_APP_NAME")), + Environment: sandbox.Value("main"), + }, + Timeout: sandbox.Duration(2 * time.Minute), +} +client, err := sandbox.NewClient(modal.New(), config) +``` + + + Full rules: [Configuration](/docs/configuration). -## Operations +## What works -| Area | Support | -| --------- | ----------------------------------------------------------------------------------------- | -| Create | Registry image; runtime, isolation, resources, network, ports, secrets, readiness, labels | -| Open | `attach` (id only). `get` / `refresh` unsupported | -| Lifecycle | `terminate`, `close`. Start/stop/pause/archive/delete unsupported | -| Files | Full filesystem API — [Filesystem](/docs/filesystem) | -| Process | `run` — [Run a command](/docs/process) | +| Area | Notes | +| --------- | ------------------------------------------------------------------------------ | +| Create | Registry image; runtime, resources, network, ports, secrets, readiness, labels | +| Open | `attach` by id. `get` and `refresh` unsupported | +| Lifecycle | `terminate`. Start, stop, pause, archive, and delete are unsupported | +| Files | Filesystem methods — [Filesystem](/docs/filesystem) | +| Process | `run` — [Run a command](/docs/process) | -When set, resources require ≥ 0.125 CPU and ≥ 128 MiB. Disk cannot be raised at create. +When you set resources: at least 0.125 CPU and 128 MiB. Disk cannot be raised at create. ## Related -| Topic | Link | -| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Resources, idle, ports | [Create](/docs/create#modal) | -| attach / terminate | [Lifecycle](/docs/lifecycle) | -| Example project | [create-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-sandbox) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-sandbox) | +- Resources, idle, ports — [Create](/docs/create) +- attach / terminate — [Lifecycle](/docs/lifecycle) + + + + +Sample: [create-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-sandbox) + + + + +Sample: [create-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-sandbox) + + + diff --git a/website/content/docs/process.mdx b/website/content/docs/process.mdx index bf8a26f2..0f338e95 100644 --- a/website/content/docs/process.mdx +++ b/website/content/docs/process.mdx @@ -3,13 +3,20 @@ title: Run a command description: Blocking Process.run — argv or shell, cwd, env, timeouts, and exit codes. --- -Use `sandbox.process.run` (TypeScript) or `Process().Run` (Go) on an open handle. Providers share the same options and result shape; switch Daytona or Modal above for mapping and edge cases. +Run a command on an open handle. You need a sandbox from [create](/docs/create) or [lifecycle](/docs/lifecycle). -| Method | Returns | -| ------------- | ---------------------------------------------------------------------- | -| `run` / `Run` | `exitCode` / `exit_code`, `stdout`, `stderr` when the command finishes | + + + +Call `sandbox.process.run`. The result includes `exitCode`, `stdout`, and `stderr`. + + + -Prerequisite: create or open a sandbox ([Daytona](/docs/daytona), [Modal](/docs/modal), or [Lifecycle](/docs/lifecycle)). +Call `Process().Run`. The result includes `exit_code`, `stdout`, and `stderr`. + + + ## Options @@ -20,13 +27,50 @@ Set **exactly one** of: | `argv` | Program + arguments | `["echo", "hello"]` | | `shell` | One shell command string | `"echo hello"` | -| Field | Rules | -| ------------------ | ------------------------------------------------------------------------------------- | -| Both or neither | Rejected. Field: `argv` | -| Blank `shell` | Rejected after trim (whitespace-only too). Field: `shell` | -| `workingDirectory` | Absolute when set (`/workspace`). Relative, blank, or NUL → field `working_directory` | -| `environment` | For this call only. Omit → provider default. Empty map → add no variables | -| `timeout` | TypeScript: ms. Go: `time.Duration`. See [Timeouts and cancel](#timeouts-and-cancel) | +| Field | Rules | +| ------------------ | ------------------------------------------------------------------------- | +| Both or neither | Rejected. Field: `argv` | +| Blank `shell` | Rejected after trim. Field: `shell` | +| `workingDirectory` | Absolute when set. Relative, blank, or NUL → field `working_directory` | +| `environment` | For this call only. Omit → provider default. Empty map → add no variables | +| `timeout` | See [Timeouts](#timeouts-and-cancel) | + + + + +```ts +const result = await sandbox.process.run({ + argv: ["echo", "hello"], // or shell: 'echo "hello"' — not both + workingDirectory: "/tmp", // absolute when set + environment: { KIT_DEMO: "from-kit" }, + timeout: 5_000, // milliseconds; whole seconds required + signal: AbortSignal.timeout(5_000), +}); +console.log(result.exitCode); +console.log(new TextDecoder().decode(result.stdout)); +console.log(new TextDecoder().decode(result.stderr)); +``` + + + + +```go +result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ + Argv: []string{"echo", "hello"}, // or Shell — not both + WorkingDirectory: sandbox.Value("/tmp"), // absolute when set + Environment: map[string]string{"KIT_DEMO": "from-kit"}, + Timeout: sandbox.Duration(5 * time.Second), // whole seconds +}) +if err != nil { + return err +} +fmt.Println(result.GetExitCode()) +fmt.Println(string(result.GetStdout())) +fmt.Println(string(result.GetStderr())) +``` + + + ### How providers run it @@ -39,36 +83,81 @@ Set **exactly one** of: | omit / zero timeout | no command limit (`0`, so Daytona does not use its 10s default) | | fractional (`1500` ms) | rejected (`timeout`) | +Daytona returns stdout only; `stderr` is empty. stdout may include merged streams. + + + + +```ts +const result = await sandbox.process.run({ + argv: ["echo", "hello"], // sent as a POSIX-quoted shell string +}); +console.log(result.exitCode); +console.log(new TextDecoder().decode(result.stdout)); +console.log(result.stderr.byteLength); // 0 — Daytona returns stdout only +``` + + + + +```go +result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ + Argv: []string{"echo", "hello"}, // sent as a POSIX-quoted shell string +}) +if err != nil { + return err +} +fmt.Println(result.GetExitCode()) +fmt.Println(string(result.GetStdout())) +fmt.Println(len(result.GetStderr())) // 0 — Daytona returns stdout only +``` + + + + -| You pass | On Modal | -| ---------------------- | --------------------------------------------------------------------- | -| `argv` | argument list as-is | -| `shell` | `bash -c` | -| omit / zero timeout | no command limit (TypeScript omits `timeoutMs`; Go uses `Timeout: 0`) | -| fractional (`1500` ms) | rejected (`timeout`) | +| You pass | On Modal | +| ---------------------- | -------------------- | +| `argv` | argument list as-is | +| `shell` | `bash -c` | +| omit / zero timeout | no command limit | +| fractional (`1500` ms) | rejected (`timeout`) | - +Modal returns both `stdout` and `stderr`. -### Result + + -| Field | Notes | -| ------------------------ | -------------------------------- | -| `exitCode` / `exit_code` | Non-zero is **not** an SDK error | -| `stdout` | Bytes | -| `stderr` | See provider note below | +```ts +const result = await sandbox.process.run({ + argv: ["echo", "hello"], // argument list as-is +}); +console.log( + result.exitCode, + new TextDecoder().decode(result.stdout), + new TextDecoder().decode(result.stderr), +); +``` - - Daytona returns stdout only; `stderr` is empty (Go: non-nil empty slice). - stdout may include merged streams. - + + -Modal returns both `stdout` and `stderr`. +```go +result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ + Argv: []string{"echo", "hello"}, // argument list as-is +}) +fmt.Println(result.GetExitCode(), string(result.GetStdout()), string(result.GetStderr())) +``` -Calls on one handle run one at a time with lifecycle and filesystem. A second -handle for the same sandbox does not wait. + + + + + +A non-zero exit code is **not** an SDK error. ## Timeouts and cancel @@ -78,20 +167,43 @@ handle for the same sandbox does not wait. | `0` | No extra client deadline for this call | | Positive value | Cap this call; must be whole seconds (`5000` ok, `1500` rejected) | -Omit or zero also means no separate provider command limit (see the mapping -table above). +Omit or zero also means no separate provider command limit. - - Cancel the Go context to end the wait. In TypeScript, abort rejects the - `await`; the remote command may keep running. Either way the handle stays busy - until that provider call settles. - + + - - Cancel the Go context to end the wait. In TypeScript, abort rejects the - `await`; the remote command may keep running. Either way the handle stays busy - until that provider call settles. - +Abort rejects the `await`; the remote command may keep running. The handle stays busy until that provider call settles. + +```ts +const ac = new AbortController(); +const pending = sandbox.process.run({ + argv: ["sleep", "30"], + timeout: 0, // no Kit deadline; still abortable + signal: ac.signal, +}); +ac.abort(); +await pending.catch(() => {}); +``` + + + + +Cancel the context to end the wait. The handle stays busy until that provider call settles. + +```go +ctx, cancel := context.WithCancel(ctx) +defer cancel() + +result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ + Argv: []string{"sleep", "30"}, + Timeout: sandbox.Duration(0), // no Kit deadline; still cancelable via ctx +}) +_ = result +_ = err +``` + + + ## argv @@ -130,20 +242,6 @@ fmt.Printf("exit=%d stdout=%q\n", result.GetExitCode(), string(result.GetStdout( - - Examples: - [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-command) - · - [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-command) - - - - Examples: - [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-command) - · - [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-command) - - ## shell Do not set `argv` on the same call. @@ -155,45 +253,33 @@ Do not set `argv` on the same call. const result = await sandbox.process.run({ shell: 'echo "hello from shell"', }); +console.log(result.exitCode); +console.log(new TextDecoder().decode(result.stdout)); ``` - - Daytona runs the string as shell. On Modal the same call uses `bash -c`. - - - - Modal runs this as `bash -c`. On Daytona the same call uses the shell string - as-is. - - ```go -import "github.com/sandbox-kit/kit/sdks/go/sandbox" +import ( + "fmt" + + "github.com/sandbox-kit/kit/sdks/go/sandbox" +) result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ Shell: sandbox.Value(`echo "hello from shell"`), }) +if err != nil { + return err +} +fmt.Println(result.GetExitCode()) +fmt.Println(string(result.GetStdout())) ``` - - Examples: - [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-shell-command) - · - [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-shell-command) - - - - Examples: - [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-shell-command) - · - [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-shell-command) - - ## Working directory and environment Applies to that call only. @@ -207,79 +293,33 @@ const result = await sandbox.process.run({ workingDirectory: "/tmp", environment: { KIT_DEMO: "from-kit" }, }); +console.log(new TextDecoder().decode(result.stdout)); ``` ```go -import "github.com/sandbox-kit/kit/sdks/go/sandbox" +import ( + "fmt" + + "github.com/sandbox-kit/kit/sdks/go/sandbox" +) result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ Argv: []string{"printenv", "KIT_DEMO"}, WorkingDirectory: sandbox.Value("/tmp"), Environment: map[string]string{"KIT_DEMO": "from-kit"}, }) +if err != nil { + return err +} +fmt.Println(string(result.GetStdout())) ``` - -cwd: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-with-cwd) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-with-cwd) - -env: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-with-env) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-with-env) - - - - -cwd: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-with-cwd) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-with-cwd) - -env: [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-with-env) · [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-with-env) - - - -## Timeout - -Cap one call with a whole-second `timeout`. Fractional values are rejected (`timeout`). - - - - -```ts -const result = await sandbox.process.run({ - argv: ["echo", "hello with timeout"], - timeout: 5_000, -}); -``` - - - - -```go -result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ - Argv: []string{"echo", "hello with timeout"}, - Timeout: sandbox.Duration(5 * time.Second), -}) -``` - - - - - - Examples: - [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-with-timeout) - · - [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-with-timeout) - - - - Examples: - [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-with-timeout) - · - [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-with-timeout) - - ## Non-zero exit code Transport and validation failures still return errors. A finished command with exit `7` does not. @@ -318,24 +358,8 @@ if result.GetExitCode() != 7 { - - Examples: - [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-check-exit) - · - [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-check-exit) - +Streaming I/O, interactive sessions, and PTY are not supported. - - Examples: - [TypeScript](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-check-exit) - · - [Go](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-check-exit) - - -## Limits - -Not supported: streaming I/O, interactive sessions, PTY. +## Samples - - Daytona `code_run` is not available on this API. - +Runnable projects: [Examples](/docs/examples). diff --git a/website/package-lock.json b/website/package-lock.json index 90191166..e74fe3d9 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -17,8 +17,7 @@ "fumadocs-ui": "npm:@fumadocs/base-ui@16.17.9", "lucide-react": "^1.61.0", "react": "^19.3.1", - "react-dom": "^19.3.1", - "takumi-js": "^2.17.1" + "react-dom": "^19.3.1" }, "devDependencies": { "@tailwindcss/vite": "^4.3.3", @@ -1625,217 +1624,6 @@ "vite": "^5.2.0 || ^6 || ^7 || ^8" } }, - "node_modules/@takumi-rs/core": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/@takumi-rs/core/-/core-2.19.0.tgz", - "integrity": "sha512-cYxOTb4pOu25Y8GBm3JTyIwenHNAZF11pxEmTxA3Q7VabC0pqeWDo/nOjTc2slTHORaglkvwK4SMmnpzab5BjQ==", - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "@takumi-rs/helpers": "2.19.0" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@takumi-rs/core-darwin-arm64": "2.19.0", - "@takumi-rs/core-darwin-x64": "2.19.0", - "@takumi-rs/core-linux-arm64-gnu": "2.19.0", - "@takumi-rs/core-linux-arm64-musl": "2.19.0", - "@takumi-rs/core-linux-x64-gnu": "2.19.0", - "@takumi-rs/core-linux-x64-musl": "2.19.0", - "@takumi-rs/core-win32-arm64-msvc": "2.19.0", - "@takumi-rs/core-win32-x64-msvc": "2.19.0" - }, - "peerDependencies": { - "csstype": "*" - }, - "peerDependenciesMeta": { - "csstype": { - "optional": true - } - } - }, - "node_modules/@takumi-rs/core-darwin-arm64": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/@takumi-rs/core-darwin-arm64/-/core-darwin-arm64-2.19.0.tgz", - "integrity": "sha512-W/SI7Zrxo70dIaKNo+/kOLVr97S3ezkqsi7OM0RWz2CtP+cFgdBTPHXNsrB561gJFPHsuWN/LZ0u8oZxeAYtGw==", - "cpu": [ - "arm64" - ], - "license": "(MIT OR Apache-2.0)", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@takumi-rs/core-darwin-x64": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/@takumi-rs/core-darwin-x64/-/core-darwin-x64-2.19.0.tgz", - "integrity": "sha512-xO/eTwPLrfUZRybMnG4lb6fDa7BjFryFi1TSkRF5KjPhkv21Lr5ovFEYz1y2P5k/4psrk66FJbU2EJDOEjdXiw==", - "cpu": [ - "x64" - ], - "license": "(MIT OR Apache-2.0)", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@takumi-rs/core-linux-arm64-gnu": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/@takumi-rs/core-linux-arm64-gnu/-/core-linux-arm64-gnu-2.19.0.tgz", - "integrity": "sha512-0PvL5bNTZTkLExjKveI3pOz3mtfjJtECqK49f/KGnp7J0bBmdoi2muszCh/dQQEEFKXcWNe27yfK1tzsO5fm0g==", - "cpu": [ - "arm64" - ], - "libc": [ - "glibc" - ], - "license": "(MIT OR Apache-2.0)", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@takumi-rs/core-linux-arm64-musl": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/@takumi-rs/core-linux-arm64-musl/-/core-linux-arm64-musl-2.19.0.tgz", - "integrity": "sha512-nwKZMGcNVdmCP+U7+uINtXpgOeyk5m7g5D9EAtttpWc6ImjJm7MaqNK4Q2YBkOFeAIbRkY5dDL8Xcu19ATSj0w==", - "cpu": [ - "arm64" - ], - "libc": [ - "musl" - ], - "license": "(MIT OR Apache-2.0)", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@takumi-rs/core-linux-x64-gnu": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/@takumi-rs/core-linux-x64-gnu/-/core-linux-x64-gnu-2.19.0.tgz", - "integrity": "sha512-gf/U6qxWZk6uX5MFnl5/PTOzxBbISj89UQwbliHa1sflcq2d+SeITDqnGtkUueF/4TlgPVV7JvrPuhAbINy2Gg==", - "cpu": [ - "x64" - ], - "libc": [ - "glibc" - ], - "license": "(MIT OR Apache-2.0)", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@takumi-rs/core-linux-x64-musl": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/@takumi-rs/core-linux-x64-musl/-/core-linux-x64-musl-2.19.0.tgz", - "integrity": "sha512-zHD0EdIA2ZMCnKV/KtMgEerUcdvjYU4hGiru9I/x96u+BJXaQGMtHCxXt9Srhj+dlqhPyWdQTMAE3wpflN+0nw==", - "cpu": [ - "x64" - ], - "libc": [ - "musl" - ], - "license": "(MIT OR Apache-2.0)", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@takumi-rs/core-win32-arm64-msvc": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/@takumi-rs/core-win32-arm64-msvc/-/core-win32-arm64-msvc-2.19.0.tgz", - "integrity": "sha512-v1CrPsmzhIe0+v+kIAdaSwrNMqiOpUXgMxHLUo0xDQdPMNML0EefDsL9ADtKDpT1pjhY/r9tvwVl3RhKsdottw==", - "cpu": [ - "arm64" - ], - "license": "(MIT OR Apache-2.0)", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@takumi-rs/core-win32-x64-msvc": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/@takumi-rs/core-win32-x64-msvc/-/core-win32-x64-msvc-2.19.0.tgz", - "integrity": "sha512-9HJb2LTDSlehFrGfPw+uKgxM3XCnpy/PYnwtyzcgAiSFJVjwv0zCLl3IvJREakj5Y9rJCg0mMtPje9hlPbJL/A==", - "cpu": [ - "x64" - ], - "license": "(MIT OR Apache-2.0)", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@takumi-rs/helpers": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/@takumi-rs/helpers/-/helpers-2.19.0.tgz", - "integrity": "sha512-3ycCjYCP31HACXBvlpv4fMLw9vneCVGuttFBfZr4jpL0nHNCt2wlXvt0XFt05FscLMUY2s+5PGKPE6EatXI/mg==", - "license": "(MIT OR Apache-2.0)", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "preact": "^10.0.0 || ^11.0.0", - "react": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "preact": { - "optional": true - }, - "react": { - "optional": true - } - } - }, - "node_modules/@takumi-rs/wasm": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/@takumi-rs/wasm/-/wasm-2.19.0.tgz", - "integrity": "sha512-V9LKPOFVHKZ7lANVQ94WmOkGvgW0EqXUeLEpsWB2Wnnx7WpOWHnbAI9Yb0VnAYeyRicp7nAfG3vF/M7vsw0s2w==", - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "@takumi-rs/helpers": "2.19.0" - }, - "engines": { - "node": ">=20.19" - }, - "peerDependencies": { - "csstype": "*" - }, - "peerDependenciesMeta": { - "csstype": { - "optional": true - } - } - }, "node_modules/@tanstack/history": { "version": "1.162.5", "resolved": "https://registry.npmjs.org/@tanstack/history/-/history-1.162.5.tgz", @@ -6683,20 +6471,6 @@ "devOptional": true, "license": "MIT" }, - "node_modules/takumi-js": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/takumi-js/-/takumi-js-2.19.0.tgz", - "integrity": "sha512-WUgzukIpAtoDUeFkdKvT0o4pterWoyM9qcXpIRUQIqUZHriIBdPdPZV42UyzEbNyXvg/1aUaVhBGEyivraT8NQ==", - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "@takumi-rs/core": "2.19.0", - "@takumi-rs/helpers": "2.19.0", - "@takumi-rs/wasm": "2.19.0" - }, - "engines": { - "node": ">=20.19" - } - }, "node_modules/tapable": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", diff --git a/website/package.json b/website/package.json index 839c1ea0..43190e18 100644 --- a/website/package.json +++ b/website/package.json @@ -23,8 +23,7 @@ "fumadocs-ui": "npm:@fumadocs/base-ui@16.17.9", "lucide-react": "^1.61.0", "react": "^19.3.1", - "react-dom": "^19.3.1", - "takumi-js": "^2.17.1" + "react-dom": "^19.3.1" }, "devDependencies": { "@tailwindcss/vite": "^4.3.3", diff --git a/website/scripts/publish-pages.mjs b/website/scripts/publish-pages.mjs index 53c23656..a2d3dbe6 100644 --- a/website/scripts/publish-pages.mjs +++ b/website/scripts/publish-pages.mjs @@ -12,15 +12,17 @@ const paths = [ "/llms-full.txt", ...docFiles .filter((name) => name.endsWith(".mdx")) - .flatMap((name) => { + .map((name) => { const slug = name.replace(/\.mdx$/, ""); const page = slug === "index" ? "" : `/${slug}`; - return [`/docs${page === "" ? "/index.md" : `${page}.md`}`, `/og/docs${page}/image.webp`]; + return `/docs${page === "" ? "/index.md" : `${page}.md`}`; }), ]; for (const path of paths) { - const response = await server.fetch(new Request(`http://localhost${base}${path}`)); + const response = await server.fetch( + new Request(`http://localhost${base}${path}`), + ); if (!response.ok) { throw new Error(`${path} returned ${response.status}`); } diff --git a/website/src/lib/providers.ts b/website/src/lib/providers.ts index 01ade209..6dbc116d 100644 --- a/website/src/lib/providers.ts +++ b/website/src/lib/providers.ts @@ -12,3 +12,35 @@ export const DOC_PROVIDER_STORAGE_KEY = "sandbox-kit.docs.provider"; export function isDocProviderId(value: string): value is DocProviderId { return DOC_PROVIDERS.some((provider) => provider.id === value); } + +/** + * TOC entries that only exist for some providers. Keyed by docs page slug + * (filename without extension), then by heading id. Keep in sync with + * headings wrapped in `` in `content/docs`. + */ +export const PROVIDER_SCOPED_HEADINGS: Record< + string, + Record +> = { + lifecycle: { + "stop-start-pause-and-archive": ["daytona"], + delete: ["daytona"], + terminate: ["modal"], + }, +}; + +export function filterTocForProvider( + pageSlug: string, + toc: T[], + provider: DocProviderId, +): T[] { + const scoped = PROVIDER_SCOPED_HEADINGS[pageSlug]; + if (!scoped) return toc; + + return toc.filter((item) => { + const id = item.url.replace(/^#/, ""); + const providers = scoped[id]; + if (!providers) return true; + return providers.includes(provider); + }); +} diff --git a/website/src/lib/seo.ts b/website/src/lib/seo.ts new file mode 100644 index 00000000..f6915327 --- /dev/null +++ b/website/src/lib/seo.ts @@ -0,0 +1,62 @@ +import { absoluteSiteUrl, appName } from "./shared"; + +export const siteDescription = + "SDK for cloud sandboxes in TypeScript or Go. Plug in a provider; the client talks to it for create, files, and commands."; + +/** Same asset as the site favicon/nav mark (`public/logo.png`). */ +export const ogImagePath = "/logo.png"; +export const ogImageMime = "image/png"; +export const ogImageSize = { width: 500, height: 500 } as const; + +export type SocialHeadInput = { + title: string; + description: string; + /** Site path such as `/` or `/docs/create` (BASE_URL applied once). */ + path: string; + type?: "website" | "article"; +}; + +/** Open Graph + Twitter Card tags with absolute URLs for static GitHub Pages. */ +export function socialHead({ + title, + description, + path, + type = "website", +}: SocialHeadInput) { + const url = absoluteSiteUrl(path); + const image = absoluteSiteUrl(ogImagePath); + const fullTitle = title === appName ? title : `${title} | ${appName}`; + + return { + meta: [ + { title: fullTitle }, + { name: "description", content: description }, + { property: "og:title", content: fullTitle }, + { property: "og:description", content: description }, + { property: "og:url", content: url }, + { property: "og:type", content: type }, + { property: "og:site_name", content: appName }, + { property: "og:locale", content: "en_US" }, + { property: "og:image", content: image }, + { property: "og:image:secure_url", content: image }, + { property: "og:image:type", content: ogImageMime }, + { property: "og:image:width", content: String(ogImageSize.width) }, + { property: "og:image:height", content: String(ogImageSize.height) }, + { property: "og:image:alt", content: appName }, + { name: "twitter:card", content: "summary" }, + { name: "twitter:title", content: fullTitle }, + { name: "twitter:description", content: description }, + { name: "twitter:image", content: image }, + { name: "twitter:image:alt", content: appName }, + ], + links: [{ rel: "canonical", href: url }], + }; +} + +export function siteSocialHead() { + return socialHead({ + title: appName, + description: siteDescription, + path: "/", + }); +} diff --git a/website/src/lib/shared.ts b/website/src/lib/shared.ts index d6f8e996..5a808e92 100644 --- a/website/src/lib/shared.ts +++ b/website/src/lib/shared.ts @@ -2,7 +2,8 @@ import { createGetUrl } from "fumadocs-core/source"; export const appName = "Sandbox Kit"; export const docsRoute = "/docs"; -export const docsImageRoute = "/og/docs"; +/** Production origin for absolute OG/canonical URLs on GitHub Pages. */ +export const siteOrigin = "https://sandbox-kit.github.io"; export const gitConfig = { user: "sandbox-kit", @@ -52,15 +53,7 @@ export function absoluteSiteUrl(path: string) { } // Static prerender for GitHub Pages project site. if (base === "/kit") { - return `https://sandbox-kit.github.io${withBase}`; + return `${siteOrigin}${withBase}`; } return withBase; } - -const getImageUrl = createGetUrl(docsImageRoute); - -export function getPageImageUrl(page: { slugs: string[]; locale?: string }) { - const segments = [...page.slugs, "image.webp"]; - - return { segments, url: getImageUrl(segments, page.locale) }; -} diff --git a/website/src/routeTree.gen.ts b/website/src/routeTree.gen.ts index 7188c595..7e58a5d1 100644 --- a/website/src/routeTree.gen.ts +++ b/website/src/routeTree.gen.ts @@ -15,7 +15,6 @@ import { Route as LlmsDottxtRouteImport } from './routes/llms[.]txt' import { Route as ApiSearchRouteImport } from './routes/api/search' import { Route as DocsSplatRouteImport } from './routes/docs/$' import { Route as DocsChar123Char125DotmdRouteImport } from './routes/docs/{$}[.]md' -import { Route as OgDocsSplatRouteImport } from './routes/og/docs/$' const IndexRoute = IndexRouteImport.update({ id: '/', @@ -47,11 +46,6 @@ const DocsChar123Char125DotmdRoute = DocsChar123Char125DotmdRouteImport.update({ path: '/docs/{$}.md', getParentRoute: () => rootRouteImport, } as any) -const OgDocsSplatRoute = OgDocsSplatRouteImport.update({ - id: '/og/docs/$', - path: '/og/docs/$', - getParentRoute: () => rootRouteImport, -} as any) export interface FileRoutesByFullPath { '/': typeof IndexRoute @@ -60,7 +54,6 @@ export interface FileRoutesByFullPath { '/api/search': typeof ApiSearchRoute '/docs/$': typeof DocsSplatRoute '/docs/{$}.md': typeof DocsChar123Char125DotmdRoute - '/og/docs/$': typeof OgDocsSplatRoute } export interface FileRoutesByTo { '/': typeof IndexRoute @@ -69,7 +62,6 @@ export interface FileRoutesByTo { '/api/search': typeof ApiSearchRoute '/docs/$': typeof DocsSplatRoute '/docs/{$}.md': typeof DocsChar123Char125DotmdRoute - '/og/docs/$': typeof OgDocsSplatRoute } export interface FileRoutesById { __root__: typeof rootRouteImport @@ -79,7 +71,6 @@ export interface FileRoutesById { '/api/search': typeof ApiSearchRoute '/docs/$': typeof DocsSplatRoute '/docs/{$}.md': typeof DocsChar123Char125DotmdRoute - '/og/docs/$': typeof OgDocsSplatRoute } export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath @@ -90,7 +81,6 @@ export interface FileRouteTypes { | '/api/search' | '/docs/$' | '/docs/{$}.md' - | '/og/docs/$' fileRoutesByTo: FileRoutesByTo to: | '/' @@ -99,7 +89,6 @@ export interface FileRouteTypes { | '/api/search' | '/docs/$' | '/docs/{$}.md' - | '/og/docs/$' id: | '__root__' | '/' @@ -108,7 +97,6 @@ export interface FileRouteTypes { | '/api/search' | '/docs/$' | '/docs/{$}.md' - | '/og/docs/$' fileRoutesById: FileRoutesById } export interface RootRouteChildren { @@ -118,7 +106,6 @@ export interface RootRouteChildren { ApiSearchRoute: typeof ApiSearchRoute DocsSplatRoute: typeof DocsSplatRoute DocsChar123Char125DotmdRoute: typeof DocsChar123Char125DotmdRoute - OgDocsSplatRoute: typeof OgDocsSplatRoute } declare module '@tanstack/react-router' { @@ -165,13 +152,6 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof DocsChar123Char125DotmdRouteImport parentRoute: typeof rootRouteImport } - '/og/docs/$': { - id: '/og/docs/$' - path: '/og/docs/$' - fullPath: '/og/docs/$' - preLoaderRoute: typeof OgDocsSplatRouteImport - parentRoute: typeof rootRouteImport - } } } @@ -182,7 +162,6 @@ const rootRouteChildren: RootRouteChildren = { ApiSearchRoute: ApiSearchRoute, DocsSplatRoute: DocsSplatRoute, DocsChar123Char125DotmdRoute: DocsChar123Char125DotmdRoute, - OgDocsSplatRoute: OgDocsSplatRoute, } export const routeTree = rootRouteImport ._addFileChildren(rootRouteChildren) diff --git a/website/src/routes/__root.tsx b/website/src/routes/__root.tsx index b8f3b4e9..6aab94eb 100644 --- a/website/src/routes/__root.tsx +++ b/website/src/routes/__root.tsx @@ -9,6 +9,7 @@ import appCss from "@/styles/app.css?url"; import { RootProvider } from "fumadocs-ui/provider/tanstack"; import { ProviderProvider } from "@/components/provider-context"; import { assetUrl } from "@/lib/shared"; +import { siteDescription } from "@/lib/seo"; export const Route = createRootRoute({ head: () => ({ @@ -19,11 +20,7 @@ export const Route = createRootRoute({ content: "width=device-width, initial-scale=1", }, { title: "Sandbox Kit" }, - { - name: "description", - content: - "Lightweight TypeScript and Go SDK for cloud sandboxes. Pluggable providers, one client for create, lifecycle, files, and commands.", - }, + { name: "description", content: siteDescription }, ], links: [ { rel: "stylesheet", href: appCss }, diff --git a/website/src/routes/docs/$.tsx b/website/src/routes/docs/$.tsx index dd025520..46fa1eef 100644 --- a/website/src/routes/docs/$.tsx +++ b/website/src/routes/docs/$.tsx @@ -10,16 +10,16 @@ import { ViewOptionsPopover, } from "fumadocs-ui/layouts/docs/page"; import { baseOptions } from "@/lib/layout.shared"; +import { absoluteSiteUrl, getPageMarkdownUrl, gitConfig } from "@/lib/shared"; +import { socialHead } from "@/lib/seo"; + +import { Suspense, use, useEffect, useMemo, useState } from "react"; import { - absoluteSiteUrl, - assetUrl, - getPageImageUrl, - getPageMarkdownUrl, - gitConfig, -} from "@/lib/shared"; -import { Suspense, use, useEffect, useState } from "react"; -import { DocsProviderSelect } from "@/components/provider-context"; + DocsProviderSelect, + useDocProvider, +} from "@/components/provider-context"; import { useMDXComponents } from "@/components/mdx"; +import { filterTocForProvider } from "@/lib/providers"; export const Route = createFileRoute("/docs/$")({ component: Page, @@ -31,22 +31,22 @@ export const Route = createFileRoute("/docs/$")({ return { path: page.path, + pageUrl: page.url, title: page.data.title, - description: page.data.description, + description: page.data.description ?? "", // Root-relative without BASE_URL — fumadocs page actions add BASE_URL once. markdownUrl: getPageMarkdownUrl(page).url, - imageUrl: assetUrl(getPageImageUrl(page).url), }; }, - head: ({ loaderData }) => ({ - meta: loaderData - ? [ - { title: `${loaderData.title} | Sandbox Kit` }, - { name: "description", content: loaderData.description ?? "" }, - { property: "og:image", content: loaderData.imageUrl }, - ] - : [], - }), + head: ({ loaderData }) => { + if (!loaderData) return {}; + return socialHead({ + title: loaderData.title, + description: loaderData.description, + path: loaderData.pageUrl, + type: "article", + }); + }, }); function Content({ path, markdownUrl }: { path: string; markdownUrl: string }) { @@ -54,6 +54,16 @@ function Content({ path, markdownUrl }: { path: string; markdownUrl: string }) { if (!page) throw new Error(`unknown page: ${path}`); const { toc } = use(page.load()); + const { provider } = useDocProvider(); + const pageSlug = + path + .replace(/\.mdx?$/, "") + .split("/") + .pop() ?? ""; + const visibleToc = useMemo( + () => filterTocForProvider(pageSlug, toc, provider), + [pageSlug, toc, provider], + ); const MDX = page.body; // AI tools fetch this URL; point at the static .md file, not the SPA HTML page. const [markdownPageUrl, setMarkdownPageUrl] = useState(markdownUrl); @@ -62,7 +72,7 @@ function Content({ path, markdownUrl }: { path: string; markdownUrl: string }) { }, [markdownUrl]); return ( - + {page.title} {page.description}
diff --git a/website/src/routes/index.tsx b/website/src/routes/index.tsx index 4dea1676..1aae9166 100644 --- a/website/src/routes/index.tsx +++ b/website/src/routes/index.tsx @@ -3,8 +3,10 @@ import { HomeLayout } from "fumadocs-ui/layouts/home"; import { HomeCodeSample } from "@/components/home-code-sample"; import { baseOptions } from "@/lib/layout.shared"; import { assetUrl } from "@/lib/shared"; +import { siteSocialHead } from "@/lib/seo"; export const Route = createFileRoute("/")({ + head: () => siteSocialHead(), component: Home, }); @@ -41,8 +43,8 @@ function Home() { Sandbox Kit

- Lightweight TypeScript and Go SDK for cloud sandboxes. Plug in a - provider—one client for create, files, and commands. + SDK for cloud sandboxes in TypeScript or Go. Plug in a provider; + the client talks to it for create, files, and commands.

- Daytona · Modal · your provider next + One client · many providers

- Same call shape on every provider + Create, then run

diff --git a/website/src/routes/og/docs/$.ts b/website/src/routes/og/docs/$.ts deleted file mode 100644 index 4a514b60..00000000 --- a/website/src/routes/og/docs/$.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { createFileRoute } from '@tanstack/react-router'; -import { generateOGImage } from 'fumadocs-ui/og/takumi'; -import { source } from '@/lib/source'; -import { appName } from '@/lib/shared'; - -export const Route = createFileRoute('/og/docs/$')({ - server: { - handlers: { - GET: ({ params }) => { - const slugs = (params._splat?.split('/') ?? []).filter((v) => v.length > 0).slice(0, -1); - const page = source.getPage(slugs); - if (!page) return new Response(undefined, { status: 404 }); - - return generateOGImage({ - title: page.data.title, - description: page.data.description, - site: appName, - format: 'webp', - }); - }, - }, - }, -}); From 23a6610ec7a2c7c5fa9227ebb0d89c7946545f17 Mon Sep 17 00:00:00 2001 From: Nabhag Motivaras <65061890+Nabhag8848@users.noreply.github.com> Date: Thu, 5 Nov 2026 22:08:17 +0530 Subject: [PATCH 2/5] Add a language-scoped API reference to the website docs. Split Client, Sandbox, and related types into dedicated pages, and print example results as whole objects with shape comments. Co-authored-by: Cursor --- website/content/docs/api/client.mdx | 337 +++++++++++++ website/content/docs/api/configuration.mdx | 179 +++++++ website/content/docs/api/create-options.mdx | 396 +++++++++++++++ website/content/docs/api/enums.mdx | 169 +++++++ website/content/docs/api/errors.mdx | 131 +++++ website/content/docs/api/filesystem.mdx | 471 +++++++++++++++++ website/content/docs/api/index.mdx | 35 ++ website/content/docs/api/meta.json | 15 + website/content/docs/api/process.mdx | 128 +++++ website/content/docs/api/sandbox-info.mdx | 99 ++++ website/content/docs/api/sandbox.mdx | 527 ++++++++++++++++++++ website/content/docs/concepts.mdx | 24 +- website/content/docs/create.mdx | 26 +- website/content/docs/errors.mdx | 20 +- website/content/docs/filesystem.mdx | 16 +- website/content/docs/index.mdx | 21 +- website/content/docs/lifecycle.mdx | 43 +- website/content/docs/meta.json | 4 +- website/content/docs/process.mdx | 50 +- website/src/lib/languages.ts | 15 + 20 files changed, 2607 insertions(+), 99 deletions(-) create mode 100644 website/content/docs/api/client.mdx create mode 100644 website/content/docs/api/configuration.mdx create mode 100644 website/content/docs/api/create-options.mdx create mode 100644 website/content/docs/api/enums.mdx create mode 100644 website/content/docs/api/errors.mdx create mode 100644 website/content/docs/api/filesystem.mdx create mode 100644 website/content/docs/api/index.mdx create mode 100644 website/content/docs/api/meta.json create mode 100644 website/content/docs/api/process.mdx create mode 100644 website/content/docs/api/sandbox-info.mdx create mode 100644 website/content/docs/api/sandbox.mdx create mode 100644 website/src/lib/languages.ts diff --git a/website/content/docs/api/client.mdx b/website/content/docs/api/client.mdx new file mode 100644 index 00000000..a661d51d --- /dev/null +++ b/website/content/docs/api/client.mdx @@ -0,0 +1,337 @@ +--- +title: Client +description: Construct a provider connection; create, get, attach, and close. +--- + +Creates and opens sandbox handles for one provider. Closing the client closes the local connection; cloud sandboxes keep running. + +## Construction + + + + +```ts +new Client(config: ClientConfig) +``` + +Validates config and initializes the selected provider. Throws on invalid config. + +**Parameters** + +| Name | Type | Description | +| -------- | ----------------------------------------- | -------------------------------------------------------------------------------- | +| `config` | [`ClientConfig`](/docs/api/configuration) | Provider plus shared settings (`auth`, `scope`, `endpoint`, `region`, `timeout`) | + +**Returns** + +`Client` + +**Example** + +```ts +import { Client } from "@sandbox-kit/sandbox"; + +await using client = new Client({ + provider, + timeout: 120_000, +}); +``` + +`await using` calls `close` on dispose. + + + + +```go +func NewClient(provider Provider, config *Config) (*Client, error) +``` + +Validates config and initializes the provider. Invalid config returns a nil client and an error. + +**Parameters** + +| Name | Type | Description | +| ---------- | ------------------------------------ | ------------------------------------------------------------------ | +| `provider` | `Provider` | Provider constructor from a provider package | +| `config` | [`*Config`](/docs/api/configuration) | Shared settings (`Auth`, `Scope`, `Endpoint`, `Region`, `Timeout`) | + +**Returns** + +`(*Client, error)` + +**Example** + +```go +client, err := sandbox.NewClient(provider, &sandbox.Config{ + Timeout: sandbox.Duration(2 * time.Minute), +}) +if err != nil { + return err +} +defer client.Close(context.Background()) +``` + + + + +## Properties + + + + +| Name | Type | Description | +| -------------- | -------- | ----------------------------------- | +| `providerName` | `string` | Identifier of the selected provider | + + + + +| Name | Signature | Description | +| -------------- | ---------------- | ----------------------------------- | +| `ProviderName` | `func () string` | Identifier of the selected provider | + + + + +## Methods + +### create + + + + +```ts +create(request?: CreateOptions, options?: OperationOptions): Promise +``` + +Creates one sandbox and returns its handle. An empty request uses provider defaults when allowed. + +**Parameters** + +| Name | Type | Description | +| ---------- | --------------------------------------------------------- | --------------------------------------------------- | +| `request?` | [`CreateOptions`](/docs/api/create-options) | Create body. Omitted fields keep provider defaults. | +| `options?` | [`OperationOptions`](/docs/api/sandbox#operation-options) | Call `timeout` (ms) and optional `signal` | + +**Returns** + +`Promise<`[`Sandbox`](/docs/api/sandbox)`>` — handle for the new sandbox + +**Example** + +```ts +const sandbox = await client.create( + { source: { image: { reference: "alpine:3.21" } } }, + { timeout: 60_000 }, +); +console.log(sandbox.id); +``` + + + + +```go +func (c *Client) Create(ctx context.Context, request *CreateOptions) (*Sandbox, error) +``` + +Creates one sandbox and returns its handle. A nil request uses provider defaults when allowed. + +**Parameters** + +| Name | Type | Description | +| --------- | -------------------------------------------- | ----------------------------- | +| `ctx` | `context.Context` | Cancellation and deadline | +| `request` | [`*CreateOptions`](/docs/api/create-options) | Create body; nil for defaults | + +**Returns** + +`(*Sandbox, error)` — handle for the new sandbox + +**Example** + +```go +instance, err := client.Create(ctx, &sandbox.CreateOptions{ + Source: &sandbox.SandboxSource{Kind: &sandbox.Image{ + Image: &sandbox.ImageSource{Reference: "alpine:3.21"}, + }}, +}) +``` + + + + +### get + + + + +```ts +get(id: string, options?: OperationOptions): Promise +``` + +Looks up a sandbox by id and returns a handle the provider has verified. + +**Parameters** + +| Name | Type | Description | +| ---------- | ------------------ | ----------------------- | +| `id` | `string` | Sandbox identifier | +| `options?` | `OperationOptions` | Call timeout and signal | + +**Returns** + +`Promise` + +**Example** + +```ts +const sandbox = await client.get(knownId); +const info = sandbox.info(); +// info: { id, provider, name?, providerState?, region?, isolation?, +// resources?, labels, createdAt?, providerMetadata?, state, terminal? } +console.log(info); +``` + + + + +```go +func (c *Client) Get(ctx context.Context, id string) (*Sandbox, error) +``` + +Looks up a sandbox by id and returns a verified handle. + +**Parameters** + +| Name | Type | Description | +| ----- | ----------------- | ------------------------- | +| `ctx` | `context.Context` | Cancellation and deadline | +| `id` | `string` | Sandbox identifier | + +**Returns** + +`(*Sandbox, error)` + +**Example** + +```go +instance, err := client.Get(ctx, knownID) +// Info(): Id, Provider, Name, ProviderState, Region, Isolation, +// Resources, Labels, CreatedAt, ProviderMetadata, State, Terminal +fmt.Println(instance.Info()) +``` + + + + +### attach + + + + +```ts +attach(id: string, options?: OperationOptions): Promise +``` + +Builds a handle for an existing sandbox id without a lookup round trip. + +**Parameters** + +| Name | Type | Description | +| ---------- | ------------------ | ----------------------- | +| `id` | `string` | Sandbox identifier | +| `options?` | `OperationOptions` | Call timeout and signal | + +**Returns** + +`Promise` + +**Example** + +```ts +const sandbox = await client.attach(knownId); +``` + + + + +```go +func (c *Client) Attach(ctx context.Context, id string) (*Sandbox, error) +``` + +Builds a handle for an existing sandbox id without a lookup round trip. + +**Parameters** + +| Name | Type | Description | +| ----- | ----------------- | ------------------------- | +| `ctx` | `context.Context` | Cancellation and deadline | +| `id` | `string` | Sandbox identifier | + +**Returns** + +`(*Sandbox, error)` + +**Example** + +```go +instance, err := client.Attach(ctx, knownID) +``` + + + + +### close + + + + +```ts +close(options?: OperationOptions): Promise +``` + +Closes the local provider connection. Does not stop, archive, or delete cloud sandboxes. + +**Parameters** + +| Name | Type | Description | +| ---------- | ------------------ | ----------------------- | +| `options?` | `OperationOptions` | Call timeout and signal | + +**Returns** + +`Promise` + +**Example** + +```ts +await client.close(); +``` + + + + +```go +func (c *Client) Close(ctx context.Context) error +``` + +Closes the local provider connection. Does not stop, archive, or delete cloud sandboxes. + +**Parameters** + +| Name | Type | Description | +| ----- | ----------------- | ------------------------- | +| `ctx` | `context.Context` | Cancellation and deadline | + +**Returns** + +`error` + +**Example** + +```go +defer client.Close(context.Background()) +``` + + + diff --git a/website/content/docs/api/configuration.mdx b/website/content/docs/api/configuration.mdx new file mode 100644 index 00000000..10e49d24 --- /dev/null +++ b/website/content/docs/api/configuration.mdx @@ -0,0 +1,179 @@ +--- +title: Client config +description: ClientConfig, Config, auth credentials, and Scope. +--- + +Passed at client construction. Credentials are checked on the first provider call, not at construction. Do not log the config object—it holds secrets. + +## Config + + + + +```ts +type ClientConfig = Config & { provider: Provider }; + +type Config = { + auth?: AuthInput; + endpoint?: string; + region?: string; + scope?: Scope; + timeout?: number; // milliseconds +}; +``` + +| Field | Type | Description | +| ----------- | -------------------- | ------------------------------------------------------------------- | +| `provider` | `Provider` | Provider constructor from a provider package | +| `auth?` | [`AuthInput`](#auth) | Credential set. Omit to use native env/profile resolution. | +| `endpoint?` | `string` | Control-plane URL override when allowed. Remote URLs must be HTTPS. | +| `region?` | `string` | Default region or target preference | +| `scope?` | [`Scope`](#scope) | App, environment, organization, or project | +| `timeout?` | `number` | Default deadline (ms) for calls that omit their own timeout | + +**Example** + +```ts +await using client = new Client({ + provider, + auth: { apiKey: { key: process.env.API_KEY! } }, + region: "us", + timeout: 120_000, +}); +``` + + + + +```go +type Config struct { + Auth *AuthConfig + Endpoint *string + Region *string + Scope *Scope + Timeout *durationpb.Duration +} +``` + +Pass `config` to `NewClient(provider, config)`. + +| Field | Description | +| ---------- | ------------------------------------------------------------ | +| `Auth` | Credential set. Nil lets the native SDK resolve env/profile. | +| `Endpoint` | Control-plane URL override when allowed | +| `Region` | Default region or target preference | +| `Scope` | App, environment, organization, or project | +| `Timeout` | Default deadline via `sandbox.Duration` | + +**Example** + +```go +client, err := sandbox.NewClient(provider, &sandbox.Config{ + Auth: &sandbox.AuthConfig{Credentials: &sandbox.APIKey{ + ApiKey: &sandbox.APIKeyCredentials{Key: os.Getenv("API_KEY")}, + }}, + Region: sandbox.Value("us"), + Timeout: sandbox.Duration(2 * time.Minute), +}) +``` + + + + +## Auth + +Exactly one credential alternative when auth is set. + + + + +```ts +type AuthInput = + | { apiKey: { key: string } } + | { tokenPair: { id: string; secret: string } } + | { bearerToken: { token: string } } + | { + oauthRefresh: { + refreshToken: string; + clientId: string; + clientSecret?: string; // exactly one of clientSecret | jwtKey + jwtKey?: string; + }; + }; +``` + +| Variant | Description | +| -------------- | --------------------------------------------------- | +| `apiKey` | Single API key string | +| `tokenPair` | Id and secret pair | +| `bearerToken` | Bearer or JWT token | +| `oauthRefresh` | Refresh token plus client id and one secret/JWT key | + + + + +```go +// AuthConfig.Credentials is one of: +// *APIKey{ ApiKey: &APIKeyCredentials{ Key } } +// *TokenPair{ TokenPair: &TokenPairCredentials{ Id, Secret } } +// *BearerToken{ BearerToken: &BearerTokenCredentials{ Token } } +// *OAuthRefresh{ OauthRefresh: &OAuthCredentials{ ... } } +``` + +`OAuthCredentials` requires `RefreshToken`, `ClientId`, and exactly one of `ClientSecret` or `JwtKey`. + +| Variant | Description | +| -------------- | --------------------------------------------------- | +| `APIKey` | Single API key string | +| `TokenPair` | Id and secret pair | +| `BearerToken` | Bearer or JWT token | +| `OAuthRefresh` | Refresh token plus client id and one secret/JWT key | + + + + +## Scope + + + + +| Field | Description | +| ---------------- | ------------------------------------------------ | +| `appName` | Application name when the provider scopes by app | +| `environment` | Environment name (often `main`) when used | +| `organizationId` | Organization when the provider scopes by org | +| `projectId` | Project when the provider scopes by project | + + + + +| Field | Description | +| ---------------- | ------------------------------------------------ | +| `AppName` | Application name when the provider scopes by app | +| `Environment` | Environment name (often `main`) when used | +| `OrganizationId` | Organization when the provider scopes by org | +| `ProjectId` | Project when the provider scopes by project | + + + + +## Helpers + + + + +| Helper | Description | +| ------------------------ | ---------------------------------- | +| `validateConfig(config)` | Throws if client config is invalid | + + + + +| Helper | Description | +| ------------------------ | ---------------------------------------------------- | +| `ValidateConfig(config)` | Returns an error if invalid | +| `Duration(d)` | Build a timeout field from `time.Duration` | +| `Value(v)` | Pointer helper for optional scalars (including zero) | + + + diff --git a/website/content/docs/api/create-options.mdx b/website/content/docs/api/create-options.mdx new file mode 100644 index 00000000..b8c5c129 --- /dev/null +++ b/website/content/docs/api/create-options.mdx @@ -0,0 +1,396 @@ +--- +title: CreateOptions +description: Create request body and nested option types. +--- + +Request body for [`Client.create`](/docs/api/client#create). Omitted fields keep provider defaults. Unsupported combinations fail in Kit before the provider call. + +## CreateOptions + + + + +```ts +type CreateOptions = { + name?: string; + source?: SandboxSourceInput; + runtime?: RuntimeConfig; + isolation?: IsolationConfig; + resources?: Resources; + placement?: Placement; + environment?: Record; + labels?: Record; + network?: NetworkConfigInput; + security?: SecurityConfig; + lifetime?: LifetimePolicyInput; + provisioning?: ProvisioningOptionsInput; + readiness?: ReadinessProbeInput; + observability?: ObservabilityConfig; +}; +``` + +Durations on this type are **milliseconds**. Allowlists under `network` are plain `string[]`. + +| Field | Description | +| --------------- | ------------------------------------------------------- | +| `name` | Display name. Explicit empty string asks for unnamed. | +| `source` | Image, snapshot, warm pool, or provider default | +| `runtime` | Language hint, user, working directory, entrypoint, PTY | +| `isolation` | Isolation class | +| `resources` | CPU, memory MiB, disk MiB | +| `placement` | Cloud, preferred regions, or target | +| `environment` | Process environment for the sandbox | +| `labels` | Caller labels/tags | +| `network` | Egress, allowlists, ports, links | +| `security` | Public access, workload identity, secrets | +| `lifetime` | Max lifetime and idle/stopped actions | +| `provisioning` | Create deadline, queue timeout, wait condition | +| `readiness` | Probe when waiting until ready | +| `observability` | Verbose logging / telemetry | + +**Example** + +```ts +const sandbox = await client.create({ + source: { image: { reference: "alpine:3.21" } }, + resources: { cpuCores: 1, memoryMib: 512n }, + runtime: { workingDirectory: "/tmp", entrypoint: ["sleep", "infinity"] }, +}); +``` + + + + +```go +type CreateOptions struct { + Name *string + Source *SandboxSource + Runtime *RuntimeConfig + Isolation *IsolationConfig + Resources *Resources + Placement *Placement + Environment map[string]string + Labels map[string]string + Network *NetworkConfig + Security *SecurityConfig + Lifetime *LifetimePolicy + Provisioning *ProvisioningOptions + Readiness *ReadinessProbe + Observability *ObservabilityConfig +} +``` + +Durations use `sandbox.Duration`. Optional numbers use `sandbox.Value`. + +| Field | Description | +| --------------- | ------------------------------------------------------- | +| `Name` | Display name. Explicit empty string asks for unnamed. | +| `Source` | Image, snapshot, warm pool, or provider default | +| `Runtime` | Language hint, user, working directory, entrypoint, PTY | +| `Isolation` | Isolation class | +| `Resources` | CPU, memory MiB, disk MiB | +| `Placement` | Cloud, preferred regions, or target | +| `Environment` | Process environment for the sandbox | +| `Labels` | Caller labels/tags | +| `Network` | Egress, allowlists, ports, links | +| `Security` | Public access, workload identity, secrets | +| `Lifetime` | Max lifetime and idle/stopped actions | +| `Provisioning` | Create deadline, queue timeout, wait condition | +| `Readiness` | Probe when waiting until ready | +| `Observability` | Verbose logging / telemetry | + +**Example** + +```go +instance, err := client.Create(ctx, &sandbox.CreateOptions{ + Source: &sandbox.SandboxSource{Kind: &sandbox.Image{ + Image: &sandbox.ImageSource{Reference: "alpine:3.21"}, + }}, + Resources: &sandbox.Resources{ + CpuCores: sandbox.Value(1.0), + MemoryMib: sandbox.Value(uint64(512)), + }, +}) +``` + + + + +## Source + +Set exactly one variant. + + + + +| Variant | Description | +| ----------------- | ------------------------------------- | +| `image` | Container image `reference` | +| `snapshot` | Snapshot `reference`, optional `kind` | +| `warmPool` | Warm pool `reference` | +| `providerDefault` | Let the provider choose | + + + + +| Variant | Description | +| ----------------- | ------------------------------------- | +| `Image` | Container image `Reference` | +| `Snapshot` | Snapshot `Reference`, optional `Kind` | +| `WarmPool` | Warm pool `Reference` | +| `ProviderDefault` | Let the provider choose | + + + + +## RuntimeConfig + + + + +| Field | Description | +| ------------------ | ------------------------------------------------- | +| `language` | Language or toolbox hint (not an install promise) | +| `version` | Version hint | +| `user` | OS user | +| `workingDirectory` | Working directory | +| `entrypoint` | Entrypoint argv | +| `pty` | Request a PTY when supported | + + + + +| Field | Description | +| ------------------ | ------------------------------------------------- | +| `Language` | Language or toolbox hint (not an install promise) | +| `Version` | Version hint | +| `User` | OS user | +| `WorkingDirectory` | Working directory | +| `Entrypoint` | Entrypoint argv | +| `Pty` | Request a PTY when supported | + + + + +## Resources + + + + +| Field | Description | +| ---------------- | ---------------------------------------------- | +| `cpuCores` | Requested CPU cores | +| `cpuLimitCores` | Optional CPU ceiling (≥ request when positive) | +| `memoryMib` | Requested memory in MiB | +| `memoryLimitMib` | Optional memory ceiling | +| `diskMib` | Requested disk in MiB | + + + + +| Field | Description | +| ---------------- | ---------------------------------------------- | +| `CpuCores` | Requested CPU cores | +| `CpuLimitCores` | Optional CPU ceiling (≥ request when positive) | +| `MemoryMib` | Requested memory in MiB | +| `MemoryLimitMib` | Optional memory ceiling | +| `DiskMib` | Requested disk in MiB | + + + + +## Placement + + + + +| Field | Description | +| --------- | -------------------------- | +| `cloud` | Cloud name preference | +| `regions` | Preferred regions in order | +| `target` | Provider target string | + + + + +| Field | Description | +| --------- | -------------------------- | +| `Cloud` | Cloud name preference | +| `Regions` | Preferred regions in order | +| `Target` | Provider target string | + + + + +## LifetimePolicy + + + + +| Field | Description | +| ----------------- | ------------------------------------------------------ | +| `maximumLifetime` | Cap on how long the sandbox may exist | +| `ephemeral` | Prefer deletion when the sandbox stops, when supported | +| `idleTerminate` | End after idle | +| `idleStop` | Stop after idle | +| `idlePause` | Pause after idle | +| `stoppedArchive` | Archive after stop | +| `stoppedDelete` | Delete after stop | + + + + +| Field | Description | +| ----------------- | ------------------------------------------------------ | +| `MaximumLifetime` | Cap on how long the sandbox may exist | +| `Ephemeral` | Prefer deletion when the sandbox stops, when supported | +| `IdleTerminate` | End after idle | +| `IdleStop` | Stop after idle | +| `IdlePause` | Pause after idle | +| `StoppedArchive` | Archive after stop | +| `StoppedDelete` | Delete after stop | + + + + +### AutomaticAction + + + + +| Field | Description | +| ------- | ----------------------------------------------------------------------------- | +| `mode` | [`PolicyMode`](/docs/api/enums#policymode): `Default`, `Disabled`, or `After` | +| `after` | Delay when mode is `After`. Zero means immediate, not disabled. | + + + + +| Field | Description | +| ------- | ----------------------------------------------------------------------------- | +| `Mode` | [`PolicyMode`](/docs/api/enums#policymode): `Default`, `Disabled`, or `After` | +| `After` | Delay when mode is `After`. Zero means immediate, not disabled. | + + + + +## ProvisioningOptions + + + + +| Field | Description | +| -------------- | ----------------------------------------------------------------- | +| `timeout` | Create operation deadline | +| `queueTimeout` | How long creation may sit in a queue | +| `waitFor` | [`WaitCondition`](/docs/api/enums#waitcondition) before returning | + + + + +| Field | Description | +| -------------- | ----------------------------------------------------------------- | +| `Timeout` | Create operation deadline | +| `QueueTimeout` | How long creation may sit in a queue | +| `WaitFor` | [`WaitCondition`](/docs/api/enums#waitcondition) before returning | + + + + +## ReadinessProbe + +Set either a TCP port or a command. + + + + +| Variant | Description | +| -------------- | ------------------------------ | +| `tcpPort` | Port `1`–`65535` | +| `command.argv` | Command argv that must succeed | + + + + +| Variant | Description | +| --------------------- | ------------------------------ | +| `TcpPort` | Port `1`–`65535` | +| `Command` with `Argv` | Command argv that must succeed | + + + + +## NetworkConfig + + + + +| Field | Description | +| ------------------ | ----------------------------------------------------------- | +| `egress` | [`EgressMode`](/docs/api/enums#egressmode) | +| `outboundCidrs` | Outbound CIDR allowlist. Present empty list means deny-all. | +| `outboundDomains` | Outbound domain allowlist | +| `inboundCidrs` | Inbound CIDR allowlist | +| `privateNetwork` | Request a private network when supported | +| `linkedSandbox` | Link to another known sandbox id | +| `proxyReference` | Provider-managed proxy name | +| `outboundProxyUrl` | Outbound proxy URL | +| `customDomain` | Custom domain when supported | +| `ports` | Published ports (`port`, optional `transport`) | + + + + +| Field | Description | +| ------------------ | ----------------------------------------------------------- | +| `Egress` | [`EgressMode`](/docs/api/enums#egressmode) | +| `OutboundCidrs` | Outbound CIDR allowlist. Present empty list means deny-all. | +| `OutboundDomains` | Outbound domain allowlist | +| `InboundCidrs` | Inbound CIDR allowlist | +| `PrivateNetwork` | Request a private network when supported | +| `LinkedSandbox` | Link to another known sandbox id | +| `ProxyReference` | Provider-managed proxy name | +| `OutboundProxyUrl` | Outbound proxy URL | +| `CustomDomain` | Custom domain when supported | +| `Ports` | Published ports (`Port`, optional `Transport`) | + + + + +## SecurityConfig + + + + +| Field | Description | +| ------------------ | ------------------------------------------------------------------------- | +| `publicAccess` | Request public access when true | +| `workloadIdentity` | Request a workload identity when supported | +| `secrets` | Provider-managed secret references (`reference`, injection, env var name) | + + + + +| Field | Description | +| ------------------ | ------------------------------------------------------------------------- | +| `PublicAccess` | Request public access when true | +| `WorkloadIdentity` | Request a workload identity when supported | +| `Secrets` | Provider-managed secret references (`Reference`, injection, env var name) | + + + + +## Helpers + + + + +`validateCreateOptions(request)` — throws if the create body is invalid. + + + + +`ValidateCreateOptions(request)` — returns an error if invalid. + + + diff --git a/website/content/docs/api/enums.mdx b/website/content/docs/api/enums.mdx new file mode 100644 index 00000000..bd39cd9d --- /dev/null +++ b/website/content/docs/api/enums.mdx @@ -0,0 +1,169 @@ +--- +title: Enums +description: Shared public enums for create, lifecycle, and info. +--- + + + + +Exported as PascalCase const objects (for example `PolicyMode.After`, `SandboxState.Running`). + + + + +Exported as prefixed constants (for example `sandbox.PolicyModeAfter`, `sandbox.SandboxStateRunning`). + + + + +## SandboxState + +Portable lifecycle state on [`SandboxInfo`](/docs/api/sandbox-info). + +| Value | Description | +| ------------- | ------------------------------------ | +| `Unknown` | State is not known or not yet mapped | +| `Queued` | Waiting to be scheduled | +| `Starting` | Booting or coming online | +| `Running` | Available for work | +| `Stopping` | Stop in progress | +| `Stopped` | Stopped and can be started again | +| `Pausing` | Pause in progress | +| `Paused` | Paused with retained state | +| `Archiving` | Archive in progress | +| `Archived` | Archived to colder storage | +| `Terminating` | Permanent end in progress | +| `Terminated` | Permanently ended | +| `Deleting` | Delete in progress | +| `Deleted` | Permanently removed | +| `Error` | Provider reported a failure state | + +## LifecycleCapability + +Used with [Capabilities](/docs/api/sandbox#capabilities). File and process calls are not capabilities. + +| Value | Description | +| ----------- | -------------------------------------- | +| `Unknown` | Unspecified capability | +| `Refresh` | Reload metadata from the provider | +| `Start` | Start a stopped sandbox | +| `Stop` | Stop a running sandbox | +| `Pause` | Pause a sandbox | +| `Terminate` | Permanently end the sandbox | +| `Archive` | Move retained state to archive storage | +| `Delete` | Permanently delete the sandbox | + +## PolicyMode + +Idle/stopped automatic actions under [`LifetimePolicy`](/docs/api/create-options#lifetimepolicy). + +| Value | Description | +| ---------- | -------------------------------------------------- | +| `Default` | Omit the policy / leave it to the provider | +| `Disabled` | Turn the policy off | +| `After` | Run after the configured delay (`after` / `After`) | + +## WaitCondition + +How far provisioning wait-for waits before create returns. + +| Value | Description | +| ----------- | ----------------------------------------------------------------------- | +| `Default` | Provider default wait depth | +| `Submitted` | Return once the create request is accepted | +| `Scheduled` | Return once the sandbox is scheduled | +| `Started` | Return once the sandbox has started | +| `Ready` | Return once readiness succeeds (probe + positive timeout when required) | + +## EgressMode + +Outbound network policy on create. + +| Value | Description | +| ------------ | -------------------------------------------------------------- | +| `Default` | Leave outbound policy to the provider | +| `AllowAll` | Allow outbound traffic | +| `BlockAll` | Block outbound traffic (including private links when enforced) | +| `Restricted` | Allow only listed CIDRs and/or domains | + +## PortTransport + +Transport for a published port. + +| Value | Description | +| ---------- | ----------------------------------- | +| `Default` | Leave the transport to the provider | +| `Tls` | TLS | +| `Http2Tls` | HTTP/2 over TLS | +| `Plain` | Unencrypted / plain transport | + +## IsolationKind + +Sandbox isolation class. + +| Value | Description | +| ------------------ | --------------------------------------------------- | +| `Default` | Leave the class to the provider | +| `Container` | Container isolation | +| `MicroVM` | MicroVM isolation | +| `LinuxVm` | Full Linux VM isolation | +| `Worker` | Worker-style isolation | +| `ProviderSpecific` | Provider-defined class (see provider kind when set) | + +## SnapshotKind + +Classification for a snapshot source. + +| Value | Description | +| ------------------ | ------------------------------- | +| `Default` | Leave the class to the provider | +| `Filesystem` | Filesystem snapshot | +| `Memory` | Memory snapshot | +| `Image` | Image snapshot | +| `Machine` | Machine snapshot | +| `Checkpoint` | Checkpoint snapshot | +| `ProviderSpecific` | Provider-defined snapshot class | + +## SecretInjection + +How a create-time secret reference is exposed. + +| Value | Description | +| ------------------- | --------------------------------- | +| `Default` | Leave injection to the provider | +| `Environment` | Inject as an environment variable | +| `EgressPlaceholder` | Inject as an egress placeholder | + +## FileType + +Filesystem entry kind on [`FileInfo`](/docs/api/filesystem#fileinfo). + +| Value | Description | +| ------------- | --------------------- | +| `Unspecified` | Type was not reported | +| `File` | Regular file | +| `Directory` | Directory | +| `Symlink` | Symbolic link | + +## ErrorKind + +Error category on the typed error. Not retry advice. See also [Errors](/docs/api/errors). + +| Value | Description | +| -------------------- | ------------------------------------------------------ | +| `Unknown` | Does not match a known category | +| `InvalidArgument` | The request shape is wrong | +| `Unsupported` | This provider does not implement the call or the field | +| `Authentication` | Credentials were rejected | +| `PermissionDenied` | The account cannot perform this operation | +| `NotFound` | The sandbox or file path was not found | +| `AlreadyExists` | The named resource already exists | +| `Conflict` | Current state rejects this operation | +| `RateLimited` | Provider rate limit reached | +| `ResourceExhausted` | Provider quota or capacity reached | +| `Timeout` | The deadline fired | +| `Canceled` | The caller canceled the operation | +| `Unavailable` | The provider could not be reached | +| `InvalidResponse` | The provider response cannot be used | +| `Internal` | Unclassified failure | +| `FailedPrecondition` | Client or sandbox is not in a usable state | diff --git a/website/content/docs/api/errors.mdx b/website/content/docs/api/errors.mdx new file mode 100644 index 00000000..d4ae7c11 --- /dev/null +++ b/website/content/docs/api/errors.mdx @@ -0,0 +1,131 @@ +--- +title: Errors +description: Typed error fields and ErrorKind values. +--- + +Failed calls surface a typed error. Kinds are categories, not retry advice. Handling patterns: [Errors guide](/docs/errors). + +## Shape + + + + +```ts +class SandboxError extends Error { + kind: ErrorKind; + provider: string; + operation: string; + field: string; + rule?: string; + statusCode?: number; + providerCode?: string; + providerSource?: string; + // cause?: unknown — provider error when present +} +``` + +Throws from the client and sandbox handle. + +| Field | Description | +| ---------------- | -------------------------------------------------------------------------------------------- | +| `kind` | [`ErrorKind`](#errorkind) category | +| `provider` | Provider id, or empty for local failures | +| `operation` | Call name (`create`, `initialize`, `run`, …) | +| `field` | Canonical path of the rejected setting (for example `resources.cpu_cores`). Empty when none. | +| `message` | Human-readable explanation | +| `rule` | Stable validation/policy id when applicable | +| `statusCode` | HTTP/transport status when reported | +| `providerCode` | Provider's own error code when reported | +| `providerSource` | Provider component when reported | + +Exported field-path constants (for example `CreateFieldResourcesCpuCores`) match `field` for comparisons. + +**Example** + +```ts +import { ErrorKind, SandboxError } from "@sandbox-kit/sandbox"; + +try { + await client.create(request); +} catch (error) { + if (!(error instanceof SandboxError)) throw error; + // error: { kind, provider, operation, field, message, rule?, + // statusCode?, providerCode?, providerSource?, cause? } + console.error(error); + if (error.kind === ErrorKind.InvalidArgument) { + // fix the field named by error.field + } +} +``` + + + + +```go +type Error struct { + Kind ErrorKind + Provider string + Operation string + Field string + Message string + StatusCode *uint32 + ProviderCode *string + ProviderSource *string + Rule *string + // Unwrap() returns the provider/validator cause when present +} +``` + +Use `errors.As(err, &detail)` to read fields. + +| Field | Description | +| ---------------- | -------------------------------------------------------------------------------------------- | +| `Kind` | [`ErrorKind`](#errorkind) category | +| `Provider` | Provider id, or empty for local failures | +| `Operation` | Call name (`create`, `initialize`, `run`, …) | +| `Field` | Canonical path of the rejected setting (for example `resources.cpu_cores`). Empty when none. | +| `Message` | Human-readable explanation | +| `Rule` | Stable validation/policy id when applicable | +| `StatusCode` | HTTP/transport status when reported | +| `ProviderCode` | Provider's own error code when reported | +| `ProviderSource` | Provider component when reported | + +Exported field-path constants (for example `CreateFieldResourcesCpuCores`) match `Field` for comparisons. + +**Example** + +```go +var detail *sandbox.Error +if errors.As(err, &detail) { + // detail: Kind, Provider, Operation, Field, Message, StatusCode, + // ProviderCode, ProviderSource, Rule (+ Unwrap cause) + fmt.Println(detail) + if detail.Kind == sandbox.ErrorKindInvalidArgument { + // fix the field named by detail.Field + } +} +``` + + + + +## ErrorKind + +| Kind | Description | +| -------------------- | ------------------------------------------------------ | +| `InvalidArgument` | The request shape is wrong | +| `Unsupported` | This provider does not implement the call or the field | +| `Authentication` | Credentials were rejected | +| `PermissionDenied` | The account cannot perform this operation | +| `NotFound` | The sandbox or file path was not found | +| `AlreadyExists` | The named resource already exists | +| `Conflict` | Current state rejects this operation | +| `RateLimited` | Provider rate limit reached | +| `ResourceExhausted` | Provider quota or capacity reached | +| `Timeout` | The deadline fired | +| `Canceled` | The caller canceled the operation | +| `Unavailable` | The provider could not be reached | +| `InvalidResponse` | The provider response cannot be used | +| `Internal` | Unclassified failure | +| `FailedPrecondition` | Client or sandbox is not in a usable state | +| `Unknown` | Does not match a known category | diff --git a/website/content/docs/api/filesystem.mdx b/website/content/docs/api/filesystem.mdx new file mode 100644 index 00000000..8eb6910a --- /dev/null +++ b/website/content/docs/api/filesystem.mdx @@ -0,0 +1,471 @@ +--- +title: Filesystem +description: Read, write, copy, list, stat, and remove files in a sandbox. +--- + +Paths inside the sandbox must be absolute. Local paths for copy may be relative. Omitted timeouts use the client default. + + + + +Access as `sandbox.filesystem`. + + + + +Access as `instance.Filesystem()`. + + + + +## Methods + +### Read a file + + + + +```ts +readFile(path: string, options?: FileReadOptions & OperationOptions): Promise +``` + +Returns the bytes of the file at `path`. + +**Parameters** + +| Name | Type | Description | +| ---------- | -------------------------------------------- | --------------------- | +| `path` | `string` | Absolute sandbox path | +| `options?` | `{ timeout?: number; signal?: AbortSignal }` | Call deadline | + +**Returns** + +`Promise` — file contents + +**Example** + +```ts +const bytes = await sandbox.filesystem.readFile("/tmp/note.txt"); +console.log(new TextDecoder().decode(bytes)); +``` + + + + +```go +func (f *Filesystem) ReadFile(ctx context.Context, path string, options *FileReadOptions) ([]byte, error) +``` + +Returns the bytes of the file at `path`. + +**Parameters** + +| Name | Type | Description | +| --------- | ------------------ | ------------------------- | +| `ctx` | `context.Context` | Cancellation and deadline | +| `path` | `string` | Absolute sandbox path | +| `options` | `*FileReadOptions` | Optional `Timeout` | + +**Returns** + +`([]byte, error)` + +**Example** + +```go +data, err := instance.Filesystem().ReadFile(ctx, "/tmp/note.txt", nil) +``` + + + + +### Write a file + + + + +```ts +writeFile(path: string, data: Uint8Array, options?: FileWriteOptions & OperationOptions): Promise +``` + +Replaces the file at `path` and creates missing parent directories. + +**Parameters** + +| Name | Type | Description | +| ---------- | ----------------------- | --------------------- | +| `path` | `string` | Absolute sandbox path | +| `data` | `Uint8Array` | Bytes to write | +| `options?` | `{ timeout?; signal? }` | Call deadline | + +**Returns** + +`Promise` + +**Example** + +```ts +await sandbox.filesystem.writeFile( + "/tmp/note.txt", + new TextEncoder().encode("hello\n"), +); +``` + + + + +```go +func (f *Filesystem) WriteFile(ctx context.Context, path string, data []byte, options *FileWriteOptions) error +``` + +Replaces the file at `path` and creates missing parent directories. + +**Parameters** + +| Name | Type | Description | +| --------- | ------------------- | --------------------- | +| `path` | `string` | Absolute sandbox path | +| `data` | `[]byte` | Bytes to write | +| `options` | `*FileWriteOptions` | Optional `Timeout` | + +**Returns** + +`error` + +**Example** + +```go +err := instance.Filesystem().WriteFile(ctx, "/tmp/note.txt", []byte("hello\n"), nil) +``` + + + + +### Copy from local + + + + +```ts +copyFromLocal(localPath: string, remotePath: string, options?: FileCopyOptions & OperationOptions): Promise +``` + +Copies a file from the caller into the sandbox. + +**Parameters** + +| Name | Type | Description | +| ------------ | ----------------------- | ---------------------------- | +| `localPath` | `string` | Local path (may be relative) | +| `remotePath` | `string` | Absolute sandbox path | +| `options?` | `{ timeout?; signal? }` | Call deadline | + +**Returns** + +`Promise` + +**Example** + +```ts +await sandbox.filesystem.copyFromLocal("./note.txt", "/tmp/note.txt"); +``` + + + + +```go +func (f *Filesystem) CopyFromLocal(ctx context.Context, localPath, remotePath string, options *FileCopyOptions) error +``` + +Copies a file from the caller into the sandbox. + +**Parameters** + +| Name | Type | Description | +| ------------ | ------------------ | ---------------------------- | +| `localPath` | `string` | Local path (may be relative) | +| `remotePath` | `string` | Absolute sandbox path | +| `options` | `*FileCopyOptions` | Optional `Timeout` | + +**Returns** + +`error` + + + + +### Copy to local + + + + +```ts +copyToLocal(remotePath: string, localPath: string, options?: FileCopyOptions & OperationOptions): Promise +``` + +Copies a sandbox file onto the caller's disk. Missing local parents are created. An existing local directory is rejected. + +**Parameters** + +| Name | Type | Description | +| ------------ | ----------------------- | ---------------------- | +| `remotePath` | `string` | Absolute sandbox path | +| `localPath` | `string` | Local destination path | +| `options?` | `{ timeout?; signal? }` | Call deadline | + +**Returns** + +`Promise` + + + + +```go +func (f *Filesystem) CopyToLocal(ctx context.Context, remotePath, localPath string, options *FileCopyOptions) error +``` + +Copies a sandbox file onto the caller's disk. Missing local parents are created. + +**Returns** + +`error` + + + + +### Make a directory + + + + +```ts +makeDirectory(path: string, options?: MakeDirectoryOptions & OperationOptions): Promise +``` + +Creates the directory at `path`. An omitted `parents` flag is `true` (create missing parents). + +**Parameters** + +| Name | Type | Description | +| ---------- | ------------------------------------------ | ------------------------- | +| `path` | `string` | Absolute sandbox path | +| `options?` | `{ parents?: boolean; timeout?; signal? }` | Parents flag and deadline | + +**Returns** + +`Promise` + + + + +```go +func (f *Filesystem) MakeDirectory(ctx context.Context, path string, options *MakeDirectoryOptions) error +``` + +Creates the directory at `path`. An omitted `Parents` flag is true. + +**Parameters** + +| Name | Type | Description | +| --------- | ----------------------- | ----------------------------------- | +| `options` | `*MakeDirectoryOptions` | `Timeout`, optional `Parents *bool` | + +**Returns** + +`error` + + + + +### List a directory + + + + +```ts +listDirectory(path: string, options?: ListDirectoryOptions & OperationOptions): Promise +``` + +Lists entries in one directory. + +**Returns** + +`Promise` + +**Example** + +```ts +const entries = await sandbox.filesystem.listDirectory("/tmp"); +// entries[]: { name, path, type, size, mode?, permissions?, owner?, group?, +// modifiedAt?, symlinkTarget? } +console.log(entries); +``` + + + + +```go +func (f *Filesystem) ListDirectory(ctx context.Context, path string, options *ListDirectoryOptions) ([]*FileInfo, error) +``` + +Lists entries in one directory. + +**Returns** + +`([]*FileInfo, error)` + +**Example** + +```go +entries, err := instance.Filesystem().ListDirectory(ctx, "/tmp", nil) +// each entry: Name, Path, Type, Size, Mode, Permissions, Owner, Group, ModifiedAt, SymlinkTarget +fmt.Println(entries) +``` + + + + +### Stat a path + + + + +```ts +stat(path: string, options?: StatOptions & OperationOptions): Promise +``` + +Returns metadata for one path. A symlink result describes the symlink. + +**Returns** + +`Promise` + +**Example** + +```ts +const info = await sandbox.filesystem.stat("/tmp/note.txt"); +// info: { name, path, type, size, mode?, permissions?, owner?, group?, +// modifiedAt?, symlinkTarget? } +console.log(info); +``` + + + + +```go +func (f *Filesystem) Stat(ctx context.Context, path string, options *StatOptions) (*FileInfo, error) +``` + +Returns metadata for one path. A symlink result describes the symlink. + +**Returns** + +`(*FileInfo, error)` + +**Example** + +```go +info, err := instance.Filesystem().Stat(ctx, "/tmp/note.txt", nil) +// info: Name, Path, Type, Size, Mode, Permissions, Owner, Group, ModifiedAt, SymlinkTarget +fmt.Println(info) +``` + + + + +### Remove a path + + + + +```ts +remove(path: string, options?: RemoveOptions & OperationOptions): Promise +``` + +Removes a file, or a directory when `recursive` is set. An omitted `recursive` flag removes a file or an empty directory. + +**Parameters** + +| Name | Type | Description | +| ---------- | -------------------------------------------- | --------------------------- | +| `path` | `string` | Absolute sandbox path | +| `options?` | `{ recursive?: boolean; timeout?; signal? }` | Recursive flag and deadline | + +**Returns** + +`Promise` + +**Example** + +```ts +await sandbox.filesystem.remove("/tmp/dir", { recursive: true }); +``` + + + + +```go +func (f *Filesystem) Remove(ctx context.Context, path string, options *RemoveOptions) error +``` + +Removes a file, or a directory when `Recursive` is set. + +**Parameters** + +| Name | Type | Description | +| --------- | ---------------- | ------------------------------------- | +| `options` | `*RemoveOptions` | `Timeout`, optional `Recursive *bool` | + +**Returns** + +`error` + +**Example** + +```go +err := instance.Filesystem().Remove(ctx, "/tmp/dir", &sandbox.RemoveOptions{ + Recursive: sandbox.Value(true), +}) +``` + + + + +## FileInfo + +Metadata for one file, directory, or symlink. + + + + +| Field | Description | +| --------------- | ------------------------------------------------------------------- | +| `name` | Base name | +| `path` | Absolute path in the sandbox | +| `type` | [`FileType`](/docs/api/enums#filetype): file, directory, or symlink | +| `size` | Size in bytes | +| `mode` | Unix mode string when reported (for example `0644`) | +| `permissions` | Symbolic permissions when reported | +| `owner` | Ownership when reported | +| `group` | Group when reported | +| `modifiedAt` | Last modification time when reported | +| `symlinkTarget` | Target path when the entry is a symlink | + + + + +| Field | Description | +| --------------- | ------------------------------------------------------------------- | +| `Name` | Base name | +| `Path` | Absolute path in the sandbox | +| `Type` | [`FileType`](/docs/api/enums#filetype): file, directory, or symlink | +| `Size` | Size in bytes | +| `Mode` | Unix mode string when reported (for example `0644`) | +| `Permissions` | Symbolic permissions when reported | +| `Owner` | Ownership when reported | +| `Group` | Group when reported | +| `ModifiedAt` | Last modification time when reported | +| `SymlinkTarget` | Target path when the entry is a symlink | + + + diff --git a/website/content/docs/api/index.mdx b/website/content/docs/api/index.mdx new file mode 100644 index 00000000..19a8e71b --- /dev/null +++ b/website/content/docs/api/index.mdx @@ -0,0 +1,35 @@ +--- +title: Overview +description: User-facing types and methods for the Sandbox Kit core SDK. +--- + +Public surface of the core sandbox package. Guides show how pieces fit together; this section documents signatures, parameters, and return values. + +Use the language tabs on each page. Unsupported calls return a typed error—see [Errors](/docs/api/errors) and the [Errors guide](/docs/errors). + + + + +Package: `@sandbox-kit/sandbox`. Durations and timeouts are **milliseconds**. + + + + +Package: `github.com/sandbox-kit/kit/sdks/go/sandbox`. Durations use `sandbox.Duration`. Optional scalars use `sandbox.Value`. + + + + +## Modules + +| Name | Description | +| ----------------------------------------- | ----------------------------------------------------------------- | +| [Client](/docs/api/client) | Construct a provider connection; create, get, or attach sandboxes | +| [Sandbox](/docs/api/sandbox) | Handle for one sandbox: lifecycle, info, filesystem, process | +| [Filesystem](/docs/api/filesystem) | Read, write, copy, list, stat, and remove files | +| [Process](/docs/api/process) | Run a command and collect exit code and output | +| [Client config](/docs/api/configuration) | Client config, auth, and scope types | +| [CreateOptions](/docs/api/create-options) | Create request body and nested option types | +| [SandboxInfo](/docs/api/sandbox-info) | Metadata returned by info and lifecycle calls | +| [Errors](/docs/api/errors) | Typed error shape and kinds | +| [Enums](/docs/api/enums) | Shared enums (`SandboxState`, `PolicyMode`, …) | diff --git a/website/content/docs/api/meta.json b/website/content/docs/api/meta.json new file mode 100644 index 00000000..7c21247f --- /dev/null +++ b/website/content/docs/api/meta.json @@ -0,0 +1,15 @@ +{ + "title": "API", + "pages": [ + "index", + "client", + "sandbox", + "filesystem", + "process", + "configuration", + "create-options", + "sandbox-info", + "errors", + "enums" + ] +} diff --git a/website/content/docs/api/process.mdx b/website/content/docs/api/process.mdx new file mode 100644 index 00000000..25940355 --- /dev/null +++ b/website/content/docs/api/process.mdx @@ -0,0 +1,128 @@ +--- +title: Process +description: Run a command in a sandbox and collect exit code and output. +--- + +A non-zero exit code is **not** an error. Set exactly one of argv or shell. + + + + +Access as `sandbox.process`. Set exactly one of `argv` or `shell`. + + + + +Access as `instance.Process()`. Set exactly one of `Argv` or `Shell`. + + + + +## Methods + +### Run a command + + + + +```ts +run(options: ExecOptions & OperationOptions): Promise +``` + +Runs one command and waits for it to finish. + +**Parameters** + +| Name | Type | Description | +| --------------------------- | ------------------------ | ------------------------------------------------------- | +| `options.argv?` | `string[]` | Program and arguments. Mutually exclusive with `shell`. | +| `options.shell?` | `string` | Shell command string. Mutually exclusive with `argv`. | +| `options.workingDirectory?` | `string` | Absolute working directory inside the sandbox | +| `options.environment?` | `Record` | Env vars for this command only | +| `options.timeout?` | `number` | Deadline in milliseconds; whole seconds required | +| `options.signal?` | `AbortSignal` | Abort the wait | + +**Returns** + +[`Promise`](#execresult) + +**Example** + +```ts +const result = await sandbox.process.run({ + argv: ["echo", "hello"], + workingDirectory: "/tmp", + environment: { KIT_DEMO: "from-kit" }, + timeout: 5_000, +}); +// result: { exitCode, stdout, stderr } +console.log(result); +``` + + + + +```go +func (p *Process) Run(ctx context.Context, options *ExecOptions) (*ExecResult, error) +``` + +Runs one command and waits for it to finish. + +**Parameters** + +| Name | Type | Description | +| -------------------------- | ---------------------- | ------------------------------------------------------- | +| `ctx` | `context.Context` | Cancellation and deadline | +| `options.Argv` | `[]string` | Program and arguments. Mutually exclusive with `Shell`. | +| `options.Shell` | `*string` | Shell command string | +| `options.WorkingDirectory` | `*string` | Absolute working directory | +| `options.Environment` | `map[string]string` | Env vars for this command only | +| `options.Timeout` | `*durationpb.Duration` | Via `sandbox.Duration`; whole seconds | + +**Returns** + +[`(*ExecResult, error)`](#execresult) + +**Example** + +```go +result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ + Argv: []string{"echo", "hello"}, + WorkingDirectory: sandbox.Value("/tmp"), + Environment: map[string]string{"KIT_DEMO": "from-kit"}, + Timeout: sandbox.Duration(5 * time.Second), +}) +if err != nil { + return err +} +// result: ExitCode, Stdout, Stderr +fmt.Println(result) +``` + + + + +## ExecResult + +Outcome of a finished command. + + + + +| Field | Description | +| ---------- | ------------------------------- | +| `exitCode` | Process exit status | +| `stdout` | Collected standard output bytes | +| `stderr` | Collected standard error bytes | + + + + +| Field | Description | +| ---------- | ------------------------------- | +| `ExitCode` | Process exit status | +| `Stdout` | Collected standard output bytes | +| `Stderr` | Collected standard error bytes | + + + diff --git a/website/content/docs/api/sandbox-info.mdx b/website/content/docs/api/sandbox-info.mdx new file mode 100644 index 00000000..fa5d4d92 --- /dev/null +++ b/website/content/docs/api/sandbox-info.mdx @@ -0,0 +1,99 @@ +--- +title: SandboxInfo +description: Metadata returned by info and lifecycle calls. +--- + +Returned by info and many lifecycle methods. Values are a **copy**; mutating them does not change the handle. Reported resources can differ from what you requested. + + + + +From [`sandbox.info()`](/docs/api/sandbox#read-metadata). + + + + +From [`instance.Info()`](/docs/api/sandbox#read-metadata). + + + + +## Fields + + + + +| Field | Description | +| ------------------ | ------------------------------------------------------- | +| `id` | Sandbox identifier | +| `provider` | Provider identifier | +| `name` | Display name when reported | +| `providerState` | Provider's native state string | +| `region` | Region when reported | +| `isolation` | Reported isolation config | +| `resources` | Reported size (`cpuCores`, `memoryMib`, …) | +| `labels` | Labels when reported | +| `createdAt` | Creation time when reported | +| `providerMetadata` | Extra provider metadata object | +| `state` | Portable [`SandboxState`](/docs/api/enums#sandboxstate) | +| `terminal` | Whether the lifecycle is permanently complete | + +**Example** + +```ts +const info = sandbox.info(); +// info: { id, provider, name?, providerState?, region?, isolation?, +// resources?, labels, createdAt?, providerMetadata?, state, terminal? } +console.log(info); +``` + + + + +| Field | Description | +| ------------------ | ------------------------------------------------------- | +| `Id` | Sandbox identifier | +| `Provider` | Provider identifier | +| `Name` | Display name when reported | +| `ProviderState` | Provider's native state string | +| `Region` | Region when reported | +| `Isolation` | Reported isolation config | +| `Resources` | Reported size (`CpuCores`, `MemoryMib`, …) | +| `Labels` | Labels when reported | +| `CreatedAt` | Creation time when reported | +| `ProviderMetadata` | Extra provider metadata object | +| `State` | Portable [`SandboxState`](/docs/api/enums#sandboxstate) | +| `Terminal` | Whether the lifecycle is permanently complete | + +**Example** + +```go +info := instance.Info() +// info: Id, Provider, Name, ProviderState, Region, Isolation, +// Resources, Labels, CreatedAt, ProviderMetadata, State, Terminal +fmt.Println(info) +``` + + + + +## ExitResult + +Returned by terminate. + + + + +| Field | Description | +| ---------- | -------------------------------------------------------------------------------- | +| `exitCode` | Process exit code when the call waited for completion. Absent when not reported. | + + + + +| Field | Description | +| ---------- | -------------------------------------------------------------------------------- | +| `ExitCode` | Process exit code when the call waited for completion. Absent when not reported. | + + + diff --git a/website/content/docs/api/sandbox.mdx b/website/content/docs/api/sandbox.mdx new file mode 100644 index 00000000..d92d5f4d --- /dev/null +++ b/website/content/docs/api/sandbox.mdx @@ -0,0 +1,527 @@ +--- +title: Sandbox +description: Handle for one sandbox — lifecycle, info, filesystem, and process. +--- + +Handle returned by create, get, or attach on [`Client`](/docs/api/client). Lifecycle methods update stored metadata when the call returns info. Closing the handle only releases local resources. + +## Properties + + + + +| Name | Type | Description | +| -------------- | ------------------------------------ | -------------------------------- | +| `id` | `string` | Sandbox identifier | +| `providerName` | `string` | Provider that owns this sandbox | +| `filesystem` | [`Filesystem`](/docs/api/filesystem) | File operations for this sandbox | +| `process` | [`Process`](/docs/api/process) | Command runner for this sandbox | + + + + +| Name | Signature | Description | +| -------------- | --------------------- | -------------------------------- | +| `ID` | `func () string` | Sandbox identifier | +| `ProviderName` | `func () string` | Provider that owns this sandbox | +| `Filesystem` | `func () *Filesystem` | File operations for this sandbox | +| `Process` | `func () *Process` | Command runner for this sandbox | + + + + +## Methods + +### Read metadata + + + + +```ts +info(): SandboxInfo +``` + +Returns a **copy** of current metadata. Mutating it does not change the handle. + +**Returns** + +[`SandboxInfo`](/docs/api/sandbox-info) + +**Example** + +```ts +const info = sandbox.info(); +// info: { id, provider, name?, providerState?, region?, isolation?, +// resources?, labels, createdAt?, providerMetadata?, state, terminal? } +console.log(info); +``` + + + + +```go +func (s *Sandbox) Info() *SandboxInfo +``` + +Returns a **copy** of current metadata. Mutating it does not change the handle. + +**Returns** + +[`*SandboxInfo`](/docs/api/sandbox-info) + +**Example** + +```go +info := instance.Info() +// info: Id, Provider, Name, ProviderState, Region, Isolation, +// Resources, Labels, CreatedAt, ProviderMetadata, State, Terminal +fmt.Println(info) +``` + + + + +### Capabilities + + + + +```ts +capabilities(): readonly LifecycleCapability[] +supports(capability: LifecycleCapability): boolean +``` + +Lists lifecycle operations this handle can attempt, or checks one. File and process calls are not capabilities—use `filesystem` and `process`. + +**Parameters** + +| Name | Type | Description | +| ------------ | ------------------------------------------------------------ | ------------------------------------------- | +| `capability` | [`LifecycleCapability`](/docs/api/enums#lifecyclecapability) | Capability to test (`Stop`, `Terminate`, …) | + +**Returns** + +Capability list, or `boolean` for `supports` + +**Example** + +```ts +if (!sandbox.supports(LifecycleCapability.Stop)) { + throw new Error(`cannot stop ${sandbox.id}`); +} +``` + + + + +```go +func (s *Sandbox) Capabilities() []LifecycleCapability +func (s *Sandbox) Supports(capability LifecycleCapability) bool +``` + +Lists lifecycle operations this handle can attempt, or checks one. + +**Parameters** + +| Name | Type | Description | +| ------------ | ------------------------------------------------------------ | ------------------ | +| `capability` | [`LifecycleCapability`](/docs/api/enums#lifecyclecapability) | Capability to test | + +**Returns** + +Capability slice, or `bool` for `Supports` + +**Example** + +```go +if !instance.Supports(sandbox.LifecycleCapabilityStop) { + return fmt.Errorf("cannot stop %s", instance.ID()) +} +``` + + + + +### Refresh + + + + +```ts +refresh(options?: OperationOptions): Promise +``` + +Reloads metadata from the provider into this handle. + +**Parameters** + +| Name | Type | Description | +| ---------- | ---------------------------------------- | ----------------------- | +| `options?` | [`OperationOptions`](#operation-options) | Call timeout and signal | + +**Returns** + +`Promise` — updated metadata (also stored on the handle) + + + + +```go +func (s *Sandbox) Refresh(ctx context.Context) error +``` + +Reloads metadata from the provider into this handle. Read it with `Info()` afterward. + +**Parameters** + +| Name | Type | Description | +| ----- | ----------------- | ------------------------- | +| `ctx` | `context.Context` | Cancellation and deadline | + +**Returns** + +`error` + + + + +### Start + + + + +```ts +start(options?: OperationOptions): Promise +``` + +Starts a stopped sandbox and stores the updated metadata. + +**Parameters** + +| Name | Type | Description | +| ---------- | ------------------ | ----------------------- | +| `options?` | `OperationOptions` | Call timeout and signal | + +**Returns** + +`Promise` + + + + +```go +func (s *Sandbox) Start(ctx context.Context, options *StartOptions) error +``` + +Starts a stopped sandbox and stores the updated metadata. + +**Parameters** + +| Name | Type | Description | +| --------- | ----------------- | ----------------------------------------- | +| `ctx` | `context.Context` | Cancellation and deadline | +| `options` | `*StartOptions` | Optional `Timeout` via `sandbox.Duration` | + +**Returns** + +`error` + + + + +### Stop + + + + +```ts +stop(options?: StopCallOptions): Promise +``` + +Stops a sandbox. Set `force: true` for an immediate stop. + +**Parameters** + +| Name | Type | Description | +| ---------- | ----------------- | -------------------------------------------------- | +| `options?` | `StopCallOptions` | `OperationOptions` plus optional `force?: boolean` | + +**Returns** + +`Promise` + +**Example** + +```ts +await sandbox.stop({ force: true, timeout: 60_000 }); +``` + + + + +```go +func (s *Sandbox) Stop(ctx context.Context, options *StopOptions) error +``` + +Stops a sandbox. Set `Force` with `Value(true)` for an immediate stop. + +**Parameters** + +| Name | Type | Description | +| --------- | ----------------- | --------------------------- | +| `ctx` | `context.Context` | Cancellation and deadline | +| `options` | `*StopOptions` | `Timeout`, optional `Force` | + +**Returns** + +`error` + +**Example** + +```go +err := instance.Stop(ctx, &sandbox.StopOptions{ + Force: sandbox.Value(true), + Timeout: sandbox.Duration(time.Minute), +}) +``` + + + + +### Pause + + + + +```ts +pause(options?: OperationOptions): Promise +``` + +Pauses a sandbox and stores the updated metadata. + +**Returns** + +`Promise` + + + + +```go +func (s *Sandbox) Pause(ctx context.Context, options *PauseOptions) error +``` + +Pauses a sandbox and stores the updated metadata. + +**Returns** + +`error` + + + + +### Terminate + + + + +```ts +terminate(options?: TerminateCallOptions): Promise +``` + +Ends the sandbox. With `wait: true`, the result may include `exitCode`. + +**Parameters** + +| Name | Type | Description | +| ---------- | ---------------------- | ------------------------------------------------- | +| `options?` | `TerminateCallOptions` | `OperationOptions` plus optional `wait?: boolean` | + +**Returns** + +`Promise` — `{ exitCode?: number }` + +**Example** + +```ts +const result = await sandbox.terminate({ wait: true }); +// result: { exitCode? } +console.log(result); +``` + + + + +```go +func (s *Sandbox) Terminate(ctx context.Context, options *TerminateOptions) (*ExitResult, error) +``` + +Ends the sandbox. With `Wait`, the result may include an exit code. + +**Parameters** + +| Name | Type | Description | +| --------- | ------------------- | -------------------------- | +| `ctx` | `context.Context` | Cancellation and deadline | +| `options` | `*TerminateOptions` | `Timeout`, optional `Wait` | + +**Returns** + +`(*ExitResult, error)` — `ExitCode *int32` when reported + +**Example** + +```go +result, err := instance.Terminate(ctx, &sandbox.TerminateOptions{ + Wait: sandbox.Value(true), +}) +// result: ExitCode +fmt.Println(result) +``` + + + + +### Archive + + + + +```ts +archive(options?: OperationOptions): Promise +``` + +Archives retained sandbox state and stores the updated metadata. + +**Returns** + +`Promise` + + + + +```go +func (s *Sandbox) Archive(ctx context.Context, options *ArchiveOptions) error +``` + +Archives retained sandbox state and stores the updated metadata. + +**Returns** + +`error` + + + + +### Delete + + + + +```ts +delete(options?: DeleteCallOptions): Promise +``` + +Deletes the cloud sandbox. Set `wait: true` to wait until deletion finishes. Unlike `close`, this removes the sandbox. + +**Parameters** + +| Name | Type | Description | +| ---------- | ------------------- | ------------------------------------------------- | +| `options?` | `DeleteCallOptions` | `OperationOptions` plus optional `wait?: boolean` | + +**Returns** + +`Promise` + + + + +```go +func (s *Sandbox) Delete(ctx context.Context, options *DeleteOptions) error +``` + +Deletes the cloud sandbox. Set `Wait` to wait until deletion finishes. + +**Parameters** + +| Name | Type | Description | +| --------- | ----------------- | -------------------------- | +| `ctx` | `context.Context` | Cancellation and deadline | +| `options` | `*DeleteOptions` | `Timeout`, optional `Wait` | + +**Returns** + +`error` + + + + +### Close + + + + +```ts +close(options?: OperationOptions): Promise +``` + +Releases local handle resources. The cloud sandbox is unchanged; you can keep using the handle afterward for provider calls until the sandbox is gone. + +**Returns** + +`Promise` + + + + +```go +func (s *Sandbox) Close(ctx context.Context) error +``` + +Releases local handle resources. The cloud sandbox is unchanged. + +**Returns** + +`error` + + + + +## Operation options + +Shared call options for TypeScript lifecycle and filesystem/process calls. + + + + +```ts +interface OperationOptions { + signal?: AbortSignal; + timeout?: number; // milliseconds +} + +type StopCallOptions = OperationOptions & { force?: boolean }; +type TerminateCallOptions = OperationOptions & { wait?: boolean }; +type DeleteCallOptions = OperationOptions & { wait?: boolean }; +``` + +| Field | Description | +| --------- | ----------------------------------------------------------------------------------- | +| `signal` | Abort the wait. The handle stays busy until the provider call settles. | +| `timeout` | Deadline for this call. Omitted → client default. `0` → no Kit deadline of its own. | +| `force` | On stop: request an immediate stop. | +| `wait` | On terminate/delete: wait until the operation finishes. | + + + + +Lifecycle option messages carry `Timeout *durationpb.Duration` (via `sandbox.Duration`). `StopOptions` adds `Force *bool`. `TerminateOptions` and `DeleteOptions` add `Wait *bool`. + +| Field | Description | +| --------- | -------------------------------------------------------------------------------- | +| `Timeout` | Call deadline. Nil → client default. Explicit zero → no Kit deadline of its own. | +| `Force` | On stop: `Value(true)` requests an immediate stop. | +| `Wait` | On terminate/delete: wait until finished. | + + + diff --git a/website/content/docs/concepts.mdx b/website/content/docs/concepts.mdx index 5b198e5d..61c3a2d9 100644 --- a/website/content/docs/concepts.mdx +++ b/website/content/docs/concepts.mdx @@ -133,9 +133,8 @@ console.log(sandbox.id); await sandbox.filesystem.writeFile("/tmp/note.txt", data); const result = await sandbox.process.run({ argv: ["echo", "hi"] }); -console.log(result.exitCode); -console.log(new TextDecoder().decode(result.stdout)); -console.log(new TextDecoder().decode(result.stderr)); +// result: { exitCode, stdout, stderr } +console.log(result); ``` @@ -150,9 +149,8 @@ console.log(sandbox.id); await sandbox.filesystem.writeFile("/tmp/note.txt", data); const result = await sandbox.process.run({ argv: ["echo", "hi"] }); -console.log(result.exitCode); -console.log(new TextDecoder().decode(result.stdout)); -console.log(new TextDecoder().decode(result.stderr)); +// result: { exitCode, stdout, stderr } +console.log(result); ``` @@ -180,9 +178,8 @@ result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ if err != nil { return err } -fmt.Println(result.GetExitCode()) -fmt.Println(string(result.GetStdout())) -fmt.Println(string(result.GetStderr())) +// result: ExitCode, Stdout, Stderr +fmt.Println(result) ``` @@ -207,9 +204,8 @@ result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ if err != nil { return err } -fmt.Println(result.GetExitCode()) -fmt.Println(string(result.GetStdout())) -fmt.Println(string(result.GetStderr())) +// result: ExitCode, Stdout, Stderr +fmt.Println(result) ``` @@ -408,4 +404,8 @@ _ = instance.Close(context.Background()) // local handle resources only Kinds, field paths, and handling: [Errors](/docs/errors). +## API surface + +Types, methods, parameters, and return values: [API reference](/docs/api) ([Client](/docs/api/client), [Sandbox](/docs/api/sandbox), [Filesystem](/docs/api/filesystem), [Process](/docs/api/process)). + Streaming I/O, interactive sessions, PTY, GPU, resize, and browsers are outside this SDK. diff --git a/website/content/docs/create.mdx b/website/content/docs/create.mdx index 4b3c7e2a..dbc87f20 100644 --- a/website/content/docs/create.mdx +++ b/website/content/docs/create.mdx @@ -467,15 +467,9 @@ Metadata from info is a **copy**. Mutating it does not change the sandbox. Repor ```ts const info = sandbox.info(); -console.log(info.id); -console.log(info.provider); -console.log(info.state); // portable lifecycle state -console.log(info.providerState); // provider's native string when set -console.log(info.name); -console.log(info.region); -console.log(info.resources?.cpuCores, info.resources?.memoryMib); -console.log(info.labels); -console.log(info.terminal); +// info: { id, provider, name?, providerState?, region?, isolation?, +// resources?, labels, createdAt?, providerMetadata?, state, terminal? } +console.log(info); ``` @@ -483,17 +477,9 @@ console.log(info.terminal); ```go info := instance.Info() -fmt.Println(info.Id) -fmt.Println(info.Provider) -fmt.Println(info.State) // portable lifecycle state -fmt.Println(info.GetProviderState()) // provider's native string when set -fmt.Println(info.GetName()) -fmt.Println(info.GetRegion()) -if info.Resources != nil { - fmt.Println(info.Resources.GetCpuCores(), info.Resources.GetMemoryMib()) -} -fmt.Println(info.Labels) -fmt.Println(info.GetTerminal()) +// info: Id, Provider, Name, ProviderState, Region, Isolation, +// Resources, Labels, CreatedAt, ProviderMetadata, State, Terminal +fmt.Println(info) ``` diff --git a/website/content/docs/errors.mdx b/website/content/docs/errors.mdx index ef03d604..4f0ee5a2 100644 --- a/website/content/docs/errors.mdx +++ b/website/content/docs/errors.mdx @@ -33,9 +33,9 @@ try { new Client({ provider, timeout: -1 }); } catch (error) { if (error instanceof SandboxError) { - console.error(error.kind); - console.error(error.field); - console.error(error.message); + // error: { kind, provider, operation, field, message, rule?, + // statusCode?, providerCode?, providerSource?, cause? } + console.error(error); } throw error; } @@ -59,9 +59,9 @@ client, err := sandbox.NewClient(provider, &sandbox.Config{ if err != nil { var detail *sandbox.Error if errors.As(err, &detail) { - fmt.Println(detail.Kind) - fmt.Println(detail.Field) - fmt.Println(detail.Message) + // detail: Kind, Provider, Operation, Field, Message, StatusCode, + // ProviderCode, ProviderSource, Rule (+ Unwrap cause) + fmt.Println(detail) } return err } @@ -218,7 +218,9 @@ try { // create may have succeeded before a later step failed — no id on the error if (knownId) { const sandbox = await client.get(knownId); - console.log(sandbox.info().state); + // info: { id, provider, name?, providerState?, region?, isolation?, + // resources?, labels, createdAt?, providerMetadata?, state, terminal? } + console.log(sandbox.info()); } throw error; } @@ -234,7 +236,9 @@ if err != nil { if knownID != "" { existing, getErr := client.Get(ctx, knownID) if getErr == nil { - fmt.Println(existing.Info().State) + // Info(): Id, Provider, Name, ProviderState, Region, Isolation, + // Resources, Labels, CreatedAt, ProviderMetadata, State, Terminal + fmt.Println(existing.Info()) } } return err diff --git a/website/content/docs/filesystem.mdx b/website/content/docs/filesystem.mdx index 29fab26d..f0ae0c7b 100644 --- a/website/content/docs/filesystem.mdx +++ b/website/content/docs/filesystem.mdx @@ -280,7 +280,9 @@ Returns entries in that one directory—no recursion. `size` is a byte count. ```ts const entries = await sandbox.filesystem.listDirectory("/tmp/kit-files"); -for (const entry of entries) console.log(entry.name, entry.size); +// each entry: { name, path, type, size?, mode?, permissions?, +// owner?, group?, modifiedAt? } +console.log(entries); ``` @@ -293,9 +295,8 @@ entries, err := instance.Filesystem().ListDirectory(ctx, "/tmp/kit-files", nil) if err != nil { return err } -for _, entry := range entries { - fmt.Println(entry.GetName(), entry.GetSize()) -} +// each entry: Name, Path, Type, Size, Mode, Permissions, Owner, Group, ModifiedAt +fmt.Println(entries) ``` @@ -318,7 +319,9 @@ for _, entry := range entries { ```ts const info = await sandbox.filesystem.stat("/tmp/note.txt"); -console.log(info.type, info.size, info.mode); +// info: { name, path, type, size?, mode?, permissions?, +// owner?, group?, modifiedAt? } +console.log(info); ``` @@ -331,7 +334,8 @@ info, err := instance.Filesystem().Stat(ctx, "/tmp/note.txt", nil) if err != nil { return err } -fmt.Println(info.GetType(), info.GetSize(), info.GetMode()) +// info: Name, Path, Type, Size, Mode, Permissions, Owner, Group, ModifiedAt +fmt.Println(info) ``` diff --git a/website/content/docs/index.mdx b/website/content/docs/index.mdx index 4605af12..f0326aa9 100644 --- a/website/content/docs/index.mdx +++ b/website/content/docs/index.mdx @@ -230,7 +230,8 @@ func main() { const result = await sandbox.process.run({ argv: ["echo", "hello from kit"], }); -console.log(result.exitCode, new TextDecoder().decode(result.stdout)); +// result: { exitCode, stdout, stderr } +console.log(result); ``` @@ -251,7 +252,8 @@ result, err := instance.Process().Run(context.Background(), &sandbox.ExecOptions if err != nil { log.Fatal(err) } -fmt.Println(result.GetExitCode(), string(result.GetStdout())) +// result: ExitCode, Stdout, Stderr +fmt.Println(result) ``` @@ -298,10 +300,11 @@ Sandbox paths are absolute. More: [Filesystem](/docs/filesystem). ## Next -| | | -| ------------------------ | ------------------------------------ | -| How the client works | [Concepts](/docs/concepts) | -| Daytona setup | [Daytona](/docs/daytona) | -| Modal setup | [Modal](/docs/modal) | -| Auth, region, timeouts | [Configuration](/docs/configuration) | -| Runnable sample projects | [Examples](/docs/examples) | +| | | +| ------------------------ | -------------------------------------------------------------------------------------- | +| How the client works | [Concepts](/docs/concepts) | +| Types and methods | [API reference](/docs/api) · [Client](/docs/api/client) · [Sandbox](/docs/api/sandbox) | +| Daytona setup | [Daytona](/docs/daytona) | +| Modal setup | [Modal](/docs/modal) | +| Auth, region, timeouts | [Configuration](/docs/configuration) | +| Runnable sample projects | [Examples](/docs/examples) | diff --git a/website/content/docs/lifecycle.mdx b/website/content/docs/lifecycle.mdx index c4f2f35c..4eb31003 100644 --- a/website/content/docs/lifecycle.mdx +++ b/website/content/docs/lifecycle.mdx @@ -55,7 +55,9 @@ Daytona may still reject a supported op for a given sandbox. Snippets assume a c ```ts const sandbox = await client.get(process.env.DAYTONA_SANDBOX_ID!); const info = await sandbox.refresh(); -console.log(sandbox.id, info.state); +// info: { id, provider, name?, providerState?, region?, isolation?, +// resources?, labels, createdAt?, providerMetadata?, state, terminal? } +console.log(info); ``` @@ -71,6 +73,9 @@ if err != nil { if err := instance.Refresh(ctx); err != nil { return err } +// Info(): Id, Provider, Name, ProviderState, Region, Isolation, +// Resources, Labels, CreatedAt, ProviderMetadata, State, Terminal +fmt.Println(instance.Info()) ``` @@ -126,7 +131,9 @@ if (!sandbox.supports(LifecycleCapability.Stop)) { } const info = await sandbox.stop({ timeout: 60_000 }); -console.log(sandbox.id, info.state); +// info: { id, provider, name?, providerState?, region?, isolation?, +// resources?, labels, createdAt?, providerMetadata?, state, terminal? } +console.log(info); ``` `timeout` is milliseconds. Pass `force: true` for an immediate stop. Check `supports` the same way before `start`, `pause`, or `archive`. @@ -155,6 +162,9 @@ if err := instance.Stop(ctx, &sandbox.StopOptions{ }); err != nil { return err } +// Info(): Id, Provider, Name, ProviderState, Region, Isolation, +// Resources, Labels, CreatedAt, ProviderMetadata, State, Terminal +fmt.Println(instance.Info()) ``` `Start`, `Pause`, and `Archive` take the same kind of options. @@ -226,7 +236,8 @@ if (!sandbox.supports(LifecycleCapability.Terminate)) { } const exit = await sandbox.terminate({ wait: true, timeout: 60_000 }); -console.log(sandbox.id, exit.exitCode); +// exit: { exitCode? } +console.log(exit); ``` `wait: true` polls until the sandbox exits or the timeout fires. The timeout is how long the client waits—Modal does not receive it as its own terminate timeout. @@ -257,7 +268,8 @@ exit, err := instance.Terminate(ctx, &sandbox.TerminateOptions{ if err != nil { return err } -fmt.Println(exit.GetExitCode()) +// exit: ExitCode +fmt.Println(exit) ``` @@ -299,18 +311,17 @@ defer client.Close(context.Background()) ```ts const info = sandbox.info(); -console.log(info.id); -console.log(info.state); // portable lifecycle state -console.log(info.providerState); // provider's native string when set -console.log(info.terminal); +// info: { id, provider, name?, providerState?, region?, isolation?, +// resources?, labels, createdAt?, providerMetadata?, state, terminal? } +console.log(info); ``` ```ts const refreshed = await sandbox.refresh(); -console.log(refreshed.state); -console.log(refreshed.providerState); +// refreshed: same SandboxInfo shape as info() +console.log(refreshed); ``` @@ -320,10 +331,9 @@ console.log(refreshed.providerState); ```go info := instance.Info() -fmt.Println(info.Id) -fmt.Println(info.State) // portable lifecycle state -fmt.Println(info.GetProviderState()) // provider's native string when set -fmt.Println(info.GetTerminal()) +// info: Id, Provider, Name, ProviderState, Region, Isolation, +// Resources, Labels, CreatedAt, ProviderMetadata, State, Terminal +fmt.Println(info) ``` @@ -332,9 +342,8 @@ fmt.Println(info.GetTerminal()) if err := instance.Refresh(ctx); err != nil { return err } -info = instance.Info() -fmt.Println(info.State) -fmt.Println(info.GetProviderState()) +// Info(): same SandboxInfo fields as above +fmt.Println(instance.Info()) ``` diff --git a/website/content/docs/meta.json b/website/content/docs/meta.json index d9a7128d..a9bca9b5 100644 --- a/website/content/docs/meta.json +++ b/website/content/docs/meta.json @@ -14,6 +14,8 @@ "process", "errors", "---Examples---", - "examples" + "examples", + "---API reference---", + "...api" ] } diff --git a/website/content/docs/process.mdx b/website/content/docs/process.mdx index 0f338e95..40975fa4 100644 --- a/website/content/docs/process.mdx +++ b/website/content/docs/process.mdx @@ -46,9 +46,8 @@ const result = await sandbox.process.run({ timeout: 5_000, // milliseconds; whole seconds required signal: AbortSignal.timeout(5_000), }); -console.log(result.exitCode); -console.log(new TextDecoder().decode(result.stdout)); -console.log(new TextDecoder().decode(result.stderr)); +// result: { exitCode, stdout, stderr } +console.log(result); ``` @@ -64,9 +63,8 @@ result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ if err != nil { return err } -fmt.Println(result.GetExitCode()) -fmt.Println(string(result.GetStdout())) -fmt.Println(string(result.GetStderr())) +// result: ExitCode, Stdout, Stderr +fmt.Println(result) ``` @@ -92,9 +90,8 @@ Daytona returns stdout only; `stderr` is empty. stdout may include merged stream const result = await sandbox.process.run({ argv: ["echo", "hello"], // sent as a POSIX-quoted shell string }); -console.log(result.exitCode); -console.log(new TextDecoder().decode(result.stdout)); -console.log(result.stderr.byteLength); // 0 — Daytona returns stdout only +// result: { exitCode, stdout, stderr } — stderr often empty on Daytona +console.log(result); ``` @@ -107,9 +104,8 @@ result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ if err != nil { return err } -fmt.Println(result.GetExitCode()) -fmt.Println(string(result.GetStdout())) -fmt.Println(len(result.GetStderr())) // 0 — Daytona returns stdout only +// result: ExitCode, Stdout, Stderr — Stderr often empty on Daytona +fmt.Println(result) ``` @@ -135,11 +131,8 @@ Modal returns both `stdout` and `stderr`. const result = await sandbox.process.run({ argv: ["echo", "hello"], // argument list as-is }); -console.log( - result.exitCode, - new TextDecoder().decode(result.stdout), - new TextDecoder().decode(result.stderr), -); +// result: { exitCode, stdout, stderr } +console.log(result); ``` @@ -149,7 +142,8 @@ console.log( result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ Argv: []string{"echo", "hello"}, // argument list as-is }) -fmt.Println(result.GetExitCode(), string(result.GetStdout()), string(result.GetStderr())) +// result: ExitCode, Stdout, Stderr +fmt.Println(result) ``` @@ -215,7 +209,8 @@ const result = await sandbox.process.run({ argv: ["echo", "hello from kit"], timeout: 5_000, }); -console.log(result.exitCode, new TextDecoder().decode(result.stdout)); +// result: { exitCode, stdout, stderr } +console.log(result); ``` @@ -236,7 +231,8 @@ result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ if err != nil { return err } -fmt.Printf("exit=%d stdout=%q\n", result.GetExitCode(), string(result.GetStdout())) +// result: ExitCode, Stdout, Stderr +fmt.Println(result) ``` @@ -253,8 +249,8 @@ Do not set `argv` on the same call. const result = await sandbox.process.run({ shell: 'echo "hello from shell"', }); -console.log(result.exitCode); -console.log(new TextDecoder().decode(result.stdout)); +// result: { exitCode, stdout, stderr } +console.log(result); ``` @@ -273,8 +269,8 @@ result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ if err != nil { return err } -fmt.Println(result.GetExitCode()) -fmt.Println(string(result.GetStdout())) +// result: ExitCode, Stdout, Stderr +fmt.Println(result) ``` @@ -293,7 +289,8 @@ const result = await sandbox.process.run({ workingDirectory: "/tmp", environment: { KIT_DEMO: "from-kit" }, }); -console.log(new TextDecoder().decode(result.stdout)); +// result: { exitCode, stdout, stderr } +console.log(result); ``` @@ -314,7 +311,8 @@ result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ if err != nil { return err } -fmt.Println(string(result.GetStdout())) +// result: ExitCode, Stdout, Stderr +fmt.Println(result) ``` diff --git a/website/src/lib/languages.ts b/website/src/lib/languages.ts new file mode 100644 index 00000000..97773413 --- /dev/null +++ b/website/src/lib/languages.ts @@ -0,0 +1,15 @@ +export const DOC_LANGUAGES = [ + { id: "typescript", label: "TypeScript" }, + { id: "go", label: "Go" }, +] as const; + +export type DocLanguageId = (typeof DOC_LANGUAGES)[number]["id"]; + +export const DEFAULT_DOC_LANGUAGE: DocLanguageId = "typescript"; + +/** Matches `` storage key in fumadocs tabs. */ +export const DOC_LANGUAGE_STORAGE_KEY = "language"; + +export function isDocLanguageId(value: string): value is DocLanguageId { + return DOC_LANGUAGES.some((language) => language.id === value); +} From f11554367c59cf1985c5ad1709f29ec3fa9caf68 Mon Sep 17 00:00:00 2001 From: Nabhag Motivaras <65061890+Nabhag8848@users.noreply.github.com> Date: Thu, 5 Nov 2026 22:28:31 +0530 Subject: [PATCH 3/5] Tighten website API docs for provider scope and clearer notes. Gate provider-only APIs and timeouts, drop export-style noise, add a language-following Note, and prefer Tailwind IDE class shorthands. Co-authored-by: Cursor --- .cursor/rules/tailwind-ide-suggestions.mdc | 31 ++++ website/content/docs/api/client.mdx | 72 ++++++-- website/content/docs/api/configuration.mdx | 68 ++++---- website/content/docs/api/create-options.mdx | 104 ++++++++++- website/content/docs/api/enums.mdx | 57 +++--- website/content/docs/api/errors.mdx | 4 - website/content/docs/api/filesystem.mdx | 39 +++-- website/content/docs/api/index.mdx | 44 +++-- website/content/docs/api/process.mdx | 46 +++-- website/content/docs/api/sandbox-info.mdx | 24 ++- website/content/docs/api/sandbox.mdx | 183 ++++++++++++-------- website/content/docs/concepts.mdx | 14 +- website/content/docs/configuration.mdx | 22 +-- website/content/docs/create.mdx | 4 +- website/content/docs/errors.mdx | 2 +- website/content/docs/filesystem.mdx | 4 +- website/content/docs/index.mdx | 8 +- website/content/docs/lifecycle.mdx | 16 +- website/content/docs/process.mdx | 14 +- website/src/components/language-context.tsx | 108 ++++++++++++ website/src/components/mdx.tsx | 4 + website/src/components/note.tsx | 29 ++++ website/src/components/tabs.tsx | 24 ++- website/src/lib/providers.ts | 13 ++ website/src/routes/__root.tsx | 5 +- 25 files changed, 680 insertions(+), 259 deletions(-) create mode 100644 .cursor/rules/tailwind-ide-suggestions.mdc create mode 100644 website/src/components/language-context.tsx create mode 100644 website/src/components/note.tsx diff --git a/.cursor/rules/tailwind-ide-suggestions.mdc b/.cursor/rules/tailwind-ide-suggestions.mdc new file mode 100644 index 00000000..6ed2c580 --- /dev/null +++ b/.cursor/rules/tailwind-ide-suggestions.mdc @@ -0,0 +1,31 @@ +--- +description: Apply Tailwind IDE/linter class shorthand suggestions when writing or editing className strings +alwaysApply: true +--- + +# Tailwind: use IDE shorthand suggestions + +When Tailwind CSS IntelliSense or the linter says a class **can be written as** +a shorter form, apply that suggestion. Do not leave the verbose form. + +## Do this + +- Prefer the suggested class over the longer arbitrary variant. +- Apply the rewrite while editing, not as a follow-up unless you only spotted it + in review. +- If several classes in the same string have suggestions, fix all of them. + +## Examples + +| Verbose | Prefer | +| ----------------------- | --------------- | +| `[&_:first-child]:mt-0` | `**:first:mt-0` | +| `[&_:last-child]:mb-0` | `**:last:mb-0` | + +Same rule for any other `can be written as …` Tailwind diagnostic the IDE shows. + +## Scope + +- Applies to `className`, `class`, `@apply`, and `cn(...)` / similar helpers. +- Do not invent shorthands the tooling did not suggest. +- Unrelated arbitrary variants with no IDE suggestion may stay as-is. diff --git a/website/content/docs/api/client.mdx b/website/content/docs/api/client.mdx index a661d51d..23938db8 100644 --- a/website/content/docs/api/client.mdx +++ b/website/content/docs/api/client.mdx @@ -1,9 +1,9 @@ --- title: Client -description: Construct a provider connection; create, get, attach, and close. +description: Construct a client; create, get or attach, and close. --- -Creates and opens sandbox handles for one provider. Closing the client closes the local connection; cloud sandboxes keep running. +Creates sandboxes and reopens them by id (`get` or `attach`). Closing the client only drops the local connection—cloud sandboxes keep running. ## Construction @@ -33,7 +33,7 @@ import { Client } from "@sandbox-kit/sandbox"; await using client = new Client({ provider, - timeout: 120_000, + timeout: 120_000, // default client deadline (ms) }); ``` @@ -63,7 +63,7 @@ Validates config and initializes the provider. Invalid config returns a nil clie ```go client, err := sandbox.NewClient(provider, &sandbox.Config{ - Timeout: sandbox.Duration(2 * time.Minute), + Timeout: sandbox.Duration(2 * time.Minute), // default client deadline }) if err != nil { return err @@ -104,7 +104,7 @@ defer client.Close(context.Background()) create(request?: CreateOptions, options?: OperationOptions): Promise ``` -Creates one sandbox and returns its handle. An empty request uses provider defaults when allowed. +Creates one sandbox and returns its handle. Omit the request (or pass `{}`) to use provider defaults. **Parameters** @@ -119,14 +119,30 @@ Creates one sandbox and returns its handle. An empty request uses provider defau **Example** + + +```ts +const sandbox = await client.create( + { source: { image: { reference: "daytonaio/playground:latest" } } }, + { timeout: 60_000 }, // deadline for this call (ms) +); +console.log(sandbox.id); +``` + + + + + ```ts const sandbox = await client.create( { source: { image: { reference: "alpine:3.21" } } }, - { timeout: 60_000 }, + { timeout: 60_000 }, // deadline for this call (ms) ); console.log(sandbox.id); ``` + + @@ -134,7 +150,7 @@ console.log(sandbox.id); func (c *Client) Create(ctx context.Context, request *CreateOptions) (*Sandbox, error) ``` -Creates one sandbox and returns its handle. A nil request uses provider defaults when allowed. +Creates one sandbox and returns its handle. A nil request uses provider defaults. **Parameters** @@ -149,19 +165,45 @@ Creates one sandbox and returns its handle. A nil request uses provider defaults **Example** + + +```go +instance, err := client.Create(ctx, &sandbox.CreateOptions{ + Source: &sandbox.SandboxSource{Kind: &sandbox.Image{ + Image: &sandbox.ImageSource{Reference: "daytonaio/playground:latest"}, + }}, + Provisioning: &sandbox.ProvisioningOptions{ + Timeout: sandbox.Duration(60 * time.Second), // deadline for this call + }, +}) +``` + + + + + ```go instance, err := client.Create(ctx, &sandbox.CreateOptions{ Source: &sandbox.SandboxSource{Kind: &sandbox.Image{ Image: &sandbox.ImageSource{Reference: "alpine:3.21"}, }}, + Provisioning: &sandbox.ProvisioningOptions{ + Timeout: sandbox.Duration(60 * time.Second), // deadline for this call + }, }) ``` + + + + ### get +Looks up a sandbox by id and returns a handle the provider has verified. + @@ -169,8 +211,6 @@ instance, err := client.Create(ctx, &sandbox.CreateOptions{ get(id: string, options?: OperationOptions): Promise ``` -Looks up a sandbox by id and returns a handle the provider has verified. - **Parameters** | Name | Type | Description | @@ -199,8 +239,6 @@ console.log(info); func (c *Client) Get(ctx context.Context, id string) (*Sandbox, error) ``` -Looks up a sandbox by id and returns a verified handle. - **Parameters** | Name | Type | Description | @@ -224,8 +262,14 @@ fmt.Println(instance.Info()) + + + + ### attach +Builds a handle for an existing sandbox id without a lookup round trip. It does not ask the provider whether that sandbox exists. + @@ -233,8 +277,6 @@ fmt.Println(instance.Info()) attach(id: string, options?: OperationOptions): Promise ``` -Builds a handle for an existing sandbox id without a lookup round trip. - **Parameters** | Name | Type | Description | @@ -259,8 +301,6 @@ const sandbox = await client.attach(knownId); func (c *Client) Attach(ctx context.Context, id string) (*Sandbox, error) ``` -Builds a handle for an existing sandbox id without a lookup round trip. - **Parameters** | Name | Type | Description | @@ -281,6 +321,8 @@ instance, err := client.Attach(ctx, knownID) + + ### close diff --git a/website/content/docs/api/configuration.mdx b/website/content/docs/api/configuration.mdx index 10e49d24..1a2cd392 100644 --- a/website/content/docs/api/configuration.mdx +++ b/website/content/docs/api/configuration.mdx @@ -22,14 +22,14 @@ type Config = { }; ``` -| Field | Type | Description | -| ----------- | -------------------- | ------------------------------------------------------------------- | -| `provider` | `Provider` | Provider constructor from a provider package | -| `auth?` | [`AuthInput`](#auth) | Credential set. Omit to use native env/profile resolution. | -| `endpoint?` | `string` | Control-plane URL override when allowed. Remote URLs must be HTTPS. | -| `region?` | `string` | Default region or target preference | -| `scope?` | [`Scope`](#scope) | App, environment, organization, or project | -| `timeout?` | `number` | Default deadline (ms) for calls that omit their own timeout | +| Field | Type | Description | +| ----------- | -------------------- | ---------------------------------------------------------------------- | +| `provider` | `Provider` | Provider constructor from a provider package | +| `auth?` | [`AuthInput`](#auth) | Credential set. Omit to use env/profile credentials from the provider. | +| `endpoint?` | `string` | API base URL override. Remote URLs must be HTTPS. | +| `region?` | `string` | Default region or target preference | +| `scope?` | [`Scope`](#scope) | App, environment, organization, or project | +| `timeout?` | `number` | Default deadline (ms) for calls that omit their own timeout | **Example** @@ -38,10 +38,15 @@ await using client = new Client({ provider, auth: { apiKey: { key: process.env.API_KEY! } }, region: "us", - timeout: 120_000, + timeout: 120_000, // default client deadline (ms) }); ``` + + This sets the client deadline only. If a create/start/stop/pause/delete call + omits its own timeout, Daytona still uses a **60s** default on its side. + + @@ -57,13 +62,13 @@ type Config struct { Pass `config` to `NewClient(provider, config)`. -| Field | Description | -| ---------- | ------------------------------------------------------------ | -| `Auth` | Credential set. Nil lets the native SDK resolve env/profile. | -| `Endpoint` | Control-plane URL override when allowed | -| `Region` | Default region or target preference | -| `Scope` | App, environment, organization, or project | -| `Timeout` | Default deadline via `sandbox.Duration` | +| Field | Description | +| ---------- | ------------------------------------------------------------------- | +| `Auth` | Credential set. Nil uses env/profile credentials from the provider. | +| `Endpoint` | API base URL override | +| `Region` | Default region or target preference | +| `Scope` | App, environment, organization, or project | +| `Timeout` | Default client deadline via `sandbox.Duration` | **Example** @@ -73,10 +78,15 @@ client, err := sandbox.NewClient(provider, &sandbox.Config{ ApiKey: &sandbox.APIKeyCredentials{Key: os.Getenv("API_KEY")}, }}, Region: sandbox.Value("us"), - Timeout: sandbox.Duration(2 * time.Minute), + Timeout: sandbox.Duration(2 * time.Minute), // default client deadline }) ``` + + This sets the client deadline only. If a create/start/stop/pause/delete call + omits its own timeout, Daytona still uses a **60s** default on its side. + + @@ -137,22 +147,22 @@ type AuthInput = -| Field | Description | -| ---------------- | ------------------------------------------------ | -| `appName` | Application name when the provider scopes by app | -| `environment` | Environment name (often `main`) when used | -| `organizationId` | Organization when the provider scopes by org | -| `projectId` | Project when the provider scopes by project | +| Field | Description | +| ---------------- | ------------------------------- | +| `appName` | Application name | +| `environment` | Environment name (often `main`) | +| `organizationId` | Organization id | +| `projectId` | Project id | -| Field | Description | -| ---------------- | ------------------------------------------------ | -| `AppName` | Application name when the provider scopes by app | -| `Environment` | Environment name (often `main`) when used | -| `OrganizationId` | Organization when the provider scopes by org | -| `ProjectId` | Project when the provider scopes by project | +| Field | Description | +| ---------------- | ------------------------------- | +| `AppName` | Application name | +| `Environment` | Environment name (often `main`) | +| `OrganizationId` | Organization id | +| `ProjectId` | Project id | diff --git a/website/content/docs/api/create-options.mdx b/website/content/docs/api/create-options.mdx index b8c5c129..a6fd5865 100644 --- a/website/content/docs/api/create-options.mdx +++ b/website/content/docs/api/create-options.mdx @@ -3,7 +3,7 @@ title: CreateOptions description: Create request body and nested option types. --- -Request body for [`Client.create`](/docs/api/client#create). Omitted fields keep provider defaults. Unsupported combinations fail in Kit before the provider call. +Request body for [`Client.create`](/docs/api/client#create). Omitted fields keep provider defaults. Unsupported fields fail before the provider call. ## CreateOptions @@ -50,6 +50,19 @@ Durations on this type are **milliseconds**. Allowlists under `network` are plai **Example** + + +```ts +const sandbox = await client.create({ + source: { image: { reference: "daytonaio/playground:latest" } }, + resources: { cpuCores: 1, memoryMib: 512n }, +}); +``` + + + + + ```ts const sandbox = await client.create({ source: { image: { reference: "alpine:3.21" } }, @@ -58,6 +71,8 @@ const sandbox = await client.create({ }); ``` + + @@ -101,6 +116,24 @@ Durations use `sandbox.Duration`. Optional numbers use `sandbox.Value`. **Example** + + +```go +instance, err := client.Create(ctx, &sandbox.CreateOptions{ + Source: &sandbox.SandboxSource{Kind: &sandbox.Image{ + Image: &sandbox.ImageSource{Reference: "daytonaio/playground:latest"}, + }}, + Resources: &sandbox.Resources{ + CpuCores: sandbox.Value(1.0), + MemoryMib: sandbox.Value(uint64(512)), + }, +}) +``` + + + + + ```go instance, err := client.Create(ctx, &sandbox.CreateOptions{ Source: &sandbox.SandboxSource{Kind: &sandbox.Image{ @@ -113,12 +146,14 @@ instance, err := client.Create(ctx, &sandbox.CreateOptions{ }) ``` + + ## Source -Set exactly one variant. +Set exactly one variant. Unsupported variants fail before the provider call. @@ -128,7 +163,7 @@ Set exactly one variant. | `image` | Container image `reference` | | `snapshot` | Snapshot `reference`, optional `kind` | | `warmPool` | Warm pool `reference` | -| `providerDefault` | Let the provider choose | +| `providerDefault` | Use the account default source | @@ -138,11 +173,24 @@ Set exactly one variant. | `Image` | Container image `Reference` | | `Snapshot` | Snapshot `Reference`, optional `Kind` | | `WarmPool` | Warm pool `Reference` | -| `ProviderDefault` | Let the provider choose | +| `ProviderDefault` | Use the account default source | + + Daytona accepts `image`, `snapshot`, and `providerDefault` when the account + allows them. Memory and disk requests must be whole GiB expressed as MiB; CPU + must be whole cores. Per-request `placement` is rejected—set client `region` + instead. + + + + Modal requires an `image` source (`providerDefault` is rejected). `diskMib` + and placement `target` are unsupported. Lifetime supports `maximumLifetime` + and `idleTerminate` only. + + ## RuntimeConfig @@ -237,6 +285,17 @@ Set exactly one variant. | `stoppedArchive` | Archive after stop | | `stoppedDelete` | Delete after stop | + + Daytona maps lifetime delays as **whole minutes**. Supported policies include + ephemeral, idle stop/pause, and stopped archive/delete (`stoppedArchive` max + 43200 minutes). `idleTerminate` is not used. + + + + Modal supports `maximumLifetime` (whole seconds, 1…86400) and `idleTerminate` + only. Ephemeral, idle stop/pause, and stopped archive/delete are rejected. + + @@ -250,6 +309,17 @@ Set exactly one variant. | `StoppedArchive` | Archive after stop | | `StoppedDelete` | Delete after stop | + + Daytona maps lifetime delays as **whole minutes**. Supported policies include + ephemeral, idle stop/pause, and stopped archive/delete (`StoppedArchive` max + 43200 minutes). `IdleTerminate` is not used. + + + + Modal supports `MaximumLifetime` (whole seconds, 1…86400) and `IdleTerminate` + only. Ephemeral, idle stop/pause, and stopped archive/delete are rejected. + + @@ -281,19 +351,41 @@ Set exactly one variant. | Field | Description | | -------------- | ----------------------------------------------------------------- | -| `timeout` | Create operation deadline | +| `timeout` | Deadline for the create call | | `queueTimeout` | How long creation may sit in a queue | | `waitFor` | [`WaitCondition`](/docs/api/enums#waitcondition) before returning | + + `timeout` must be whole seconds. Omit or `0` still leaves Daytona's **60s** + create default. `queueTimeout` is whole minutes and must be greater than 0 + when set. + + + + `timeout` is how long this create/ready wait may run. A ready wait needs a + positive timeout. `queueTimeout` is unsupported. + + | Field | Description | | -------------- | ----------------------------------------------------------------- | -| `Timeout` | Create operation deadline | +| `Timeout` | Deadline for the create call | | `QueueTimeout` | How long creation may sit in a queue | | `WaitFor` | [`WaitCondition`](/docs/api/enums#waitcondition) before returning | + + `Timeout` must be whole seconds. Omit or zero still leaves Daytona's **60s** + create default. `QueueTimeout` is whole minutes and must be greater than 0 + when set. + + + + `Timeout` is how long this create/ready wait may run. A ready wait needs a + positive timeout. `QueueTimeout` is unsupported. + + diff --git a/website/content/docs/api/enums.mdx b/website/content/docs/api/enums.mdx index bd39cd9d..39990869 100644 --- a/website/content/docs/api/enums.mdx +++ b/website/content/docs/api/enums.mdx @@ -3,40 +3,27 @@ title: Enums description: Shared public enums for create, lifecycle, and info. --- - - - -Exported as PascalCase const objects (for example `PolicyMode.After`, `SandboxState.Running`). - - - - -Exported as prefixed constants (for example `sandbox.PolicyModeAfter`, `sandbox.SandboxStateRunning`). - - - - ## SandboxState Portable lifecycle state on [`SandboxInfo`](/docs/api/sandbox-info). -| Value | Description | -| ------------- | ------------------------------------ | -| `Unknown` | State is not known or not yet mapped | -| `Queued` | Waiting to be scheduled | -| `Starting` | Booting or coming online | -| `Running` | Available for work | -| `Stopping` | Stop in progress | -| `Stopped` | Stopped and can be started again | -| `Pausing` | Pause in progress | -| `Paused` | Paused with retained state | -| `Archiving` | Archive in progress | -| `Archived` | Archived to colder storage | -| `Terminating` | Permanent end in progress | -| `Terminated` | Permanently ended | -| `Deleting` | Delete in progress | -| `Deleted` | Permanently removed | -| `Error` | Provider reported a failure state | +| Value | Description | +| ------------- | --------------------------------- | +| `Unknown` | State is not known | +| `Queued` | Waiting to be scheduled | +| `Starting` | Booting or coming online | +| `Running` | Available for work | +| `Stopping` | Stop in progress | +| `Stopped` | Stopped and can be started again | +| `Pausing` | Pause in progress | +| `Paused` | Paused with retained state | +| `Archiving` | Archive in progress | +| `Archived` | Archived to colder storage | +| `Terminating` | Permanent end in progress | +| `Terminated` | Permanently ended | +| `Deleting` | Delete in progress | +| `Deleted` | Permanently removed | +| `Error` | Provider reported a failure state | ## LifecycleCapability @@ -57,11 +44,11 @@ Used with [Capabilities](/docs/api/sandbox#capabilities). File and process calls Idle/stopped automatic actions under [`LifetimePolicy`](/docs/api/create-options#lifetimepolicy). -| Value | Description | -| ---------- | -------------------------------------------------- | -| `Default` | Omit the policy / leave it to the provider | -| `Disabled` | Turn the policy off | -| `After` | Run after the configured delay (`after` / `After`) | +| Value | Description | +| ---------- | ------------------------------------------ | +| `Default` | Omit the policy / leave it to the provider | +| `Disabled` | Turn the policy off | +| `After` | Run after the configured delay | ## WaitCondition diff --git a/website/content/docs/api/errors.mdx b/website/content/docs/api/errors.mdx index d4ae7c11..d963f68c 100644 --- a/website/content/docs/api/errors.mdx +++ b/website/content/docs/api/errors.mdx @@ -38,8 +38,6 @@ Throws from the client and sandbox handle. | `providerCode` | Provider's own error code when reported | | `providerSource` | Provider component when reported | -Exported field-path constants (for example `CreateFieldResourcesCpuCores`) match `field` for comparisons. - **Example** ```ts @@ -90,8 +88,6 @@ Use `errors.As(err, &detail)` to read fields. | `ProviderCode` | Provider's own error code when reported | | `ProviderSource` | Provider component when reported | -Exported field-path constants (for example `CreateFieldResourcesCpuCores`) match `Field` for comparisons. - **Example** ```go diff --git a/website/content/docs/api/filesystem.mdx b/website/content/docs/api/filesystem.mdx index 8eb6910a..0ec138e7 100644 --- a/website/content/docs/api/filesystem.mdx +++ b/website/content/docs/api/filesystem.mdx @@ -5,18 +5,10 @@ description: Read, write, copy, list, stat, and remove files in a sandbox. Paths inside the sandbox must be absolute. Local paths for copy may be relative. Omitted timeouts use the client default. - - - -Access as `sandbox.filesystem`. - - - - -Access as `instance.Filesystem()`. - - - + + Access as `sandbox.filesystem`. + Access as `instance.Filesystem()`. + ## Methods @@ -255,6 +247,19 @@ Creates the directory at `path`. An omitted `parents` flag is `true` (create mis `Promise` + + Daytona rejects `parents: false` before the call (field `parents`) and errors + if the directory already exists. Transfer timeouts must be whole seconds; + omit/zero passes `0` so Daytona does not apply its 30-minute upload/download + default. + + + + Modal accepts a directory that already exists. With `parents: false`, the + parent must already exist. Fractional-millisecond deadlines are allowed on + filesystem calls. + + @@ -274,6 +279,16 @@ Creates the directory at `path`. An omitted `Parents` flag is true. `error` + + Daytona rejects `Parents: false` before the call (field `parents`) and errors + if the directory already exists. + + + + Modal accepts a directory that already exists. With `Parents: false`, the + parent must already exist. + + diff --git a/website/content/docs/api/index.mdx b/website/content/docs/api/index.mdx index 19a8e71b..4fb47ebf 100644 --- a/website/content/docs/api/index.mdx +++ b/website/content/docs/api/index.mdx @@ -7,29 +7,27 @@ Public surface of the core sandbox package. Guides show how pieces fit together; Use the language tabs on each page. Unsupported calls return a typed error—see [Errors](/docs/api/errors) and the [Errors guide](/docs/errors). - - - -Package: `@sandbox-kit/sandbox`. Durations and timeouts are **milliseconds**. - - - - -Package: `github.com/sandbox-kit/kit/sdks/go/sandbox`. Durations use `sandbox.Duration`. Optional scalars use `sandbox.Value`. - - - + + + Package: `@sandbox-kit/sandbox`. Durations and timeouts are + **milliseconds**. + + + Package: `github.com/sandbox-kit/kit/sdks/go/sandbox`. Durations use + `sandbox.Duration`. Optional scalars use `sandbox.Value`. + + ## Modules -| Name | Description | -| ----------------------------------------- | ----------------------------------------------------------------- | -| [Client](/docs/api/client) | Construct a provider connection; create, get, or attach sandboxes | -| [Sandbox](/docs/api/sandbox) | Handle for one sandbox: lifecycle, info, filesystem, process | -| [Filesystem](/docs/api/filesystem) | Read, write, copy, list, stat, and remove files | -| [Process](/docs/api/process) | Run a command and collect exit code and output | -| [Client config](/docs/api/configuration) | Client config, auth, and scope types | -| [CreateOptions](/docs/api/create-options) | Create request body and nested option types | -| [SandboxInfo](/docs/api/sandbox-info) | Metadata returned by info and lifecycle calls | -| [Errors](/docs/api/errors) | Typed error shape and kinds | -| [Enums](/docs/api/enums) | Shared enums (`SandboxState`, `PolicyMode`, …) | +| Name | Description | +| ----------------------------------------- | ------------------------------------------------------------ | +| [Client](/docs/api/client) | Construct a provider connection; create and open sandboxes | +| [Sandbox](/docs/api/sandbox) | Handle for one sandbox: lifecycle, info, filesystem, process | +| [Filesystem](/docs/api/filesystem) | Read, write, copy, list, stat, and remove files | +| [Process](/docs/api/process) | Run a command and collect exit code and output | +| [Client config](/docs/api/configuration) | Client config, auth, and scope types | +| [CreateOptions](/docs/api/create-options) | Create request body and nested option types | +| [SandboxInfo](/docs/api/sandbox-info) | Metadata returned by info and lifecycle calls | +| [Errors](/docs/api/errors) | Typed error shape and kinds | +| [Enums](/docs/api/enums) | Shared enums (`SandboxState`, `PolicyMode`, …) | diff --git a/website/content/docs/api/process.mdx b/website/content/docs/api/process.mdx index 25940355..bc0eac08 100644 --- a/website/content/docs/api/process.mdx +++ b/website/content/docs/api/process.mdx @@ -5,18 +5,14 @@ description: Run a command in a sandbox and collect exit code and output. A non-zero exit code is **not** an error. Set exactly one of argv or shell. - - - -Access as `sandbox.process`. Set exactly one of `argv` or `shell`. - - - - -Access as `instance.Process()`. Set exactly one of `Argv` or `Shell`. - - - + + + Access as `sandbox.process`. Set exactly one of `argv` or `shell`. + + + Access as `instance.Process()`. Set exactly one of `Argv` or `Shell`. + + ## Methods @@ -39,7 +35,7 @@ Runs one command and waits for it to finish. | `options.shell?` | `string` | Shell command string. Mutually exclusive with `argv`. | | `options.workingDirectory?` | `string` | Absolute working directory inside the sandbox | | `options.environment?` | `Record` | Env vars for this command only | -| `options.timeout?` | `number` | Deadline in milliseconds; whole seconds required | +| `options.timeout?` | `number` | Kit + command deadline (ms); whole seconds required | | `options.signal?` | `AbortSignal` | Abort the wait | **Returns** @@ -115,6 +111,18 @@ Outcome of a finished command. | `stdout` | Collected standard output bytes | | `stderr` | Collected standard error bytes | + + Daytona returns stdout only; `stderr` is empty (stdout may include merged + streams). `argv` is sent as a POSIX-quoted shell string. Omit/zero timeout + sends `0` so Daytona does not apply its 10s command default. + + + + Modal returns both `stdout` and `stderr`. `argv` is passed as-is; `shell` runs + via `bash -c`. Omit/zero timeout omits Modal's `timeoutMs` (Modal rejects an + explicit 0). + + @@ -124,5 +132,17 @@ Outcome of a finished command. | `Stdout` | Collected standard output bytes | | `Stderr` | Collected standard error bytes | + + Daytona returns Stdout only; Stderr is empty (Stdout may include merged + streams). Argv is sent as a POSIX-quoted shell string. Omit/zero Timeout sends + 0 so Daytona does not apply its 10s command default. + + + + Modal returns both Stdout and Stderr. Argv is passed as-is; Shell runs via + `bash -c`. Omit/zero Timeout omits Modal's timeoutMs (Modal rejects an + explicit 0). + + diff --git a/website/content/docs/api/sandbox-info.mdx b/website/content/docs/api/sandbox-info.mdx index fa5d4d92..4fa390b4 100644 --- a/website/content/docs/api/sandbox-info.mdx +++ b/website/content/docs/api/sandbox-info.mdx @@ -5,18 +5,14 @@ description: Metadata returned by info and lifecycle calls. Returned by info and many lifecycle methods. Values are a **copy**; mutating them does not change the handle. Reported resources can differ from what you requested. - - - -From [`sandbox.info()`](/docs/api/sandbox#read-metadata). - - - - -From [`instance.Info()`](/docs/api/sandbox#read-metadata). - - - + + + From [`sandbox.info()`](/docs/api/sandbox#read-metadata). + + + From [`instance.Info()`](/docs/api/sandbox#read-metadata). + + ## Fields @@ -28,7 +24,7 @@ From [`instance.Info()`](/docs/api/sandbox#read-metadata). | `id` | Sandbox identifier | | `provider` | Provider identifier | | `name` | Display name when reported | -| `providerState` | Provider's native state string | +| `providerState` | Raw state string from the cloud | | `region` | Region when reported | | `isolation` | Reported isolation config | | `resources` | Reported size (`cpuCores`, `memoryMib`, …) | @@ -55,7 +51,7 @@ console.log(info); | `Id` | Sandbox identifier | | `Provider` | Provider identifier | | `Name` | Display name when reported | -| `ProviderState` | Provider's native state string | +| `ProviderState` | Raw state string from the cloud | | `Region` | Region when reported | | `Isolation` | Reported isolation config | | `Resources` | Reported size (`CpuCores`, `MemoryMib`, …) | diff --git a/website/content/docs/api/sandbox.mdx b/website/content/docs/api/sandbox.mdx index d92d5f4d..b970b5cc 100644 --- a/website/content/docs/api/sandbox.mdx +++ b/website/content/docs/api/sandbox.mdx @@ -3,7 +3,7 @@ title: Sandbox description: Handle for one sandbox — lifecycle, info, filesystem, and process. --- -Handle returned by create, get, or attach on [`Client`](/docs/api/client). Lifecycle methods update stored metadata when the call returns info. Closing the handle only releases local resources. +Handle from [`Client.create`](/docs/api/client#create), [`get`](/docs/api/client#get), or [`attach`](/docs/api/client#attach). Lifecycle methods that return info also update the handle. `close` only drops local resources—the cloud sandbox keeps running. Call `supports` before a lifecycle method that might be unavailable. ## Properties @@ -105,12 +105,26 @@ Capability list, or `boolean` for `supports` **Example** + + ```ts if (!sandbox.supports(LifecycleCapability.Stop)) { throw new Error(`cannot stop ${sandbox.id}`); } ``` + + + + +```ts +if (!sandbox.supports(LifecycleCapability.Terminate)) { + throw new Error(`cannot terminate ${sandbox.id}`); +} +``` + + + @@ -133,15 +147,31 @@ Capability slice, or `bool` for `Supports` **Example** + + ```go if !instance.Supports(sandbox.LifecycleCapabilityStop) { return fmt.Errorf("cannot stop %s", instance.ID()) } ``` + + + + +```go +if !instance.Supports(sandbox.LifecycleCapabilityTerminate) { + return fmt.Errorf("cannot terminate %s", instance.ID()) +} +``` + + + + + ### Refresh @@ -253,7 +283,7 @@ Stops a sandbox. Set `force: true` for an immediate stop. **Example** ```ts -await sandbox.stop({ force: true, timeout: 60_000 }); +await sandbox.stop({ force: true, timeout: 60_000 }); // call deadline (ms) ``` @@ -281,7 +311,7 @@ Stops a sandbox. Set `Force` with `Value(true)` for an immediate stop. ```go err := instance.Stop(ctx, &sandbox.StopOptions{ Force: sandbox.Value(true), - Timeout: sandbox.Duration(time.Minute), + Timeout: sandbox.Duration(time.Minute), // call deadline }) ``` @@ -319,78 +349,53 @@ Pauses a sandbox and stores the updated metadata. -### Terminate +### Archive ```ts -terminate(options?: TerminateCallOptions): Promise +archive(options?: OperationOptions): Promise ``` -Ends the sandbox. With `wait: true`, the result may include `exitCode`. - -**Parameters** - -| Name | Type | Description | -| ---------- | ---------------------- | ------------------------------------------------- | -| `options?` | `TerminateCallOptions` | `OperationOptions` plus optional `wait?: boolean` | +Archives retained sandbox state and stores the updated metadata. **Returns** -`Promise` — `{ exitCode?: number }` - -**Example** - -```ts -const result = await sandbox.terminate({ wait: true }); -// result: { exitCode? } -console.log(result); -``` +`Promise` ```go -func (s *Sandbox) Terminate(ctx context.Context, options *TerminateOptions) (*ExitResult, error) +func (s *Sandbox) Archive(ctx context.Context, options *ArchiveOptions) error ``` -Ends the sandbox. With `Wait`, the result may include an exit code. - -**Parameters** - -| Name | Type | Description | -| --------- | ------------------- | -------------------------- | -| `ctx` | `context.Context` | Cancellation and deadline | -| `options` | `*TerminateOptions` | `Timeout`, optional `Wait` | +Archives retained sandbox state and stores the updated metadata. **Returns** -`(*ExitResult, error)` — `ExitCode *int32` when reported - -**Example** - -```go -result, err := instance.Terminate(ctx, &sandbox.TerminateOptions{ - Wait: sandbox.Value(true), -}) -// result: ExitCode -fmt.Println(result) -``` +`error` -### Archive +### Delete ```ts -archive(options?: OperationOptions): Promise +delete(options?: DeleteCallOptions): Promise ``` -Archives retained sandbox state and stores the updated metadata. +Deletes the cloud sandbox. Set `wait: true` to wait until deletion finishes. Unlike `close`, this removes the sandbox. + +**Parameters** + +| Name | Type | Description | +| ---------- | ------------------- | ------------------------------------------------- | +| `options?` | `DeleteCallOptions` | `OperationOptions` plus optional `wait?: boolean` | **Returns** @@ -400,10 +405,17 @@ Archives retained sandbox state and stores the updated metadata. ```go -func (s *Sandbox) Archive(ctx context.Context, options *ArchiveOptions) error +func (s *Sandbox) Delete(ctx context.Context, options *DeleteOptions) error ``` -Archives retained sandbox state and stores the updated metadata. +Deletes the cloud sandbox. Set `Wait` to wait until deletion finishes. + +**Parameters** + +| Name | Type | Description | +| --------- | ----------------- | -------------------------- | +| `ctx` | `context.Context` | Cancellation and deadline | +| `options` | `*DeleteOptions` | `Timeout`, optional `Wait` | **Returns** @@ -412,50 +424,79 @@ Archives retained sandbox state and stores the updated metadata. -### Delete +If you omit the timeout (or pass `0`), Daytona still uses its own **60s** default for create, start, stop, pause, and delete. Pass a positive whole-second timeout to override. Fractional seconds are rejected. + + + + + +### Terminate ```ts -delete(options?: DeleteCallOptions): Promise +terminate(options?: TerminateCallOptions): Promise ``` -Deletes the cloud sandbox. Set `wait: true` to wait until deletion finishes. Unlike `close`, this removes the sandbox. +Ends the sandbox. With `wait: true`, the result may include `exitCode`. **Parameters** -| Name | Type | Description | -| ---------- | ------------------- | ------------------------------------------------- | -| `options?` | `DeleteCallOptions` | `OperationOptions` plus optional `wait?: boolean` | +| Name | Type | Description | +| ---------- | ---------------------- | ------------------------------------------------- | +| `options?` | `TerminateCallOptions` | `OperationOptions` plus optional `wait?: boolean` | **Returns** -`Promise` +`Promise` — `{ exitCode?: number }` + +**Example** + +```ts +const result = await sandbox.terminate({ wait: true, timeout: 60_000 }); +// result: { exitCode? } — timeout is how long this call may wait +console.log(result); +``` ```go -func (s *Sandbox) Delete(ctx context.Context, options *DeleteOptions) error +func (s *Sandbox) Terminate(ctx context.Context, options *TerminateOptions) (*ExitResult, error) ``` -Deletes the cloud sandbox. Set `Wait` to wait until deletion finishes. +Ends the sandbox. With `Wait`, the result may include an exit code. **Parameters** -| Name | Type | Description | -| --------- | ----------------- | -------------------------- | -| `ctx` | `context.Context` | Cancellation and deadline | -| `options` | `*DeleteOptions` | `Timeout`, optional `Wait` | +| Name | Type | Description | +| --------- | ------------------- | -------------------------- | +| `ctx` | `context.Context` | Cancellation and deadline | +| `options` | `*TerminateOptions` | `Timeout`, optional `Wait` | **Returns** -`error` +`(*ExitResult, error)` — `ExitCode *int32` when reported + +**Example** + +```go +result, err := instance.Terminate(ctx, &sandbox.TerminateOptions{ + Wait: sandbox.Value(true), + Timeout: sandbox.Duration(time.Minute), // how long this call may wait +}) +// result: ExitCode +fmt.Println(result) +``` +`timeout` / `Timeout` caps how long this call waits. It is not sent to Modal as a separate terminate setting. + + + ### Close @@ -505,23 +546,23 @@ type TerminateCallOptions = OperationOptions & { wait?: boolean }; type DeleteCallOptions = OperationOptions & { wait?: boolean }; ``` -| Field | Description | -| --------- | ----------------------------------------------------------------------------------- | -| `signal` | Abort the wait. The handle stays busy until the provider call settles. | -| `timeout` | Deadline for this call. Omitted → client default. `0` → no Kit deadline of its own. | -| `force` | On stop: request an immediate stop. | -| `wait` | On terminate/delete: wait until the operation finishes. | +| Field | Description | +| --------- | ---------------------------------------------------------------------------- | +| `signal` | Abort the wait. The handle stays busy until the in-flight call finishes. | +| `timeout` | Deadline for this call (ms). Omitted → client default. `0` → no deadline. | +| `force` | On stop: request an immediate stop. | +| `wait` | On terminate/delete: wait until the operation finishes. | Lifecycle option messages carry `Timeout *durationpb.Duration` (via `sandbox.Duration`). `StopOptions` adds `Force *bool`. `TerminateOptions` and `DeleteOptions` add `Wait *bool`. -| Field | Description | -| --------- | -------------------------------------------------------------------------------- | -| `Timeout` | Call deadline. Nil → client default. Explicit zero → no Kit deadline of its own. | -| `Force` | On stop: `Value(true)` requests an immediate stop. | -| `Wait` | On terminate/delete: wait until finished. | +| Field | Description | +| --------- | -------------------------------------------------------------------------- | +| `Timeout` | Deadline for this call. Nil → client default. Explicit zero → no deadline. | +| `Force` | On stop: `Value(true)` requests an immediate stop. | +| `Wait` | On terminate/delete: wait until finished. | diff --git a/website/content/docs/concepts.mdx b/website/content/docs/concepts.mdx index 61c3a2d9..ebcf3257 100644 --- a/website/content/docs/concepts.mdx +++ b/website/content/docs/concepts.mdx @@ -22,7 +22,7 @@ await using client = new Client({ provider: daytona(), auth: { apiKey: { key: process.env.DAYTONA_API_KEY! } }, region: process.env.DAYTONA_TARGET, - timeout: 120_000, // milliseconds + timeout: 120_000, // default client deadline (ms) }); ``` @@ -47,7 +47,7 @@ await using client = new Client({ environment: "main", }, region: process.env.MODAL_REGION, - timeout: 120_000, // milliseconds + timeout: 120_000, // default client deadline (ms) }); ``` @@ -118,7 +118,7 @@ if err != nil { ## Sandbox handle -`create` and the provider's open-by-id method return a handle. Use that handle for lifecycle, filesystem, and process calls. +`create` returns a handle. To reopen an existing sandbox, use `get` or `attach`—see [Lifecycle](/docs/lifecycle). Use the handle for lifecycle, filesystem, and process calls. @@ -217,7 +217,7 @@ fmt.Println(result) Each provider is its own package. Pass it into the client. Auth, create defaults, and which lifecycle calls exist depend on the provider; the client methods stay the same. -The client invokes the provider's native SDK—it does not sit in front of a separate Kit service. +The client talks to Daytona or Modal directly. There is no separate Kit cloud in the middle. @@ -313,7 +313,7 @@ Setup: [Modal](/docs/modal). ## Capabilities -Kit rejects unsupported calls before talking to the provider. A provider can still refuse a supported call for a particular sandbox; that comes back as a provider error. +Unsupported calls fail before anything reaches the cloud. The cloud can still refuse a supported call for a particular sandbox; that comes back as a provider error. @@ -353,7 +353,7 @@ const pending = sandbox.process.run({ argv: ["sleep", "30"], signal: ac.signal, }); -ac.abort(); // rejects the await; handle stays busy until the provider call settles +ac.abort(); // rejects the await; handle stays busy until the in-flight call finishes await pending.catch(() => {}); ``` @@ -366,7 +366,7 @@ defer cancel() go func() { time.Sleep(10 * time.Millisecond) - cancel() // ends the wait; handle stays busy until the provider call settles + cancel() // ends the wait; handle stays busy until the in-flight call finishes }() _, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ diff --git a/website/content/docs/configuration.mdx b/website/content/docs/configuration.mdx index 14f2363a..c5381fb6 100644 --- a/website/content/docs/configuration.mdx +++ b/website/content/docs/configuration.mdx @@ -13,7 +13,7 @@ import { Client } from "@sandbox-kit/sandbox"; await using client = new Client({ provider, - timeout: 120_000, // milliseconds + timeout: 120_000, // default client deadline (ms) }); ``` @@ -28,7 +28,7 @@ import ( ) client, err := sandbox.NewClient(provider, &sandbox.Config{ - Timeout: sandbox.Duration(2 * time.Minute), + Timeout: sandbox.Duration(2 * time.Minute), // default client deadline }) if err != nil { return err @@ -43,9 +43,9 @@ if err != nil { | `provider` | Provider constructor | | `auth` | One of `apiKey`, `tokenPair`, `bearerToken`, `oauthRefresh`. Omit to use provider env creds | | `scope` | App, environment, or organization | -| `endpoint` | Provider control-plane URL when that provider allows it | +| `endpoint` | API base URL override | | `region` | Target / default placement | -| `timeout` | Default deadline | +| `timeout` | Default deadline for calls that omit their own | Provider setup: [Daytona](/docs/daytona). @@ -291,7 +291,7 @@ client, err := sandbox.NewClient(modal.New(), config) `timeout` on the client is the default deadline. Create and lifecycle calls can override it. -Explicit zero adds no Kit deadline of its own. A context deadline or abort signal that fires earlier still wins. +Explicit zero means no deadline from the client. A context deadline or abort signal that fires earlier still wins. @@ -301,12 +301,12 @@ Explicit zero adds no Kit deadline of its own. A context deadline or abort signa ```ts await using client = new Client({ provider: daytona(), - timeout: 120_000, // default deadline for calls that omit timeout + timeout: 120_000, // default for calls that omit timeout }); const sandbox = await client.create( { source: { image: { reference: "daytonaio/playground:latest" } } }, - { timeout: 60_000 }, // override for this call; 0 = no Kit deadline + { timeout: 60_000 }, // override for this call; 0 = no deadline ); ``` @@ -317,12 +317,12 @@ const sandbox = await client.create( ```ts await using client = new Client({ provider: modal(), - timeout: 120_000, // default deadline for calls that omit timeout + timeout: 120_000, // default for calls that omit timeout }); const sandbox = await client.create( { source: { image: { reference: "alpine:3.21" } } }, - { timeout: 60_000 }, // override for this call; 0 = no Kit deadline + { timeout: 60_000 }, // override for this call; 0 = no deadline ); ``` @@ -346,7 +346,7 @@ instance, err := client.Create(ctx, &sandbox.CreateOptions{ Image: &sandbox.ImageSource{Reference: "daytonaio/playground:latest"}, }}, Provisioning: &sandbox.ProvisioningOptions{ - Timeout: sandbox.Duration(60 * time.Second), // override; 0 = no Kit deadline + Timeout: sandbox.Duration(60 * time.Second), // override; 0 = no deadline }, }) ``` @@ -368,7 +368,7 @@ instance, err := client.Create(ctx, &sandbox.CreateOptions{ Image: &sandbox.ImageSource{Reference: "alpine:3.21"}, }}, Provisioning: &sandbox.ProvisioningOptions{ - Timeout: sandbox.Duration(60 * time.Second), // override; 0 = no Kit deadline + Timeout: sandbox.Duration(60 * time.Second), // override; 0 = no deadline }, }) ``` diff --git a/website/content/docs/create.mdx b/website/content/docs/create.mdx index dbc87f20..19165986 100644 --- a/website/content/docs/create.mdx +++ b/website/content/docs/create.mdx @@ -10,7 +10,7 @@ Create returns a sandbox handle. Build the client first. Provider setup: [Modal](/docs/modal). -Omitted fields keep provider defaults. Unsupported fields fail in Kit before the provider call. +Omitted fields keep provider defaults. Unsupported fields fail before the provider call. @@ -404,7 +404,7 @@ Samples: [Examples](/docs/examples). Set cloud and region on `placement`. A ready wait needs a probe and a positive timeout. -Disk size, a control-plane endpoint, and stop / pause / archive / delete policies are rejected. +Disk size, an API endpoint override, and stop / pause / archive / delete policies are rejected. diff --git a/website/content/docs/errors.mdx b/website/content/docs/errors.mdx index 4f0ee5a2..a56d4661 100644 --- a/website/content/docs/errors.mdx +++ b/website/content/docs/errors.mdx @@ -116,7 +116,7 @@ try { } ``` -The provider's own error is `error.cause`. +The underlying cloud error is `error.cause`. diff --git a/website/content/docs/filesystem.mdx b/website/content/docs/filesystem.mdx index f0ae0c7b..c12bb042 100644 --- a/website/content/docs/filesystem.mdx +++ b/website/content/docs/filesystem.mdx @@ -49,7 +49,7 @@ err = instance.Filesystem().CopyFromLocal(ctx, "note.txt", "/tmp/note.txt", nil) ## Timeouts -Omit timeout → client deadline. Explicit `0` → no extra Kit deadline. +Omit timeout → client deadline. Explicit `0` → no deadline from the client. @@ -304,7 +304,7 @@ fmt.Println(entries) ## Read metadata -`stat` returns one path. `mode` is an octal string when supplied (`0644`). `permissions`, `owner`, `group`, and `modifiedAt` appear when the provider sends them. +`stat` returns one path. `mode` is an octal string when supplied (`0644`). `permissions`, `owner`, `group`, and `modifiedAt` appear when the cloud returns them. A symlink path is reported as a file or a directory. diff --git a/website/content/docs/index.mdx b/website/content/docs/index.mdx index f0326aa9..604186b1 100644 --- a/website/content/docs/index.mdx +++ b/website/content/docs/index.mdx @@ -85,7 +85,7 @@ import { Client } from "@sandbox-kit/sandbox"; await using client = new Client({ provider: daytona(), auth: { apiKey: { key: process.env.DAYTONA_API_KEY! } }, - timeout: 120_000, + timeout: 120_000, // default client deadline (ms) }); const sandbox = await client.create(); @@ -112,7 +112,7 @@ await using client = new Client({ appName: process.env.MODAL_APP_NAME!, environment: process.env.MODAL_ENVIRONMENT ?? "main", }, - timeout: 120_000, + timeout: 120_000, // default client deadline (ms) }); const sandbox = await client.create({ @@ -294,8 +294,8 @@ Sandbox paths are absolute. More: [Filesystem](/docs/filesystem). `client.close()` and handle `close` only release local resources. The cloud - sandbox keeps running until you stop, terminate, archive, delete, or a - lifetime policy ends it. See [Concepts](/docs/concepts). + sandbox keeps running until an explicit lifecycle call or a lifetime policy + ends it. See [Concepts](/docs/concepts) and [Lifecycle](/docs/lifecycle). ## Next diff --git a/website/content/docs/lifecycle.mdx b/website/content/docs/lifecycle.mdx index 4eb31003..40a9da20 100644 --- a/website/content/docs/lifecycle.mdx +++ b/website/content/docs/lifecycle.mdx @@ -3,7 +3,7 @@ title: Lifecycle description: get, attach, start, stop, pause, archive, delete, terminate, and close. --- -Operate on a handle from `create`, or open one by id. Unsupported ops fail before the provider call. +Operate on a handle from `create`, or reopen one with `get` / `attach`. Unsupported calls fail before the provider runs. @@ -304,7 +304,19 @@ defer client.Close(context.Background()) ## Read the state -`info.state` is the portable state; the provider's native string sits beside it. After a lifecycle call, refresh or re-fetch before assuming the sandbox is stopped or gone. A failed call can still mean the provider already changed state. See [Errors](/docs/errors). +`info.state` is the portable lifecycle state. `providerState` is the raw string from +the cloud when one is set. A failed call can still mean the cloud already changed +state. See [Errors](/docs/errors). + + + After a lifecycle call, call `refresh` (or `get` again) before assuming the + sandbox is stopped or gone. + + + + Use the info returned by the call, or `info()` on the handle. There is no + `refresh` or `get` on Modal. + diff --git a/website/content/docs/process.mdx b/website/content/docs/process.mdx index 40975fa4..7667d8bb 100644 --- a/website/content/docs/process.mdx +++ b/website/content/docs/process.mdx @@ -8,12 +8,14 @@ Run a command on an open handle. You need a sandbox from [create](/docs/create) -Call `sandbox.process.run`. The result includes `exitCode`, `stdout`, and `stderr`. +Call `sandbox.process.run`. The result includes `exitCode`, `stdout`, and `stderr` +(providers may leave `stderr` empty—see [How providers run it](#how-providers-run-it)). -Call `Process().Run`. The result includes `exit_code`, `stdout`, and `stderr`. +Call `Process().Run`. The result includes `exit_code`, `stdout`, and `stderr` +(providers may leave `stderr` empty—see [How providers run it](#how-providers-run-it)). @@ -166,13 +168,13 @@ Omit or zero also means no separate provider command limit. -Abort rejects the `await`; the remote command may keep running. The handle stays busy until that provider call settles. +Abort rejects the `await`; the remote command may keep running. The handle stays busy until the in-flight call finishes. ```ts const ac = new AbortController(); const pending = sandbox.process.run({ argv: ["sleep", "30"], - timeout: 0, // no Kit deadline; still abortable + timeout: 0, // no deadline; still abortable signal: ac.signal, }); ac.abort(); @@ -182,7 +184,7 @@ await pending.catch(() => {}); -Cancel the context to end the wait. The handle stays busy until that provider call settles. +Cancel the context to end the wait. The handle stays busy until the in-flight call finishes. ```go ctx, cancel := context.WithCancel(ctx) @@ -190,7 +192,7 @@ defer cancel() result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ Argv: []string{"sleep", "30"}, - Timeout: sandbox.Duration(0), // no Kit deadline; still cancelable via ctx + Timeout: sandbox.Duration(0), // no deadline; still cancelable via ctx }) _ = result _ = err diff --git a/website/src/components/language-context.tsx b/website/src/components/language-context.tsx new file mode 100644 index 00000000..0f310fe5 --- /dev/null +++ b/website/src/components/language-context.tsx @@ -0,0 +1,108 @@ +"use client"; + +import { + createContext, + useCallback, + useContext, + useLayoutEffect, + useMemo, + useState, + type ReactNode, +} from "react"; +import { + DEFAULT_DOC_LANGUAGE, + DOC_LANGUAGE_STORAGE_KEY, + DOC_LANGUAGES, + isDocLanguageId, + type DocLanguageId, +} from "@/lib/languages"; + +type LanguageContextValue = { + language: DocLanguageId; + setLanguage: (id: DocLanguageId) => void; + languages: typeof DOC_LANGUAGES; +}; + +const LanguageContext = createContext(null); + +function readStoredLanguage(): DocLanguageId { + if (typeof window === "undefined") return DEFAULT_DOC_LANGUAGE; + try { + const stored = + localStorage.getItem(DOC_LANGUAGE_STORAGE_KEY) ?? + sessionStorage.getItem(DOC_LANGUAGE_STORAGE_KEY); + if (stored && isDocLanguageId(stored)) return stored; + } catch { + // ignore + } + return DEFAULT_DOC_LANGUAGE; +} + +export function LanguageProvider({ children }: { children: ReactNode }) { + const [language, setLanguageState] = + useState(DEFAULT_DOC_LANGUAGE); + + useLayoutEffect(() => { + setLanguageState(readStoredLanguage()); + }, []); + + const setLanguage = useCallback((id: DocLanguageId) => { + setLanguageState(id); + try { + sessionStorage.setItem(DOC_LANGUAGE_STORAGE_KEY, id); + localStorage.setItem(DOC_LANGUAGE_STORAGE_KEY, id); + } catch { + // ignore + } + }, []); + + const value = useMemo( + () => ({ + language, + setLanguage, + languages: DOC_LANGUAGES, + }), + [language, setLanguage], + ); + + return ( + + {children} + + ); +} + +export function useDocLanguage(): LanguageContextValue { + const ctx = useContext(LanguageContext); + if (!ctx) { + throw new Error("useDocLanguage must be used within LanguageProvider"); + } + return ctx; +} + +export function useDocLanguageOptional(): LanguageContextValue | null { + return useContext(LanguageContext); +} + +export function resolveDocLanguageId(value: string): DocLanguageId | null { + const normalized = value.toLowerCase().replace(/\s+/g, "-"); + if (isDocLanguageId(normalized)) return normalized; + return null; +} + +/** Show children only for the active docs language. No language switcher. */ +export function ForLanguage({ + id, + children, +}: { + id: DocLanguageId | DocLanguageId[] | string | string[]; + children: ReactNode; +}) { + const { language } = useDocLanguage(); + const raw = Array.isArray(id) ? id : [id]; + const ids = raw + .map((item) => resolveDocLanguageId(String(item))) + .filter((item): item is DocLanguageId => item !== null); + if (!ids.includes(language)) return null; + return children; +} diff --git a/website/src/components/mdx.tsx b/website/src/components/mdx.tsx index ea0c5b3f..8e304c07 100644 --- a/website/src/components/mdx.tsx +++ b/website/src/components/mdx.tsx @@ -1,5 +1,7 @@ import defaultMdxComponents from "fumadocs-ui/mdx"; import type { MDXComponents } from "mdx/types"; +import { ForLanguage } from "@/components/language-context"; +import { Note } from "@/components/note"; import { ForProvider } from "@/components/provider-context"; import { Tab, Tabs } from "@/components/tabs"; @@ -9,6 +11,8 @@ export function getMDXComponents(components?: MDXComponents) { Tabs, Tab, ForProvider, + ForLanguage, + Note, ...components, } satisfies MDXComponents; } diff --git a/website/src/components/note.tsx b/website/src/components/note.tsx new file mode 100644 index 00000000..eae323e2 --- /dev/null +++ b/website/src/components/note.tsx @@ -0,0 +1,29 @@ +"use client"; + +import type { ReactNode } from "react"; +import { cn } from "@/lib/cn"; + +/** + * Compact language/provider-aware note. Content swaps with the page language + * tabs and provider select — this box has no switchers of its own. + */ +export function Note({ + children, + className, +}: { + children: ReactNode; + className?: string; +}) { + return ( + + ); +} diff --git a/website/src/components/tabs.tsx b/website/src/components/tabs.tsx index ee7f258c..081d4da8 100644 --- a/website/src/components/tabs.tsx +++ b/website/src/components/tabs.tsx @@ -16,6 +16,11 @@ import { TabsTrigger as RootTabsTrigger, } from "fumadocs-ui/components/ui/tabs"; import { cn } from "@/lib/cn"; +import { DOC_LANGUAGE_STORAGE_KEY } from "@/lib/languages"; +import { + resolveDocLanguageId, + useDocLanguageOptional, +} from "@/components/language-context"; type TabsContextValue = { items?: string[]; @@ -49,10 +54,16 @@ export function Tabs({ label, defaultIndex = 0, defaultValue = items ? escapeValue(items[defaultIndex]!) : undefined, + groupId, + persist, children, ...props }: TabsProps) { const collection = useMemo(() => [] as string[], []); + const languageCtx = useDocLanguageOptional(); + const isLanguageGroup = groupId === DOC_LANGUAGE_STORAGE_KEY; + const languageValue = + isLanguageGroup && languageCtx ? languageCtx.language : undefined; return ( { + const id = resolveDocLanguageId(value); + if (id) languageCtx.setLanguage(id); + } + : undefined + } {...props} > {items && ( diff --git a/website/src/lib/providers.ts b/website/src/lib/providers.ts index 6dbc116d..4a65eee5 100644 --- a/website/src/lib/providers.ts +++ b/website/src/lib/providers.ts @@ -27,6 +27,19 @@ export const PROVIDER_SCOPED_HEADINGS: Record< delete: ["daytona"], terminate: ["modal"], }, + client: { + get: ["daytona"], + attach: ["modal"], + }, + sandbox: { + refresh: ["daytona"], + start: ["daytona"], + stop: ["daytona"], + pause: ["daytona"], + archive: ["daytona"], + delete: ["daytona"], + terminate: ["modal"], + }, }; export function filterTocForProvider( diff --git a/website/src/routes/__root.tsx b/website/src/routes/__root.tsx index 6aab94eb..4725b307 100644 --- a/website/src/routes/__root.tsx +++ b/website/src/routes/__root.tsx @@ -7,6 +7,7 @@ import { import * as React from "react"; import appCss from "@/styles/app.css?url"; import { RootProvider } from "fumadocs-ui/provider/tanstack"; +import { LanguageProvider } from "@/components/language-context"; import { ProviderProvider } from "@/components/provider-context"; import { assetUrl } from "@/lib/shared"; import { siteDescription } from "@/lib/seo"; @@ -42,7 +43,9 @@ function RootComponent() { search={{ options: { type: "static" } }} > - + + + From 87fe87292c2c96fe1611fbb82b99c0df2109ef06 Mon Sep 17 00:00:00 2001 From: Nabhag Motivaras <65061890+Nabhag8848@users.noreply.github.com> Date: Thu, 5 Nov 2026 22:37:05 +0530 Subject: [PATCH 4/5] Rename the docs reference to SDK and clean guide wording. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move /docs/api to /docs/sdk, prefer “examples” over “samples”, expand Concepts, and drop obvious secret-logging asides. Co-authored-by: Cursor --- website/content/docs/concepts.mdx | 248 +++++++++-- website/content/docs/configuration.mdx | 16 +- website/content/docs/create.mdx | 6 +- website/content/docs/daytona.mdx | 10 +- website/content/docs/errors.mdx | 4 +- website/content/docs/examples.mdx | 384 +++++++++--------- website/content/docs/filesystem.mdx | 2 +- website/content/docs/index.mdx | 16 +- website/content/docs/meta.json | 4 +- website/content/docs/modal.mdx | 4 +- website/content/docs/process.mdx | 4 +- website/content/docs/{api => sdk}/client.mdx | 12 +- .../docs/{api => sdk}/configuration.mdx | 10 +- .../docs/{api => sdk}/create-options.mdx | 14 +- website/content/docs/{api => sdk}/enums.mdx | 10 +- website/content/docs/{api => sdk}/errors.mdx | 0 .../content/docs/{api => sdk}/filesystem.mdx | 4 +- website/content/docs/{api => sdk}/index.mdx | 20 +- website/content/docs/{api => sdk}/meta.json | 2 +- website/content/docs/{api => sdk}/process.mdx | 0 .../docs/{api => sdk}/sandbox-info.mdx | 8 +- website/content/docs/{api => sdk}/sandbox.mdx | 14 +- 22 files changed, 479 insertions(+), 313 deletions(-) rename website/content/docs/{api => sdk}/client.mdx (95%) rename website/content/docs/{api => sdk}/configuration.mdx (94%) rename website/content/docs/{api => sdk}/create-options.mdx (97%) rename website/content/docs/{api => sdk}/enums.mdx (95%) rename website/content/docs/{api => sdk}/errors.mdx (100%) rename website/content/docs/{api => sdk}/filesystem.mdx (99%) rename website/content/docs/{api => sdk}/index.mdx (66%) rename website/content/docs/{api => sdk}/meta.json (91%) rename website/content/docs/{api => sdk}/process.mdx (100%) rename website/content/docs/{api => sdk}/sandbox-info.mdx (93%) rename website/content/docs/{api => sdk}/sandbox.mdx (96%) diff --git a/website/content/docs/concepts.mdx b/website/content/docs/concepts.mdx index ebcf3257..5474d76a 100644 --- a/website/content/docs/concepts.mdx +++ b/website/content/docs/concepts.mdx @@ -1,6 +1,6 @@ --- title: Concepts -description: Client, sandbox handle, providers, capabilities, and close. +description: Client, handle, filesystem, process, providers, concurrency, and close. --- Sandbox Kit is an SDK. You construct a client with a provider and config; the client calls that provider for create, lifecycle, filesystem, and process work. Application code stays on the shared client surface. @@ -130,11 +130,6 @@ const sandbox = await client.create({ source: { image: { reference: "daytonaio/playground:latest" } }, }); console.log(sandbox.id); - -await sandbox.filesystem.writeFile("/tmp/note.txt", data); -const result = await sandbox.process.run({ argv: ["echo", "hi"] }); -// result: { exitCode, stdout, stderr } -console.log(result); ``` @@ -146,11 +141,6 @@ const sandbox = await client.create({ source: { image: { reference: "alpine:3.21" } }, }); console.log(sandbox.id); - -await sandbox.filesystem.writeFile("/tmp/note.txt", data); -const result = await sandbox.process.run({ argv: ["echo", "hi"] }); -// result: { exitCode, stdout, stderr } -console.log(result); ``` @@ -170,16 +160,6 @@ if err != nil { return err } fmt.Println(instance.ID()) - -err = instance.Filesystem().WriteFile(ctx, "/tmp/note.txt", data, nil) -result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ - Argv: []string{"echo", "hi"}, -}) -if err != nil { - return err -} -// result: ExitCode, Stdout, Stderr -fmt.Println(result) ``` @@ -196,10 +176,74 @@ if err != nil { return err } fmt.Println(instance.ID()) +``` + + + + + + +## Filesystem + +Sandbox paths are absolute. Write, read, copy, list, and remove go through the handle. More: [Filesystem](/docs/filesystem). + + + + +```ts +const body = new TextEncoder().encode("hello from kit\n"); +await sandbox.filesystem.writeFile("/tmp/note.txt", body); + +const bytes = await sandbox.filesystem.readFile("/tmp/note.txt"); +console.log(new TextDecoder().decode(bytes)); +``` + + + + +```go +err = instance.Filesystem().WriteFile(ctx, "/tmp/note.txt", []byte("hello from kit\n"), nil) +if err != nil { + return err +} + +data, err := instance.Filesystem().ReadFile(ctx, "/tmp/note.txt", nil) +if err != nil { + return err +} +fmt.Printf("%s", data) +``` + + + + +## Process + +Run one command and wait for it to finish. A non-zero exit code is **not** an SDK error—check `exitCode` yourself. More: [Process](/docs/process). + + + + +```ts +const result = await sandbox.process.run({ + argv: ["echo", "hello from kit"], + workingDirectory: "/tmp", + environment: { KIT_DEMO: "from-kit" }, + timeout: 5_000, +}); +// result: { exitCode, stdout, stderr } +console.log(result); +``` + + + -err = instance.Filesystem().WriteFile(ctx, "/tmp/note.txt", data, nil) +```go result, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ - Argv: []string{"echo", "hi"}, + Argv: []string{"echo", "hello from kit"}, + WorkingDirectory: sandbox.Value("/tmp"), + Environment: map[string]string{"KIT_DEMO": "from-kit"}, + Timeout: sandbox.Duration(5 * time.Second), }) if err != nil { return err @@ -208,8 +252,6 @@ if err != nil { fmt.Println(result) ``` - - @@ -318,6 +360,8 @@ Unsupported calls fail before anything reaches the cloud. The cloud can still re + + ```ts import { LifecycleCapability } from "@sandbox-kit/sandbox"; @@ -326,9 +370,25 @@ if (!sandbox.supports(LifecycleCapability.Stop)) { } ``` + + + + +```ts +import { LifecycleCapability } from "@sandbox-kit/sandbox"; + +if (!sandbox.supports(LifecycleCapability.Terminate)) { + throw new Error(`sandbox ${sandbox.id} cannot be terminated`); +} +``` + + + + + ```go import "github.com/sandbox-kit/kit/sdks/go/sandbox" @@ -337,43 +397,161 @@ if !instance.Supports(sandbox.LifecycleCapabilityStop) { } ``` + + + + +```go +import "github.com/sandbox-kit/kit/sdks/go/sandbox" + +if !instance.Supports(sandbox.LifecycleCapabilityTerminate) { + return fmt.Errorf("sandbox %s cannot be terminated", instance.ID()) +} +``` + + + ## Concurrency -Calls on one handle run one at a time. A second handle for the same sandbox id does not share that queue. +Calls on **one handle** run one at a time. Starting two awaits does not overlap them—the second waits until the first settles. Abort or cancel rejects your wait promptly; the handle stays busy until the provider call finishes. A second handle for the same sandbox id has its own queue, so those calls can run together. ```ts +// Queued on one handle — `two` starts only after `one` finishes. +const one = sandbox.process.run({ argv: ["echo", "one"] }); +const two = sandbox.process.run({ argv: ["echo", "two"] }); +const [first, second] = await Promise.all([one, two]); +console.log(first, second); + +// Abort ends the wait; the handle stays busy until the provider call settles. const ac = new AbortController(); const pending = sandbox.process.run({ argv: ["sleep", "30"], signal: ac.signal, }); -ac.abort(); // rejects the await; handle stays busy until the in-flight call finishes +ac.abort(); await pending.catch(() => {}); ``` + + +```ts +// Parallel work: another handle for the same id has its own queue. +const other = await client.get(sandbox.id); +await Promise.all([ + sandbox.process.run({ argv: ["echo", "a"] }), + other.process.run({ argv: ["echo", "b"] }), +]); +``` + + + + + +```ts +// Parallel work: another handle for the same id has its own queue. +const other = await client.attach(sandbox.id); +await Promise.all([ + sandbox.process.run({ argv: ["echo", "a"] }), + other.process.run({ argv: ["echo", "b"] }), +]); +``` + + + ```go -ctx, cancel := context.WithCancel(ctx) -defer cancel() +// Two goroutines still serialize on one handle — the second waits for the first. +errCh := make(chan error, 2) +go func() { + _, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ + Argv: []string{"echo", "one"}, + }) + errCh <- err +}() +go func() { + _, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ + Argv: []string{"echo", "two"}, + }) + errCh <- err +}() +for range 2 { + if err := <-errCh; err != nil { + return err + } +} +// Cancel ends the wait; the handle stays busy until the provider call settles. +runCtx, cancel := context.WithCancel(ctx) +defer cancel() go func() { time.Sleep(10 * time.Millisecond) - cancel() // ends the wait; handle stays busy until the in-flight call finishes + cancel() }() - -_, err := instance.Process().Run(ctx, &sandbox.ExecOptions{ +_, _ = instance.Process().Run(runCtx, &sandbox.ExecOptions{ Argv: []string{"sleep", "30"}, }) ``` + + +```go +// Parallel work: another handle for the same id has its own queue. +other, err := client.Get(ctx, instance.ID()) +if err != nil { + return err +} +errCh = make(chan error, 2) +go func() { + _, err := instance.Process().Run(ctx, &sandbox.ExecOptions{Argv: []string{"echo", "a"}}) + errCh <- err +}() +go func() { + _, err := other.Process().Run(ctx, &sandbox.ExecOptions{Argv: []string{"echo", "b"}}) + errCh <- err +}() +for range 2 { + if err := <-errCh; err != nil { + return err + } +} +``` + + + + + +```go +// Parallel work: another handle for the same id has its own queue. +other, err := client.Attach(ctx, instance.ID()) +if err != nil { + return err +} +errCh = make(chan error, 2) +go func() { + _, err := instance.Process().Run(ctx, &sandbox.ExecOptions{Argv: []string{"echo", "a"}}) + errCh <- err +}() +go func() { + _, err := other.Process().Run(ctx, &sandbox.ExecOptions{Argv: []string{"echo", "b"}}) + errCh <- err +}() +for range 2 { + if err := <-errCh; err != nil { + return err + } +} +``` + + + @@ -404,8 +582,6 @@ _ = instance.Close(context.Background()) // local handle resources only Kinds, field paths, and handling: [Errors](/docs/errors). -## API surface - -Types, methods, parameters, and return values: [API reference](/docs/api) ([Client](/docs/api/client), [Sandbox](/docs/api/sandbox), [Filesystem](/docs/api/filesystem), [Process](/docs/api/process)). +## SDK reference -Streaming I/O, interactive sessions, PTY, GPU, resize, and browsers are outside this SDK. +Types, methods, parameters, and return values: [SDK reference](/docs/sdk) ([Client](/docs/sdk/client), [Sandbox](/docs/sdk/sandbox), [Filesystem](/docs/sdk/filesystem), [Process](/docs/sdk/process)). diff --git a/website/content/docs/configuration.mdx b/website/content/docs/configuration.mdx index c5381fb6..22951eca 100644 --- a/website/content/docs/configuration.mdx +++ b/website/content/docs/configuration.mdx @@ -43,7 +43,7 @@ if err != nil { | `provider` | Provider constructor | | `auth` | One of `apiKey`, `tokenPair`, `bearerToken`, `oauthRefresh`. Omit to use provider env creds | | `scope` | App, environment, or organization | -| `endpoint` | API base URL override | +| `endpoint` | Provider endpoint URL override | | `region` | Target / default placement | | `timeout` | Default deadline for calls that omit their own | @@ -168,7 +168,7 @@ client, err := sandbox.NewClient(modal.New(), config) | Setting | What to pass | | ------------ | ------------------------------------------------- | -| API key | `auth.apiKey.key` | +| `apiKey` | `auth.apiKey.key` | | Bearer token | `auth.bearerToken.token`, plus an organization id | | Endpoint | `endpoint`. Default `https://app.daytona.io/api` | | Target | `region`. Omit for the default target | @@ -190,7 +190,7 @@ await using client = new Client({ | Setting | What to pass | | ------------ | ------------------------------------------------------- | -| API key | `APIKey` | +| `APIKey` | `APIKey` | | Bearer token | `BearerToken`, plus an organization id | | Endpoint | `Config.Endpoint`. Default `https://app.daytona.io/api` | | Target | `Config.Region`. Omit for the default target | @@ -386,7 +386,7 @@ instance, err := client.Create(ctx, &sandbox.CreateOptions{ ## Credentials -Do not log the config object—it holds secrets. Construction does not contact the provider. Bad credentials fail on the first create or open. See [Errors](/docs/errors). +Construction does not contact the provider. Bad credentials fail on the first create or open. See [Errors](/docs/errors). @@ -403,8 +403,6 @@ const config = { await using client = new Client(config); ``` -Keep secrets out of logs—do not `JSON.stringify(config)`. - @@ -425,8 +423,6 @@ const config = { await using client = new Client(config); ``` -Keep secrets out of logs—do not `JSON.stringify(config)`. - @@ -444,8 +440,6 @@ config := &sandbox.Config{ client, err := sandbox.NewClient(daytona.New(), config) ``` -Keep secrets out of logs—do not `fmt.Printf("%+v", config)`. - @@ -467,8 +461,6 @@ config := &sandbox.Config{ client, err := sandbox.NewClient(modal.New(), config) ``` -Keep secrets out of logs—do not `fmt.Printf("%+v", config)`. - diff --git a/website/content/docs/create.mdx b/website/content/docs/create.mdx index 19165986..cd36e918 100644 --- a/website/content/docs/create.mdx +++ b/website/content/docs/create.mdx @@ -396,7 +396,7 @@ A linked sandbox must be ephemeral; Kit rejects the request otherwise. Idle stop, idle pause, stopped archive, and stopped delete use `PolicyMode` (`After` / `Disabled`). You cannot combine a positive stop delay with a positive pause delay. -Samples: [Examples](/docs/examples). +See [Examples](/docs/examples). @@ -404,7 +404,7 @@ Samples: [Examples](/docs/examples). Set cloud and region on `placement`. A ready wait needs a probe and a positive timeout. -Disk size, an API endpoint override, and stop / pause / archive / delete policies are rejected. +Disk size, an endpoint override, and stop / pause / archive / delete policies are rejected. @@ -454,7 +454,7 @@ instance, err := client.Create(ctx, &sandbox.CreateOptions{ -Samples: [Examples](/docs/examples). +See [Examples](/docs/examples). diff --git a/website/content/docs/daytona.mdx b/website/content/docs/daytona.mdx index 4abb80df..ff85951c 100644 --- a/website/content/docs/daytona.mdx +++ b/website/content/docs/daytona.mdx @@ -98,7 +98,7 @@ Omit `auth` to let the Daytona SDK pick credentials from its environment. Closin | Setting | Field | | ------------ | ------------------------ | -| API URL | `endpoint` | +| Endpoint | `endpoint` | | Target | `region` | | Organization | `scope.organizationId` | | Bearer token | `auth.bearerToken.token` | @@ -130,7 +130,7 @@ await using client = new Client({ | Setting | Field | | ------------ | ---------------------- | -| API URL | `Config.Endpoint` | +| Endpoint | `Config.Endpoint` | | Target | `Config.Region` | | Organization | `Scope.OrganizationId` | | Bearer token | `BearerToken` | @@ -168,7 +168,7 @@ client, err := sandbox.NewClient(daytona.New(), config) -Default API URL: `https://app.daytona.io/api`. Remote URLs need HTTPS; HTTP is allowed for localhost. Bearer tokens need an organization id. Full rules: [Configuration](/docs/configuration). +Default endpoint: `https://app.daytona.io/api`. Remote URLs need HTTPS; HTTP is allowed for localhost. Bearer tokens need an organization id. Full rules: [Configuration](/docs/configuration). ## What works @@ -190,12 +190,12 @@ CPU is whole cores. Memory and disk are whole GiB expressed as MiB. Resource ove -Sample: [create-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-sandbox) +Example: [create-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-sandbox) -Sample: [create-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-sandbox) +Example: [create-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-sandbox) diff --git a/website/content/docs/errors.mdx b/website/content/docs/errors.mdx index a56d4661..e1ed9b58 100644 --- a/website/content/docs/errors.mdx +++ b/website/content/docs/errors.mdx @@ -249,7 +249,7 @@ _ = instance -Samples: [Examples](/docs/examples). +See [Examples](/docs/examples). @@ -294,6 +294,6 @@ _ = instance -Samples: [Examples](/docs/examples). +See [Examples](/docs/examples). diff --git a/website/content/docs/examples.mdx b/website/content/docs/examples.mdx index 2197321e..97f6cc9a 100644 --- a/website/content/docs/examples.mdx +++ b/website/content/docs/examples.mdx @@ -1,9 +1,9 @@ --- title: Examples -description: Clone a sample project, set .env, and run one operation. +description: Clone an example project, set .env, and run one operation. --- -Each sample is a small project that loads its own `.env` and demonstrates one call against a provider. Creation samples provision a real sandbox. Filesystem, process, and lifecycle samples need a sandbox id in `.env`. Error samples fail locally. +Each example is a small project that loads its own `.env` and demonstrates one call against a provider. Creation examples provision a real sandbox. Filesystem, process, and lifecycle examples need a sandbox id in `.env`. Error examples fail locally. Destructive ops (stop, terminate, archive, delete, remove) can destroy the sandbox or path you configure. @@ -77,38 +77,38 @@ go run . -| Example | Project | -| ------- | ------- | -| Creation | [create-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-sandbox) | -| Snapshot | [create-daytona-from-snapshot](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-from-snapshot) | -| Image | [create-daytona-from-image](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-from-image) | -| Runtime | [create-daytona-with-runtime](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-runtime) | -| Ephemeral | [create-daytona-ephemeral](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-ephemeral) | -| Linked | [create-daytona-linked](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-linked) | -| Policies | [create-daytona-with-policies](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-policies) | -| Network | [create-daytona-with-network](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-network) | -| Labels | [create-daytona-with-labels](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-labels) | -| Secrets | [create-daytona-with-secrets](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-secrets) | -| KVM | [create-daytona-with-kvm](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-kvm) | -| TTL | [create-daytona-with-ttl](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-ttl) | +| Example | Project | +| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| Creation | [create-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-sandbox) | +| Snapshot | [create-daytona-from-snapshot](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-from-snapshot) | +| Image | [create-daytona-from-image](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-from-image) | +| Runtime | [create-daytona-with-runtime](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-runtime) | +| Ephemeral | [create-daytona-ephemeral](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-ephemeral) | +| Linked | [create-daytona-linked](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-linked) | +| Policies | [create-daytona-with-policies](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-policies) | +| Network | [create-daytona-with-network](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-network) | +| Labels | [create-daytona-with-labels](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-labels) | +| Secrets | [create-daytona-with-secrets](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-secrets) | +| KVM | [create-daytona-with-kvm](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-kvm) | +| TTL | [create-daytona-with-ttl](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/configuration/create-daytona-with-ttl) | -| Example | Project | -| ------- | ------- | -| Creation | [create-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-sandbox) | -| Snapshot | [create-daytona-from-snapshot](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-from-snapshot) | -| Image | [create-daytona-from-image](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-from-image) | -| Runtime | [create-daytona-with-runtime](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-runtime) | -| Ephemeral | [create-daytona-ephemeral](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-ephemeral) | -| Linked | [create-daytona-linked](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-linked) | -| Policies | [create-daytona-with-policies](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-policies) | -| Network | [create-daytona-with-network](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-network) | -| Labels | [create-daytona-with-labels](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-labels) | -| Secrets | [create-daytona-with-secrets](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-secrets) | -| KVM | [create-daytona-with-kvm](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-kvm) | -| TTL | [create-daytona-with-ttl](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-ttl) | +| Example | Project | +| --------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| Creation | [create-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-sandbox) | +| Snapshot | [create-daytona-from-snapshot](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-from-snapshot) | +| Image | [create-daytona-from-image](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-from-image) | +| Runtime | [create-daytona-with-runtime](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-runtime) | +| Ephemeral | [create-daytona-ephemeral](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-ephemeral) | +| Linked | [create-daytona-linked](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-linked) | +| Policies | [create-daytona-with-policies](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-policies) | +| Network | [create-daytona-with-network](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-network) | +| Labels | [create-daytona-with-labels](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-labels) | +| Secrets | [create-daytona-with-secrets](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-secrets) | +| KVM | [create-daytona-with-kvm](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-kvm) | +| TTL | [create-daytona-with-ttl](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/configuration/create-daytona-with-ttl) | @@ -118,26 +118,26 @@ go run . -| Example | Project | -| ------- | ------- | -| Run command | [run-daytona-command](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-command) | -| Shell command | [run-daytona-shell-command](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-shell-command) | -| Run with cwd | [run-daytona-with-cwd](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-with-cwd) | -| Run with env | [run-daytona-with-env](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-with-env) | -| Run with timeout | [run-daytona-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-with-timeout) | -| Check exit | [run-daytona-check-exit](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-check-exit) | +| Example | Project | +| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------- | +| Run command | [run-daytona-command](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-command) | +| Shell command | [run-daytona-shell-command](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-shell-command) | +| Run with cwd | [run-daytona-with-cwd](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-with-cwd) | +| Run with env | [run-daytona-with-env](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-with-env) | +| Run with timeout | [run-daytona-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-with-timeout) | +| Check exit | [run-daytona-check-exit](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/process/run-daytona-check-exit) | -| Example | Project | -| ------- | ------- | -| Run command | [run-daytona-command](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-command) | -| Shell command | [run-daytona-shell-command](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-shell-command) | -| Run with cwd | [run-daytona-with-cwd](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-with-cwd) | -| Run with env | [run-daytona-with-env](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-with-env) | -| Run with timeout | [run-daytona-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-with-timeout) | -| Check exit | [run-daytona-check-exit](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-check-exit) | +| Example | Project | +| ---------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| Run command | [run-daytona-command](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-command) | +| Shell command | [run-daytona-shell-command](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-shell-command) | +| Run with cwd | [run-daytona-with-cwd](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-with-cwd) | +| Run with env | [run-daytona-with-env](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-with-env) | +| Run with timeout | [run-daytona-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-with-timeout) | +| Check exit | [run-daytona-check-exit](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/process/run-daytona-check-exit) | @@ -147,30 +147,30 @@ go run . -| Example | Project | -| ------- | ------- | -| Read file | [read-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/read-daytona-file) | -| Write file | [write-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/write-daytona-file) | -| Copy in | [copy-file-into-daytona](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/copy-file-into-daytona) | -| Copy out | [copy-file-from-daytona](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/copy-file-from-daytona) | -| Directory | [make-daytona-directory](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/make-daytona-directory) | -| List | [list-daytona-directory](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/list-daytona-directory) | -| Stat | [stat-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/stat-daytona-file) | -| Remove | [remove-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/remove-daytona-file) | +| Example | Project | +| ---------- | ------------------------------------------------------------------------------------------------------------------------------------ | +| Read file | [read-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/read-daytona-file) | +| Write file | [write-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/write-daytona-file) | +| Copy in | [copy-file-into-daytona](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/copy-file-into-daytona) | +| Copy out | [copy-file-from-daytona](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/copy-file-from-daytona) | +| Directory | [make-daytona-directory](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/make-daytona-directory) | +| List | [list-daytona-directory](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/list-daytona-directory) | +| Stat | [stat-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/stat-daytona-file) | +| Remove | [remove-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/filesystem/remove-daytona-file) | -| Example | Project | -| ------- | ------- | -| Read file | [read-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/read-daytona-file) | -| Write file | [write-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/write-daytona-file) | -| Copy in | [copy-file-into-daytona](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/copy-file-into-daytona) | -| Copy out | [copy-file-from-daytona](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/copy-file-from-daytona) | -| Directory | [make-daytona-directory](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/make-daytona-directory) | -| List | [list-daytona-directory](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/list-daytona-directory) | -| Stat | [stat-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/stat-daytona-file) | -| Remove | [remove-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/remove-daytona-file) | +| Example | Project | +| ---------- | ---------------------------------------------------------------------------------------------------------------------------- | +| Read file | [read-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/read-daytona-file) | +| Write file | [write-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/write-daytona-file) | +| Copy in | [copy-file-into-daytona](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/copy-file-into-daytona) | +| Copy out | [copy-file-from-daytona](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/copy-file-from-daytona) | +| Directory | [make-daytona-directory](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/make-daytona-directory) | +| List | [list-daytona-directory](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/list-daytona-directory) | +| Stat | [stat-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/stat-daytona-file) | +| Remove | [remove-daytona-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/filesystem/remove-daytona-file) | @@ -180,36 +180,36 @@ go run . -| Example | Project | -| ------- | ------- | -| Get | [get-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/get-daytona-sandbox) | -| Refresh | [refresh-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/refresh-daytona-sandbox) | -| Start | [start-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/start-daytona-sandbox) | -| Start timeout | [start-daytona-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/start-daytona-with-timeout) | -| Stop | [stop-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/stop-daytona-sandbox) | -| Force stop | [force-stop-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/force-stop-daytona-sandbox) | -| Pause | [pause-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/pause-daytona-sandbox) | -| Archive | [archive-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/archive-daytona-sandbox) | -| Delete | [delete-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/delete-daytona-sandbox) | -| Delete request | [request-daytona-deletion](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/request-daytona-deletion) | -| Close handle | [close-daytona-handle](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/close-daytona-handle) | +| Example | Project | +| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| Get | [get-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/get-daytona-sandbox) | +| Refresh | [refresh-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/refresh-daytona-sandbox) | +| Start | [start-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/start-daytona-sandbox) | +| Start timeout | [start-daytona-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/start-daytona-with-timeout) | +| Stop | [stop-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/stop-daytona-sandbox) | +| Force stop | [force-stop-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/force-stop-daytona-sandbox) | +| Pause | [pause-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/pause-daytona-sandbox) | +| Archive | [archive-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/archive-daytona-sandbox) | +| Delete | [delete-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/delete-daytona-sandbox) | +| Delete request | [request-daytona-deletion](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/request-daytona-deletion) | +| Close handle | [close-daytona-handle](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/lifecycle/close-daytona-handle) | -| Example | Project | -| ------- | ------- | -| Get | [get-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/get-daytona-sandbox) | -| Refresh | [refresh-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/refresh-daytona-sandbox) | -| Start | [start-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/start-daytona-sandbox) | -| Start timeout | [start-daytona-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/start-daytona-with-timeout) | -| Stop | [stop-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/stop-daytona-sandbox) | -| Force stop | [force-stop-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/force-stop-daytona-sandbox) | -| Pause | [pause-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/pause-daytona-sandbox) | -| Archive | [archive-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/archive-daytona-sandbox) | -| Delete | [delete-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/delete-daytona-sandbox) | -| Delete request | [request-daytona-deletion](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/request-daytona-deletion) | -| Close handle | [close-daytona-handle](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/close-daytona-handle) | +| Example | Project | +| -------------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| Get | [get-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/get-daytona-sandbox) | +| Refresh | [refresh-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/refresh-daytona-sandbox) | +| Start | [start-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/start-daytona-sandbox) | +| Start timeout | [start-daytona-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/start-daytona-with-timeout) | +| Stop | [stop-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/stop-daytona-sandbox) | +| Force stop | [force-stop-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/force-stop-daytona-sandbox) | +| Pause | [pause-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/pause-daytona-sandbox) | +| Archive | [archive-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/archive-daytona-sandbox) | +| Delete | [delete-daytona-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/delete-daytona-sandbox) | +| Delete request | [request-daytona-deletion](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/request-daytona-deletion) | +| Close handle | [close-daytona-handle](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/lifecycle/close-daytona-handle) | @@ -219,16 +219,16 @@ go run . -| Example | Project | -| ------- | ------- | -| Errors | [handle-daytona-errors](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/errors/handle-daytona-errors) | +| Example | Project | +| ------- | ------------------------------------------------------------------------------------------------------------------------------ | +| Errors | [handle-daytona-errors](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/daytona/errors/handle-daytona-errors) | -| Example | Project | -| ------- | ------- | -| Errors | [handle-daytona-errors](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/errors/handle-daytona-errors) | +| Example | Project | +| ------- | ---------------------------------------------------------------------------------------------------------------------- | +| Errors | [handle-daytona-errors](https://github.com/sandbox-kit/kit/tree/main/examples/go/daytona/errors/handle-daytona-errors) | @@ -244,48 +244,48 @@ go run . -| Example | Project | -| ------- | ------- | -| Creation | [create-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-sandbox) | -| Resources | [create-modal-with-resources](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-resources) | -| Runtime | [create-modal-with-runtime](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-runtime) | -| GVisor | [create-modal-gvisor](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-gvisor) | -| Linux VM | [create-modal-linux-vm](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-linux-vm) | -| Placement | [create-modal-with-placement](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-placement) | -| Labels | [create-modal-with-labels](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-labels) | -| Network | [create-modal-with-network](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-network) | -| Idle timeout | [create-modal-idle](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-idle) | -| Readiness | [create-modal-ready](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-ready) | -| TCP readiness | [create-modal-tcp-ready](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-tcp-ready) | -| Client timeout wait | [create-modal-client-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-client-timeout) | -| Ports | [create-modal-with-ports](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-ports) | -| Allowlists | [create-modal-with-allowlists](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-allowlists) | -| Secrets | [create-modal-with-secrets](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-secrets) | -| Verbose | [create-modal-verbose](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-verbose) | -| Identity | [create-modal-with-identity](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-identity) | +| Example | Project | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| Creation | [create-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-sandbox) | +| Resources | [create-modal-with-resources](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-resources) | +| Runtime | [create-modal-with-runtime](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-runtime) | +| GVisor | [create-modal-gvisor](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-gvisor) | +| Linux VM | [create-modal-linux-vm](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-linux-vm) | +| Placement | [create-modal-with-placement](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-placement) | +| Labels | [create-modal-with-labels](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-labels) | +| Network | [create-modal-with-network](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-network) | +| Idle timeout | [create-modal-idle](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-idle) | +| Readiness | [create-modal-ready](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-ready) | +| TCP readiness | [create-modal-tcp-ready](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-tcp-ready) | +| Client timeout wait | [create-modal-client-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-client-timeout) | +| Ports | [create-modal-with-ports](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-ports) | +| Allowlists | [create-modal-with-allowlists](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-allowlists) | +| Secrets | [create-modal-with-secrets](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-secrets) | +| Verbose | [create-modal-verbose](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-verbose) | +| Identity | [create-modal-with-identity](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-with-identity) | -| Example | Project | -| ------- | ------- | -| Creation | [create-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-sandbox) | -| Resources | [create-modal-with-resources](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-resources) | -| Runtime | [create-modal-with-runtime](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-runtime) | -| GVisor | [create-modal-gvisor](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-gvisor) | -| Linux VM | [create-modal-linux-vm](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-linux-vm) | -| Placement | [create-modal-with-placement](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-placement) | -| Labels | [create-modal-with-labels](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-labels) | -| Network | [create-modal-with-network](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-network) | -| Idle timeout | [create-modal-idle](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-idle) | -| Readiness | [create-modal-ready](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-ready) | -| TCP readiness | [create-modal-tcp-ready](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-tcp-ready) | -| Client timeout wait | [create-modal-client-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-client-timeout) | -| Ports | [create-modal-with-ports](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-ports) | -| Allowlists | [create-modal-with-allowlists](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-allowlists) | -| Secrets | [create-modal-with-secrets](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-secrets) | -| Verbose | [create-modal-verbose](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-verbose) | -| Identity | [create-modal-with-identity](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-identity) | +| Example | Project | +| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| Creation | [create-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-sandbox) | +| Resources | [create-modal-with-resources](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-resources) | +| Runtime | [create-modal-with-runtime](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-runtime) | +| GVisor | [create-modal-gvisor](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-gvisor) | +| Linux VM | [create-modal-linux-vm](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-linux-vm) | +| Placement | [create-modal-with-placement](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-placement) | +| Labels | [create-modal-with-labels](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-labels) | +| Network | [create-modal-with-network](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-network) | +| Idle timeout | [create-modal-idle](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-idle) | +| Readiness | [create-modal-ready](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-ready) | +| TCP readiness | [create-modal-tcp-ready](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-tcp-ready) | +| Client timeout wait | [create-modal-client-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-client-timeout) | +| Ports | [create-modal-with-ports](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-ports) | +| Allowlists | [create-modal-with-allowlists](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-allowlists) | +| Secrets | [create-modal-with-secrets](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-secrets) | +| Verbose | [create-modal-verbose](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-verbose) | +| Identity | [create-modal-with-identity](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-with-identity) | @@ -295,26 +295,26 @@ go run . -| Example | Project | -| ------- | ------- | -| Run command | [run-modal-command](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-command) | -| Shell command | [run-modal-shell-command](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-shell-command) | -| Run with cwd | [run-modal-with-cwd](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-with-cwd) | -| Run with env | [run-modal-with-env](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-with-env) | -| Run with timeout | [run-modal-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-with-timeout) | -| Check exit | [run-modal-check-exit](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-check-exit) | +| Example | Project | +| ---------------- | --------------------------------------------------------------------------------------------------------------------------------- | +| Run command | [run-modal-command](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-command) | +| Shell command | [run-modal-shell-command](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-shell-command) | +| Run with cwd | [run-modal-with-cwd](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-with-cwd) | +| Run with env | [run-modal-with-env](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-with-env) | +| Run with timeout | [run-modal-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-with-timeout) | +| Check exit | [run-modal-check-exit](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/process/run-modal-check-exit) | -| Example | Project | -| ------- | ------- | -| Run command | [run-modal-command](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-command) | -| Shell command | [run-modal-shell-command](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-shell-command) | -| Run with cwd | [run-modal-with-cwd](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-with-cwd) | -| Run with env | [run-modal-with-env](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-with-env) | -| Run with timeout | [run-modal-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-with-timeout) | -| Check exit | [run-modal-check-exit](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-check-exit) | +| Example | Project | +| ---------------- | ------------------------------------------------------------------------------------------------------------------------- | +| Run command | [run-modal-command](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-command) | +| Shell command | [run-modal-shell-command](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-shell-command) | +| Run with cwd | [run-modal-with-cwd](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-with-cwd) | +| Run with env | [run-modal-with-env](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-with-env) | +| Run with timeout | [run-modal-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-with-timeout) | +| Check exit | [run-modal-check-exit](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/process/run-modal-check-exit) | @@ -324,30 +324,30 @@ go run . -| Example | Project | -| ------- | ------- | -| Read file | [read-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/read-modal-file) | -| Write file | [write-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/write-modal-file) | -| Copy in | [copy-file-into-modal](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/copy-file-into-modal) | -| Copy out | [copy-file-from-modal](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/copy-file-from-modal) | -| Directory | [make-modal-directory](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/make-modal-directory) | -| List | [list-modal-directory](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/list-modal-directory) | -| Stat | [stat-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/stat-modal-file) | -| Remove | [remove-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/remove-modal-file) | +| Example | Project | +| ---------- | ------------------------------------------------------------------------------------------------------------------------------ | +| Read file | [read-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/read-modal-file) | +| Write file | [write-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/write-modal-file) | +| Copy in | [copy-file-into-modal](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/copy-file-into-modal) | +| Copy out | [copy-file-from-modal](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/copy-file-from-modal) | +| Directory | [make-modal-directory](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/make-modal-directory) | +| List | [list-modal-directory](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/list-modal-directory) | +| Stat | [stat-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/stat-modal-file) | +| Remove | [remove-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/filesystem/remove-modal-file) | -| Example | Project | -| ------- | ------- | -| Read file | [read-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/read-modal-file) | -| Write file | [write-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/write-modal-file) | -| Copy in | [copy-file-into-modal](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/copy-file-into-modal) | -| Copy out | [copy-file-from-modal](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/copy-file-from-modal) | -| Directory | [make-modal-directory](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/make-modal-directory) | -| List | [list-modal-directory](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/list-modal-directory) | -| Stat | [stat-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/stat-modal-file) | -| Remove | [remove-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/remove-modal-file) | +| Example | Project | +| ---------- | ---------------------------------------------------------------------------------------------------------------------- | +| Read file | [read-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/read-modal-file) | +| Write file | [write-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/write-modal-file) | +| Copy in | [copy-file-into-modal](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/copy-file-into-modal) | +| Copy out | [copy-file-from-modal](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/copy-file-from-modal) | +| Directory | [make-modal-directory](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/make-modal-directory) | +| List | [list-modal-directory](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/list-modal-directory) | +| Stat | [stat-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/stat-modal-file) | +| Remove | [remove-modal-file](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/filesystem/remove-modal-file) | @@ -357,24 +357,24 @@ go run . -| Example | Project | -| ------- | ------- | -| Attach | [attach-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/lifecycle/attach-modal-sandbox) | -| Terminate | [terminate-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/lifecycle/terminate-modal-sandbox) | -| Terminate timeout | [terminate-modal-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/lifecycle/terminate-modal-with-timeout) | -| Termination request | [request-modal-termination](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/lifecycle/request-modal-termination) | -| Close handle | [close-modal-handle](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/lifecycle/close-modal-handle) | +| Example | Project | +| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | +| Attach | [attach-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/lifecycle/attach-modal-sandbox) | +| Terminate | [terminate-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/lifecycle/terminate-modal-sandbox) | +| Terminate timeout | [terminate-modal-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/lifecycle/terminate-modal-with-timeout) | +| Termination request | [request-modal-termination](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/lifecycle/request-modal-termination) | +| Close handle | [close-modal-handle](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/lifecycle/close-modal-handle) | -| Example | Project | -| ------- | ------- | -| Attach | [attach-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/lifecycle/attach-modal-sandbox) | -| Terminate | [terminate-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/lifecycle/terminate-modal-sandbox) | -| Terminate timeout | [terminate-modal-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/lifecycle/terminate-modal-with-timeout) | -| Termination request | [request-modal-termination](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/lifecycle/request-modal-termination) | -| Close handle | [close-modal-handle](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/lifecycle/close-modal-handle) | +| Example | Project | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | +| Attach | [attach-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/lifecycle/attach-modal-sandbox) | +| Terminate | [terminate-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/lifecycle/terminate-modal-sandbox) | +| Terminate timeout | [terminate-modal-with-timeout](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/lifecycle/terminate-modal-with-timeout) | +| Termination request | [request-modal-termination](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/lifecycle/request-modal-termination) | +| Close handle | [close-modal-handle](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/lifecycle/close-modal-handle) | @@ -384,16 +384,16 @@ go run . -| Example | Project | -| ------- | ------- | -| Errors | [handle-modal-errors](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/errors/handle-modal-errors) | +| Example | Project | +| ------- | ------------------------------------------------------------------------------------------------------------------------ | +| Errors | [handle-modal-errors](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/errors/handle-modal-errors) | -| Example | Project | -| ------- | ------- | -| Errors | [handle-modal-errors](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/errors/handle-modal-errors) | +| Example | Project | +| ------- | ---------------------------------------------------------------------------------------------------------------- | +| Errors | [handle-modal-errors](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/errors/handle-modal-errors) | diff --git a/website/content/docs/filesystem.mdx b/website/content/docs/filesystem.mdx index c12bb042..f3ac43a0 100644 --- a/website/content/docs/filesystem.mdx +++ b/website/content/docs/filesystem.mdx @@ -373,6 +373,6 @@ if err := files.Remove(ctx, "/tmp/kit-files", &sandbox.RemoveOptions{ -## Samples +## Examples Runnable projects: [Examples](/docs/examples). diff --git a/website/content/docs/index.mdx b/website/content/docs/index.mdx index 604186b1..feb585a2 100644 --- a/website/content/docs/index.mdx +++ b/website/content/docs/index.mdx @@ -300,11 +300,11 @@ Sandbox paths are absolute. More: [Filesystem](/docs/filesystem). ## Next -| | | -| ------------------------ | -------------------------------------------------------------------------------------- | -| How the client works | [Concepts](/docs/concepts) | -| Types and methods | [API reference](/docs/api) · [Client](/docs/api/client) · [Sandbox](/docs/api/sandbox) | -| Daytona setup | [Daytona](/docs/daytona) | -| Modal setup | [Modal](/docs/modal) | -| Auth, region, timeouts | [Configuration](/docs/configuration) | -| Runnable sample projects | [Examples](/docs/examples) | +| | | +| ------------------------- | -------------------------------------------------------------------------------------- | +| How the client works | [Concepts](/docs/concepts) | +| Types and methods | [SDK reference](/docs/sdk) · [Client](/docs/sdk/client) · [Sandbox](/docs/sdk/sandbox) | +| Daytona setup | [Daytona](/docs/daytona) | +| Modal setup | [Modal](/docs/modal) | +| Auth, region, timeouts | [Configuration](/docs/configuration) | +| Runnable example projects | [Examples](/docs/examples) | diff --git a/website/content/docs/meta.json b/website/content/docs/meta.json index a9bca9b5..77885484 100644 --- a/website/content/docs/meta.json +++ b/website/content/docs/meta.json @@ -15,7 +15,7 @@ "errors", "---Examples---", "examples", - "---API reference---", - "...api" + "---SDK reference---", + "...sdk" ] } diff --git a/website/content/docs/modal.mdx b/website/content/docs/modal.mdx index f94e02cf..1a24beb6 100644 --- a/website/content/docs/modal.mdx +++ b/website/content/docs/modal.mdx @@ -248,12 +248,12 @@ When you set resources: at least 0.125 CPU and 128 MiB. Disk cannot be raised at -Sample: [create-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-sandbox) +Example: [create-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/configuration/create-modal-sandbox) -Sample: [create-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-sandbox) +Example: [create-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/go/modal/configuration/create-modal-sandbox) diff --git a/website/content/docs/process.mdx b/website/content/docs/process.mdx index 7667d8bb..30edebab 100644 --- a/website/content/docs/process.mdx +++ b/website/content/docs/process.mdx @@ -358,8 +358,6 @@ if result.GetExitCode() != 7 { -Streaming I/O, interactive sessions, and PTY are not supported. - -## Samples +## Examples Runnable projects: [Examples](/docs/examples). diff --git a/website/content/docs/api/client.mdx b/website/content/docs/sdk/client.mdx similarity index 95% rename from website/content/docs/api/client.mdx rename to website/content/docs/sdk/client.mdx index 23938db8..dd6812fb 100644 --- a/website/content/docs/api/client.mdx +++ b/website/content/docs/sdk/client.mdx @@ -20,7 +20,7 @@ Validates config and initializes the selected provider. Throws on invalid config | Name | Type | Description | | -------- | ----------------------------------------- | -------------------------------------------------------------------------------- | -| `config` | [`ClientConfig`](/docs/api/configuration) | Provider plus shared settings (`auth`, `scope`, `endpoint`, `region`, `timeout`) | +| `config` | [`ClientConfig`](/docs/sdk/configuration) | Provider plus shared settings (`auth`, `scope`, `endpoint`, `region`, `timeout`) | **Returns** @@ -53,7 +53,7 @@ Validates config and initializes the provider. Invalid config returns a nil clie | Name | Type | Description | | ---------- | ------------------------------------ | ------------------------------------------------------------------ | | `provider` | `Provider` | Provider constructor from a provider package | -| `config` | [`*Config`](/docs/api/configuration) | Shared settings (`Auth`, `Scope`, `Endpoint`, `Region`, `Timeout`) | +| `config` | [`*Config`](/docs/sdk/configuration) | Shared settings (`Auth`, `Scope`, `Endpoint`, `Region`, `Timeout`) | **Returns** @@ -110,12 +110,12 @@ Creates one sandbox and returns its handle. Omit the request (or pass `{}`) to u | Name | Type | Description | | ---------- | --------------------------------------------------------- | --------------------------------------------------- | -| `request?` | [`CreateOptions`](/docs/api/create-options) | Create body. Omitted fields keep provider defaults. | -| `options?` | [`OperationOptions`](/docs/api/sandbox#operation-options) | Call `timeout` (ms) and optional `signal` | +| `request?` | [`CreateOptions`](/docs/sdk/create-options) | Create body. Omitted fields keep provider defaults. | +| `options?` | [`OperationOptions`](/docs/sdk/sandbox#operation-options) | Call `timeout` (ms) and optional `signal` | **Returns** -`Promise<`[`Sandbox`](/docs/api/sandbox)`>` — handle for the new sandbox +`Promise<`[`Sandbox`](/docs/sdk/sandbox)`>` — handle for the new sandbox **Example** @@ -157,7 +157,7 @@ Creates one sandbox and returns its handle. A nil request uses provider defaults | Name | Type | Description | | --------- | -------------------------------------------- | ----------------------------- | | `ctx` | `context.Context` | Cancellation and deadline | -| `request` | [`*CreateOptions`](/docs/api/create-options) | Create body; nil for defaults | +| `request` | [`*CreateOptions`](/docs/sdk/create-options) | Create body; nil for defaults | **Returns** diff --git a/website/content/docs/api/configuration.mdx b/website/content/docs/sdk/configuration.mdx similarity index 94% rename from website/content/docs/api/configuration.mdx rename to website/content/docs/sdk/configuration.mdx index 1a2cd392..fcca0720 100644 --- a/website/content/docs/api/configuration.mdx +++ b/website/content/docs/sdk/configuration.mdx @@ -3,7 +3,7 @@ title: Client config description: ClientConfig, Config, auth credentials, and Scope. --- -Passed at client construction. Credentials are checked on the first provider call, not at construction. Do not log the config object—it holds secrets. +Passed at client construction. Credentials are checked on the first provider call, not at construction. ## Config @@ -26,7 +26,7 @@ type Config = { | ----------- | -------------------- | ---------------------------------------------------------------------- | | `provider` | `Provider` | Provider constructor from a provider package | | `auth?` | [`AuthInput`](#auth) | Credential set. Omit to use env/profile credentials from the provider. | -| `endpoint?` | `string` | API base URL override. Remote URLs must be HTTPS. | +| `endpoint?` | `string` | Provider endpoint URL override. Remote URLs must be HTTPS. | | `region?` | `string` | Default region or target preference | | `scope?` | [`Scope`](#scope) | App, environment, organization, or project | | `timeout?` | `number` | Default deadline (ms) for calls that omit their own timeout | @@ -65,7 +65,7 @@ Pass `config` to `NewClient(provider, config)`. | Field | Description | | ---------- | ------------------------------------------------------------------- | | `Auth` | Credential set. Nil uses env/profile credentials from the provider. | -| `Endpoint` | API base URL override | +| `Endpoint` | Provider endpoint URL override | | `Region` | Default region or target preference | | `Scope` | App, environment, organization, or project | | `Timeout` | Default client deadline via `sandbox.Duration` | @@ -114,7 +114,7 @@ type AuthInput = | Variant | Description | | -------------- | --------------------------------------------------- | -| `apiKey` | Single API key string | +| `apiKey` | Single key string | | `tokenPair` | Id and secret pair | | `bearerToken` | Bearer or JWT token | | `oauthRefresh` | Refresh token plus client id and one secret/JWT key | @@ -134,7 +134,7 @@ type AuthInput = | Variant | Description | | -------------- | --------------------------------------------------- | -| `APIKey` | Single API key string | +| `APIKey` | Single key string | | `TokenPair` | Id and secret pair | | `BearerToken` | Bearer or JWT token | | `OAuthRefresh` | Refresh token plus client id and one secret/JWT key | diff --git a/website/content/docs/api/create-options.mdx b/website/content/docs/sdk/create-options.mdx similarity index 97% rename from website/content/docs/api/create-options.mdx rename to website/content/docs/sdk/create-options.mdx index a6fd5865..672adb69 100644 --- a/website/content/docs/api/create-options.mdx +++ b/website/content/docs/sdk/create-options.mdx @@ -3,7 +3,7 @@ title: CreateOptions description: Create request body and nested option types. --- -Request body for [`Client.create`](/docs/api/client#create). Omitted fields keep provider defaults. Unsupported fields fail before the provider call. +Request body for [`Client.create`](/docs/sdk/client#create). Omitted fields keep provider defaults. Unsupported fields fail before the provider call. ## CreateOptions @@ -330,7 +330,7 @@ Set exactly one variant. Unsupported variants fail before the provider call. | Field | Description | | ------- | ----------------------------------------------------------------------------- | -| `mode` | [`PolicyMode`](/docs/api/enums#policymode): `Default`, `Disabled`, or `After` | +| `mode` | [`PolicyMode`](/docs/sdk/enums#policymode): `Default`, `Disabled`, or `After` | | `after` | Delay when mode is `After`. Zero means immediate, not disabled. | @@ -338,7 +338,7 @@ Set exactly one variant. Unsupported variants fail before the provider call. | Field | Description | | ------- | ----------------------------------------------------------------------------- | -| `Mode` | [`PolicyMode`](/docs/api/enums#policymode): `Default`, `Disabled`, or `After` | +| `Mode` | [`PolicyMode`](/docs/sdk/enums#policymode): `Default`, `Disabled`, or `After` | | `After` | Delay when mode is `After`. Zero means immediate, not disabled. | @@ -353,7 +353,7 @@ Set exactly one variant. Unsupported variants fail before the provider call. | -------------- | ----------------------------------------------------------------- | | `timeout` | Deadline for the create call | | `queueTimeout` | How long creation may sit in a queue | -| `waitFor` | [`WaitCondition`](/docs/api/enums#waitcondition) before returning | +| `waitFor` | [`WaitCondition`](/docs/sdk/enums#waitcondition) before returning | `timeout` must be whole seconds. Omit or `0` still leaves Daytona's **60s** @@ -373,7 +373,7 @@ Set exactly one variant. Unsupported variants fail before the provider call. | -------------- | ----------------------------------------------------------------- | | `Timeout` | Deadline for the create call | | `QueueTimeout` | How long creation may sit in a queue | -| `WaitFor` | [`WaitCondition`](/docs/api/enums#waitcondition) before returning | +| `WaitFor` | [`WaitCondition`](/docs/sdk/enums#waitcondition) before returning | `Timeout` must be whole seconds. Omit or zero still leaves Daytona's **60s** @@ -419,7 +419,7 @@ Set either a TCP port or a command. | Field | Description | | ------------------ | ----------------------------------------------------------- | -| `egress` | [`EgressMode`](/docs/api/enums#egressmode) | +| `egress` | [`EgressMode`](/docs/sdk/enums#egressmode) | | `outboundCidrs` | Outbound CIDR allowlist. Present empty list means deny-all. | | `outboundDomains` | Outbound domain allowlist | | `inboundCidrs` | Inbound CIDR allowlist | @@ -435,7 +435,7 @@ Set either a TCP port or a command. | Field | Description | | ------------------ | ----------------------------------------------------------- | -| `Egress` | [`EgressMode`](/docs/api/enums#egressmode) | +| `Egress` | [`EgressMode`](/docs/sdk/enums#egressmode) | | `OutboundCidrs` | Outbound CIDR allowlist. Present empty list means deny-all. | | `OutboundDomains` | Outbound domain allowlist | | `InboundCidrs` | Inbound CIDR allowlist | diff --git a/website/content/docs/api/enums.mdx b/website/content/docs/sdk/enums.mdx similarity index 95% rename from website/content/docs/api/enums.mdx rename to website/content/docs/sdk/enums.mdx index 39990869..b79e3bd3 100644 --- a/website/content/docs/api/enums.mdx +++ b/website/content/docs/sdk/enums.mdx @@ -5,7 +5,7 @@ description: Shared public enums for create, lifecycle, and info. ## SandboxState -Portable lifecycle state on [`SandboxInfo`](/docs/api/sandbox-info). +Portable lifecycle state on [`SandboxInfo`](/docs/sdk/sandbox-info). | Value | Description | | ------------- | --------------------------------- | @@ -27,7 +27,7 @@ Portable lifecycle state on [`SandboxInfo`](/docs/api/sandbox-info). ## LifecycleCapability -Used with [Capabilities](/docs/api/sandbox#capabilities). File and process calls are not capabilities. +Used with [Capabilities](/docs/sdk/sandbox#capabilities). File and process calls are not capabilities. | Value | Description | | ----------- | -------------------------------------- | @@ -42,7 +42,7 @@ Used with [Capabilities](/docs/api/sandbox#capabilities). File and process calls ## PolicyMode -Idle/stopped automatic actions under [`LifetimePolicy`](/docs/api/create-options#lifetimepolicy). +Idle/stopped automatic actions under [`LifetimePolicy`](/docs/sdk/create-options#lifetimepolicy). | Value | Description | | ---------- | ------------------------------------------ | @@ -123,7 +123,7 @@ How a create-time secret reference is exposed. ## FileType -Filesystem entry kind on [`FileInfo`](/docs/api/filesystem#fileinfo). +Filesystem entry kind on [`FileInfo`](/docs/sdk/filesystem#fileinfo). | Value | Description | | ------------- | --------------------- | @@ -134,7 +134,7 @@ Filesystem entry kind on [`FileInfo`](/docs/api/filesystem#fileinfo). ## ErrorKind -Error category on the typed error. Not retry advice. See also [Errors](/docs/api/errors). +Error category on the typed error. Not retry advice. See also [Errors](/docs/sdk/errors). | Value | Description | | -------------------- | ------------------------------------------------------ | diff --git a/website/content/docs/api/errors.mdx b/website/content/docs/sdk/errors.mdx similarity index 100% rename from website/content/docs/api/errors.mdx rename to website/content/docs/sdk/errors.mdx diff --git a/website/content/docs/api/filesystem.mdx b/website/content/docs/sdk/filesystem.mdx similarity index 99% rename from website/content/docs/api/filesystem.mdx rename to website/content/docs/sdk/filesystem.mdx index 0ec138e7..90055e93 100644 --- a/website/content/docs/api/filesystem.mdx +++ b/website/content/docs/sdk/filesystem.mdx @@ -457,7 +457,7 @@ Metadata for one file, directory, or symlink. | --------------- | ------------------------------------------------------------------- | | `name` | Base name | | `path` | Absolute path in the sandbox | -| `type` | [`FileType`](/docs/api/enums#filetype): file, directory, or symlink | +| `type` | [`FileType`](/docs/sdk/enums#filetype): file, directory, or symlink | | `size` | Size in bytes | | `mode` | Unix mode string when reported (for example `0644`) | | `permissions` | Symbolic permissions when reported | @@ -473,7 +473,7 @@ Metadata for one file, directory, or symlink. | --------------- | ------------------------------------------------------------------- | | `Name` | Base name | | `Path` | Absolute path in the sandbox | -| `Type` | [`FileType`](/docs/api/enums#filetype): file, directory, or symlink | +| `Type` | [`FileType`](/docs/sdk/enums#filetype): file, directory, or symlink | | `Size` | Size in bytes | | `Mode` | Unix mode string when reported (for example `0644`) | | `Permissions` | Symbolic permissions when reported | diff --git a/website/content/docs/api/index.mdx b/website/content/docs/sdk/index.mdx similarity index 66% rename from website/content/docs/api/index.mdx rename to website/content/docs/sdk/index.mdx index 4fb47ebf..025fce78 100644 --- a/website/content/docs/api/index.mdx +++ b/website/content/docs/sdk/index.mdx @@ -5,7 +5,7 @@ description: User-facing types and methods for the Sandbox Kit core SDK. Public surface of the core sandbox package. Guides show how pieces fit together; this section documents signatures, parameters, and return values. -Use the language tabs on each page. Unsupported calls return a typed error—see [Errors](/docs/api/errors) and the [Errors guide](/docs/errors). +Use the language tabs on each page. Unsupported calls return a typed error—see [Errors](/docs/sdk/errors) and the [Errors guide](/docs/errors). @@ -22,12 +22,12 @@ Use the language tabs on each page. Unsupported calls return a typed error—see | Name | Description | | ----------------------------------------- | ------------------------------------------------------------ | -| [Client](/docs/api/client) | Construct a provider connection; create and open sandboxes | -| [Sandbox](/docs/api/sandbox) | Handle for one sandbox: lifecycle, info, filesystem, process | -| [Filesystem](/docs/api/filesystem) | Read, write, copy, list, stat, and remove files | -| [Process](/docs/api/process) | Run a command and collect exit code and output | -| [Client config](/docs/api/configuration) | Client config, auth, and scope types | -| [CreateOptions](/docs/api/create-options) | Create request body and nested option types | -| [SandboxInfo](/docs/api/sandbox-info) | Metadata returned by info and lifecycle calls | -| [Errors](/docs/api/errors) | Typed error shape and kinds | -| [Enums](/docs/api/enums) | Shared enums (`SandboxState`, `PolicyMode`, …) | +| [Client](/docs/sdk/client) | Construct a provider connection; create and open sandboxes | +| [Sandbox](/docs/sdk/sandbox) | Handle for one sandbox: lifecycle, info, filesystem, process | +| [Filesystem](/docs/sdk/filesystem) | Read, write, copy, list, stat, and remove files | +| [Process](/docs/sdk/process) | Run a command and collect exit code and output | +| [Client config](/docs/sdk/configuration) | Client config, auth, and scope types | +| [CreateOptions](/docs/sdk/create-options) | Create request body and nested option types | +| [SandboxInfo](/docs/sdk/sandbox-info) | Metadata returned by info and lifecycle calls | +| [Errors](/docs/sdk/errors) | Typed error shape and kinds | +| [Enums](/docs/sdk/enums) | Shared enums (`SandboxState`, `PolicyMode`, …) | diff --git a/website/content/docs/api/meta.json b/website/content/docs/sdk/meta.json similarity index 91% rename from website/content/docs/api/meta.json rename to website/content/docs/sdk/meta.json index 7c21247f..9d983b6b 100644 --- a/website/content/docs/api/meta.json +++ b/website/content/docs/sdk/meta.json @@ -1,5 +1,5 @@ { - "title": "API", + "title": "SDK", "pages": [ "index", "client", diff --git a/website/content/docs/api/process.mdx b/website/content/docs/sdk/process.mdx similarity index 100% rename from website/content/docs/api/process.mdx rename to website/content/docs/sdk/process.mdx diff --git a/website/content/docs/api/sandbox-info.mdx b/website/content/docs/sdk/sandbox-info.mdx similarity index 93% rename from website/content/docs/api/sandbox-info.mdx rename to website/content/docs/sdk/sandbox-info.mdx index 4fa390b4..47fbe0de 100644 --- a/website/content/docs/api/sandbox-info.mdx +++ b/website/content/docs/sdk/sandbox-info.mdx @@ -7,10 +7,10 @@ Returned by info and many lifecycle methods. Values are a **copy**; mutating the - From [`sandbox.info()`](/docs/api/sandbox#read-metadata). + From [`sandbox.info()`](/docs/sdk/sandbox#read-metadata). - From [`instance.Info()`](/docs/api/sandbox#read-metadata). + From [`instance.Info()`](/docs/sdk/sandbox#read-metadata). @@ -31,7 +31,7 @@ Returned by info and many lifecycle methods. Values are a **copy**; mutating the | `labels` | Labels when reported | | `createdAt` | Creation time when reported | | `providerMetadata` | Extra provider metadata object | -| `state` | Portable [`SandboxState`](/docs/api/enums#sandboxstate) | +| `state` | Portable [`SandboxState`](/docs/sdk/enums#sandboxstate) | | `terminal` | Whether the lifecycle is permanently complete | **Example** @@ -58,7 +58,7 @@ console.log(info); | `Labels` | Labels when reported | | `CreatedAt` | Creation time when reported | | `ProviderMetadata` | Extra provider metadata object | -| `State` | Portable [`SandboxState`](/docs/api/enums#sandboxstate) | +| `State` | Portable [`SandboxState`](/docs/sdk/enums#sandboxstate) | | `Terminal` | Whether the lifecycle is permanently complete | **Example** diff --git a/website/content/docs/api/sandbox.mdx b/website/content/docs/sdk/sandbox.mdx similarity index 96% rename from website/content/docs/api/sandbox.mdx rename to website/content/docs/sdk/sandbox.mdx index b970b5cc..0b1173b5 100644 --- a/website/content/docs/api/sandbox.mdx +++ b/website/content/docs/sdk/sandbox.mdx @@ -3,7 +3,7 @@ title: Sandbox description: Handle for one sandbox — lifecycle, info, filesystem, and process. --- -Handle from [`Client.create`](/docs/api/client#create), [`get`](/docs/api/client#get), or [`attach`](/docs/api/client#attach). Lifecycle methods that return info also update the handle. `close` only drops local resources—the cloud sandbox keeps running. Call `supports` before a lifecycle method that might be unavailable. +Handle from [`Client.create`](/docs/sdk/client#create), [`get`](/docs/sdk/client#get), or [`attach`](/docs/sdk/client#attach). Lifecycle methods that return info also update the handle. `close` only drops local resources—the cloud sandbox keeps running. Call `supports` before a lifecycle method that might be unavailable. ## Properties @@ -14,8 +14,8 @@ Handle from [`Client.create`](/docs/api/client#create), [`get`](/docs/api/client | -------------- | ------------------------------------ | -------------------------------- | | `id` | `string` | Sandbox identifier | | `providerName` | `string` | Provider that owns this sandbox | -| `filesystem` | [`Filesystem`](/docs/api/filesystem) | File operations for this sandbox | -| `process` | [`Process`](/docs/api/process) | Command runner for this sandbox | +| `filesystem` | [`Filesystem`](/docs/sdk/filesystem) | File operations for this sandbox | +| `process` | [`Process`](/docs/sdk/process) | Command runner for this sandbox | @@ -45,7 +45,7 @@ Returns a **copy** of current metadata. Mutating it does not change the handle. **Returns** -[`SandboxInfo`](/docs/api/sandbox-info) +[`SandboxInfo`](/docs/sdk/sandbox-info) **Example** @@ -67,7 +67,7 @@ Returns a **copy** of current metadata. Mutating it does not change the handle. **Returns** -[`*SandboxInfo`](/docs/api/sandbox-info) +[`*SandboxInfo`](/docs/sdk/sandbox-info) **Example** @@ -97,7 +97,7 @@ Lists lifecycle operations this handle can attempt, or checks one. File and proc | Name | Type | Description | | ------------ | ------------------------------------------------------------ | ------------------------------------------- | -| `capability` | [`LifecycleCapability`](/docs/api/enums#lifecyclecapability) | Capability to test (`Stop`, `Terminate`, …) | +| `capability` | [`LifecycleCapability`](/docs/sdk/enums#lifecyclecapability) | Capability to test (`Stop`, `Terminate`, …) | **Returns** @@ -139,7 +139,7 @@ Lists lifecycle operations this handle can attempt, or checks one. | Name | Type | Description | | ------------ | ------------------------------------------------------------ | ------------------ | -| `capability` | [`LifecycleCapability`](/docs/api/enums#lifecyclecapability) | Capability to test | +| `capability` | [`LifecycleCapability`](/docs/sdk/enums#lifecyclecapability) | Capability to test | **Returns** From 449ad31daee5c6980edf683333b2b2425dec1817 Mon Sep 17 00:00:00 2001 From: Nabhag Motivaras <65061890+Nabhag8848@users.noreply.github.com> Date: Thu, 5 Nov 2026 22:50:00 +0530 Subject: [PATCH 5/5] Polish the site brand lockup and homepage hero. Use an SVG cube mark in the nav wordmark, keep the home title text-only, and stagger the hero entrance motion. Co-authored-by: Cursor --- website/src/components/brand-mark.tsx | 34 ++++++++++++++++++++++++ website/src/components/logo-mark.tsx | 37 +++++++++++++++++++++++++++ website/src/lib/layout.shared.tsx | 16 +++--------- website/src/routes/index.tsx | 31 ++++++++++------------ website/src/styles/app.css | 34 +++++++++++++++++++----- 5 files changed, 115 insertions(+), 37 deletions(-) create mode 100644 website/src/components/brand-mark.tsx create mode 100644 website/src/components/logo-mark.tsx diff --git a/website/src/components/brand-mark.tsx b/website/src/components/brand-mark.tsx new file mode 100644 index 00000000..f601a895 --- /dev/null +++ b/website/src/components/brand-mark.tsx @@ -0,0 +1,34 @@ +import { cn } from "@/lib/cn"; +import { LogoMark } from "@/components/logo-mark"; + +/** Nav / sidebar wordmark — white/black cube badge + lowercase name. */ +export function BrandMark({ + className, + logoClassName, + showLogo = true, +}: { + className?: string; + logoClassName?: string; + showLogo?: boolean; +}) { + return ( + + {showLogo ? ( + + ) : null} + + sandbox-kit + + + ); +} diff --git a/website/src/components/logo-mark.tsx b/website/src/components/logo-mark.tsx new file mode 100644 index 00000000..ffa49b77 --- /dev/null +++ b/website/src/components/logo-mark.tsx @@ -0,0 +1,37 @@ +import { cn } from "@/lib/cn"; + +/** White square badge with a black isometric cube. */ +export function LogoMark({ + className, + title, +}: { + className?: string; + title?: string; +}) { + return ( + + {title ? {title} : null} + + {/* Cube sized like the original mark — room around it on the white badge */} + + + + + + ); +} diff --git a/website/src/lib/layout.shared.tsx b/website/src/lib/layout.shared.tsx index f050509c..ca9909b5 100644 --- a/website/src/lib/layout.shared.tsx +++ b/website/src/lib/layout.shared.tsx @@ -1,21 +1,11 @@ import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared"; -import { appName, assetUrl, gitConfig } from "./shared"; +import { BrandMark } from "@/components/brand-mark"; +import { gitConfig } from "./shared"; export function baseOptions(): BaseLayoutProps { return { nav: { - title: ( - - - {appName} - - ), + title: , }, githubUrl: `https://github.com/${gitConfig.user}/${gitConfig.repo}`, }; diff --git a/website/src/routes/index.tsx b/website/src/routes/index.tsx index 1aae9166..fec9c258 100644 --- a/website/src/routes/index.tsx +++ b/website/src/routes/index.tsx @@ -2,7 +2,6 @@ import { createFileRoute, Link } from "@tanstack/react-router"; import { HomeLayout } from "fumadocs-ui/layouts/home"; import { HomeCodeSample } from "@/components/home-code-sample"; import { baseOptions } from "@/lib/layout.shared"; -import { assetUrl } from "@/lib/shared"; import { siteSocialHead } from "@/lib/seo"; export const Route = createFileRoute("/")({ @@ -30,48 +29,44 @@ function Home() { className="pointer-events-none absolute inset-0 opacity-[0.35] [background-image:linear-gradient(to_right,rgba(17,17,16,0.045)_1px,transparent_1px),linear-gradient(to_bottom,rgba(17,17,16,0.045)_1px,transparent_1px)] [background-size:48px_48px] dark:opacity-[0.18]" /> -
+
- -

- Sandbox Kit +

+ sandbox-kit

-

+ +

SDK for cloud sandboxes in TypeScript or Go. Plug in a provider; the client talks to it for create, files, and commands.

-
+ +
Quickstart Concepts
-

+ +

One client · many providers

-

+

Create, then run

-
+
diff --git a/website/src/styles/app.css b/website/src/styles/app.css index 1dd2801b..a6b22f4c 100644 --- a/website/src/styles/app.css +++ b/website/src/styles/app.css @@ -72,24 +72,43 @@ body { max-height: 100dvh; } -.home-copy, +.home-brand, +.home-lede, +.home-cta, +.home-meta, .home-sample, .home-code { - animation: home-rise 700ms cubic-bezier(0.22, 1, 0.36, 1) both; + animation: home-rise 720ms cubic-bezier(0.22, 1, 0.36, 1) both; +} + +.home-brand { + animation-delay: 40ms; +} + +.home-lede { + animation-delay: 130ms; +} + +.home-cta { + animation-delay: 210ms; +} + +.home-meta { + animation-delay: 290ms; } .home-sample { - animation-delay: 90ms; + animation-delay: 160ms; } .home-code { - animation-delay: 160ms; + animation-delay: 240ms; } @keyframes home-rise { from { opacity: 0; - transform: translateY(12px); + transform: translateY(14px); } to { opacity: 1; @@ -98,7 +117,10 @@ body { } @media (prefers-reduced-motion: reduce) { - .home-copy, + .home-brand, + .home-lede, + .home-cta, + .home-meta, .home-sample, .home-code { animation: none;