DaytonaSandboxProvider
A Daytona sandbox provider creates each sandbox in Daytona’s cloud, a Linux machine of its own, which Daytona names by the sandbox’s id. It reaches Daytona through Daytona’s SDK, with the API key of the organization the sandboxes belong to, and closes the SDK’s client with its scope.
A sandbox made from a template starts from a snapshot of the template’s version once Daytona has made one, and is prepared on its own until then; snapshots still being made when the provider’s scope closes are left for the next create to make.
A sandbox runs until it is stopped or destroyed. Daytona stops a sandbox that sees no requests to its API for a while, and requests to the sandbox’s ports do not count, so a sandbox would stop under an agent that only serves a host through a port; the provider turns that off unless the options set it. A port’s endpoint is Daytona’s preview URL for it, which takes the sandbox’s preview token in a header and passes the request’s other headers on. Daytona opens a sandbox’s port the first time it gives its preview URL, so exposing a port only records it.
Since v0.1.0
Constructors
Section titled “Constructors”The provider over Daytona’s SDK with options, in a scope that closes the SDK’s client and
leaves snapshots still being made to a later create.
Details
It needs Effect’s Crypto service, as BunCrypto.layer or NodeCrypto.layer provide it.
Example (A provider for one piece of work)
import { DaytonaSandboxProvider } from "@amends-dev/sandbox-daytona"import { BunCrypto } from "@effect/platform-bun"import { Effect, Redacted } from "effect"
declare const apiKey: Redacted.Redacted<string>
const program = Effect.gen(function* () { const sandboxProvider = yield* DaytonaSandboxProvider.make({ apiKey, target: "eu" }) const sandbox = yield* sandboxProvider.createScoped() return sandbox.workingDirectory}).pipe(Effect.scoped, Effect.provide(BunCrypto.layer))Signature
declare const make: ( options: Options) => Effect.Effect< { readonly create: <E = never>( options?: SandboxProvider.CreateOptions<E> ) => Effect.Effect<Sandbox.Sandbox["Service"], SandboxError.SandboxError | E> readonly createScoped: <E = never>( options?: SandboxProvider.CreateOptions<E> ) => Effect.Effect<Sandbox.Sandbox["Service"], SandboxError.SandboxError | E, Scope> readonly resume: (id: Sandbox.SandboxId) => Effect.Effect<Sandbox.Sandbox["Service"], SandboxError.SandboxError> }, never, Scope | Crypto.Crypto>Since v0.1.0
Layers
Section titled “Layers”Provides the SandboxProvider service over Daytona with options, as make makes it, to a
program that keeps its sandboxes on Daytona.
Example (Sandboxes of the organization whose key the environment holds)
import { SandboxProvider } from "@amends-dev/sandbox"import { DaytonaSandboxProvider } from "@amends-dev/sandbox-daytona"import { BunCrypto } from "@effect/platform-bun"import { Config, Effect, Layer } from "effect"
const sandboxes = Layer.unwrap( Effect.map(Config.Redacted("DAYTONA_API_KEY"), (apiKey) => DaytonaSandboxProvider.layer({ apiKey }))).pipe(Layer.provide(BunCrypto.layer))
const program = Effect.gen(function* () { const sandboxProvider = yield* SandboxProvider.SandboxProvider const sandbox = yield* sandboxProvider.create() return sandbox.id}).pipe(Effect.provide(sandboxes))Signature
declare const layer: (options: Options) => Layer.Layer<SandboxProvider.SandboxProvider, never, Crypto.Crypto>Since v0.1.0
Options
Section titled “Options”Options (interface)
Section titled “Options (interface)”How the provider reaches Daytona, and what every sandbox it creates gets unless the sandbox’s
ProviderOptions say otherwise.
Signature
export interface Options { /** The API key of the Daytona organization the sandboxes belong to. */ readonly apiKey: Redacted.Redacted<string>
/** Daytona's API, when it is not that of Daytona's own cloud. */ readonly apiUrl?: string
/** The region to create sandboxes in, such as `us` or `eu`, rather than the organization's. */ readonly target?: string
/** The snapshot sandboxes start from, rather than Daytona's default. */ readonly snapshot?: string
/** * Minutes without requests to Daytona's API, which requests to the sandbox's ports do not count * as, after which Daytona stops a sandbox. 0, the default, never stops it. */ readonly autoStopInterval?: number}Since v0.1.0
ProviderOptions
Section titled “ProviderOptions”What a sandbox on Daytona is created with besides the contract’s options, under
providerOptions.daytona, each in place of the provider’s own option for this sandbox.
Details
An entry that is not this fails the create with InvalidOptionsError before Daytona is asked.
Example (A sandbox from another snapshot, which Daytona stops after an hour idle)
import { SandboxProvider } from "@amends-dev/sandbox"import { Effect } from "effect"
const program = Effect.gen(function* () { const sandboxProvider = yield* SandboxProvider.SandboxProvider return yield* sandboxProvider.create({ providerOptions: { daytona: { snapshot: "python-3.13", autoStopInterval: 60 } } })})Signature
declare const ProviderOptions: Schema.Struct<{ readonly snapshot: Schema.optionalKey<Schema.String> readonly autoStopInterval: Schema.optionalKey<Schema.Int>}>Since v0.1.0
ProviderOptions (type alias)
Section titled “ProviderOptions (type alias)”Signature
type ProviderOptions = typeof ProviderOptions.TypeSince v0.1.0