withruntime 0.3.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DAYTONA.md +129 -0
- package/E2B.md +146 -0
- package/README.md +84 -12
- package/VERCEL.md +127 -0
- package/dist/ai/index.d.ts +33 -0
- package/dist/ai/index.js +38 -0
- package/dist/claude-agent-sdk/index.d.ts +7 -0
- package/dist/claude-agent-sdk/index.js +65 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.js +949 -105
- package/dist/client.d.ts +25 -2
- package/dist/client.js +14 -1
- package/dist/credentials.d.ts +10 -0
- package/dist/credentials.js +56 -1
- package/dist/daytona/client.d.ts +44 -0
- package/dist/daytona/client.js +40 -0
- package/dist/daytona/context.d.ts +26 -0
- package/dist/daytona/context.js +22 -0
- package/dist/daytona/daytona.d.ts +185 -0
- package/dist/daytona/daytona.js +416 -0
- package/dist/daytona/errors.d.ts +106 -0
- package/dist/daytona/errors.js +182 -0
- package/dist/daytona/filesystem.d.ts +84 -0
- package/dist/daytona/filesystem.js +206 -0
- package/dist/daytona/git.d.ts +33 -0
- package/dist/daytona/git.js +128 -0
- package/dist/daytona/image.d.ts +45 -0
- package/dist/daytona/image.js +140 -0
- package/dist/daytona/index.d.ts +50 -0
- package/dist/daytona/index.js +50 -0
- package/dist/daytona/process.d.ts +86 -0
- package/dist/daytona/process.js +339 -0
- package/dist/daytona/sandbox.d.ts +196 -0
- package/dist/daytona/sandbox.js +448 -0
- package/dist/e2b/client.d.ts +58 -0
- package/dist/e2b/client.js +66 -0
- package/dist/e2b/code-interpreter.d.ts +144 -0
- package/dist/e2b/code-interpreter.js +244 -0
- package/dist/e2b/commands.d.ts +100 -0
- package/dist/e2b/commands.js +268 -0
- package/dist/e2b/errors.d.ts +72 -0
- package/dist/e2b/errors.js +151 -0
- package/dist/e2b/filesystem.d.ts +82 -0
- package/dist/e2b/filesystem.js +143 -0
- package/dist/e2b/index.d.ts +28 -0
- package/dist/e2b/index.js +61 -0
- package/dist/e2b/sandbox.d.ts +203 -0
- package/dist/e2b/sandbox.js +490 -0
- package/dist/e2b/unsupported.d.ts +19 -0
- package/dist/e2b/unsupported.js +27 -0
- package/dist/errors.d.ts +10 -4
- package/dist/errors.js +26 -6
- package/dist/image-context.d.ts +39 -0
- package/dist/image-context.js +176 -0
- package/dist/index.d.ts +19 -2
- package/dist/index.js +17 -2
- package/dist/keys.d.ts +43 -0
- package/dist/keys.js +196 -0
- package/dist/login.js +27 -6
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +4 -3
- package/dist/openai-agents/index.d.ts +132 -0
- package/dist/openai-agents/index.js +791 -0
- package/dist/products/audit.d.ts +48 -0
- package/dist/products/audit.js +10 -0
- package/dist/products/images.d.ts +113 -7
- package/dist/products/images.js +186 -27
- package/dist/products/index.d.ts +11 -0
- package/dist/products/index.js +17 -1
- package/dist/products/observability.d.ts +186 -0
- package/dist/products/observability.js +117 -0
- package/dist/products/secrets.d.ts +40 -0
- package/dist/products/secrets.js +24 -0
- package/dist/products/switching.d.ts +89 -0
- package/dist/products/switching.js +25 -0
- package/dist/proxy.d.ts +30 -0
- package/dist/proxy.js +178 -0
- package/dist/sandbox.d.ts +30 -2
- package/dist/sandbox.js +101 -1
- package/dist/ssh.d.ts +21 -0
- package/dist/ssh.js +312 -0
- package/dist/tar.d.ts +1 -0
- package/dist/tar.js +4 -4
- package/dist/tools/index.d.ts +62 -0
- package/dist/tools/index.js +180 -0
- package/dist/transport.d.ts +12 -2
- package/dist/transport.js +76 -16
- package/dist/tunnel.d.ts +67 -0
- package/dist/tunnel.js +311 -0
- package/dist/types.d.ts +57 -1
- package/dist/vercel/client.d.ts +40 -0
- package/dist/vercel/client.js +39 -0
- package/dist/vercel/command.d.ts +70 -0
- package/dist/vercel/command.js +148 -0
- package/dist/vercel/errors.d.ts +53 -0
- package/dist/vercel/errors.js +113 -0
- package/dist/vercel/filesystem.d.ts +150 -0
- package/dist/vercel/filesystem.js +248 -0
- package/dist/vercel/index.d.ts +30 -0
- package/dist/vercel/index.js +38 -0
- package/dist/vercel/sandbox.d.ts +317 -0
- package/dist/vercel/sandbox.js +726 -0
- package/dist/vercel/snapshot.d.ts +93 -0
- package/dist/vercel/snapshot.js +123 -0
- package/package.json +69 -5
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
import { clientFor, } from "./client.js";
|
|
2
|
+
import { DaytonaError, DaytonaNotFoundError, guard, NotSupportedError } from "./errors.js";
|
|
3
|
+
import { networkRules, notFound, retentionDays, Sandbox, windowSeconds, } from "./sandbox.js";
|
|
4
|
+
/* Daytona's client over Runtime's. `new Daytona()` then `daytona.create()`
|
|
5
|
+
makes a Runtime sandbox with Daytona's defaults. */
|
|
6
|
+
/** Daytona's default machine: 1 vCPU, 1 GiB memory, 3 GiB disk (checked
|
|
7
|
+
* 23 September 2026). */
|
|
8
|
+
export const DEFAULT_RESOURCES = { cpu: 1, memory: 1, disk: 3 };
|
|
9
|
+
/** Daytona's default autoStopInterval, 15 minutes. */
|
|
10
|
+
export const DEFAULT_AUTO_STOP_MINUTES = 15;
|
|
11
|
+
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
12
|
+
/** Daytona's own snapshots (daytona-small, daytonaio/sandbox:...) are
|
|
13
|
+
* Runtime's stock image: Ubuntu 24.04 with Python 3.12, Node.js 24 and Bun. */
|
|
14
|
+
const STOCK_SNAPSHOT = /^daytona(io)?[-/:]|^daytona$/;
|
|
15
|
+
/** Daytona's label for a sandbox's code language. */
|
|
16
|
+
export const LANGUAGE_LABEL = "code-toolbox-language";
|
|
17
|
+
export var CodeLanguage;
|
|
18
|
+
(function (CodeLanguage) {
|
|
19
|
+
CodeLanguage["PYTHON"] = "python";
|
|
20
|
+
CodeLanguage["TYPESCRIPT"] = "typescript";
|
|
21
|
+
CodeLanguage["JAVASCRIPT"] = "javascript";
|
|
22
|
+
})(CodeLanguage || (CodeLanguage = {}));
|
|
23
|
+
/** An image name Runtime accepts: letters, digits, dot, dash and underscore. */
|
|
24
|
+
const imageName = (reference) => reference.replace(/[^A-Za-z0-9._-]+/g, "-").slice(0, 128);
|
|
25
|
+
function snapshotOf(image) {
|
|
26
|
+
const state = image.state === "ready"
|
|
27
|
+
? "active"
|
|
28
|
+
: image.state === "failed"
|
|
29
|
+
? "error"
|
|
30
|
+
: image.state === "deleting" || image.state === "deleted"
|
|
31
|
+
? "removing"
|
|
32
|
+
: image.state === "queued"
|
|
33
|
+
? "pending"
|
|
34
|
+
: "building";
|
|
35
|
+
return {
|
|
36
|
+
id: image.id,
|
|
37
|
+
name: image.name ?? image.id,
|
|
38
|
+
imageName: image.name ?? image.id,
|
|
39
|
+
state,
|
|
40
|
+
size: image.sizeBytes === null ? null : image.sizeBytes / 1_073_741_824,
|
|
41
|
+
errorReason: image.error,
|
|
42
|
+
createdAt: image.createdAt,
|
|
43
|
+
updatedAt: image.readyAt ?? image.createdAt,
|
|
44
|
+
lastUsedAt: null,
|
|
45
|
+
general: false,
|
|
46
|
+
cpu: 0,
|
|
47
|
+
gpu: 0,
|
|
48
|
+
mem: 0,
|
|
49
|
+
disk: 0,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function volumeOf(volume) {
|
|
53
|
+
return {
|
|
54
|
+
id: volume.id,
|
|
55
|
+
name: volume.name ?? volume.id,
|
|
56
|
+
organizationId: "",
|
|
57
|
+
state: volume.state === "ready" ? "ready" : volume.state,
|
|
58
|
+
createdAt: volume.createdAt,
|
|
59
|
+
updatedAt: volume.readyAt ?? volume.createdAt,
|
|
60
|
+
lastUsedAt: null,
|
|
61
|
+
errorReason: volume.error,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/** Builds (or finds, when built before) the Runtime image for a Daytona
|
|
65
|
+
* image: a registry reference or a declarative Image. */
|
|
66
|
+
async function imageFor(client, image, onLogs, name) {
|
|
67
|
+
const built = typeof image === "string" ? undefined : await image.build();
|
|
68
|
+
const wanted = name ?? (built ? built.name : imageName(image));
|
|
69
|
+
const existing = (await client.images.list({ name: wanted, state: "ready", limit: 1 })).data[0];
|
|
70
|
+
if (existing)
|
|
71
|
+
return existing;
|
|
72
|
+
return client.images.build(built
|
|
73
|
+
? { name: wanted, dockerfile: built.dockerfile, files: built.files }
|
|
74
|
+
: { name: wanted, image: image }, onLogs ? { onLog: (line) => onLogs(`${line.text}\n`) } : {});
|
|
75
|
+
}
|
|
76
|
+
/** `daytona.snapshot`: Daytona snapshots as Runtime images. */
|
|
77
|
+
export class SnapshotService {
|
|
78
|
+
#client;
|
|
79
|
+
constructor(client) {
|
|
80
|
+
this.#client = client;
|
|
81
|
+
}
|
|
82
|
+
async list(queryOrPage, maybeLimit) {
|
|
83
|
+
const query = typeof queryOrPage === "object" ? queryOrPage : { page: queryOrPage, limit: maybeLimit };
|
|
84
|
+
if (query.sourceSandboxId !== undefined)
|
|
85
|
+
throw new NotSupportedError("Listing snapshots by source sandbox", "Use runtime.snapshots.list({ sandboxId }) through sandbox.withruntime.");
|
|
86
|
+
const all = await guard("other", async () => (await this.#client.images.list()).toArray(10_000));
|
|
87
|
+
const limit = query.limit ?? 100;
|
|
88
|
+
const page = query.page ?? 1;
|
|
89
|
+
const items = all.filter((one) => one.state !== "deleted").map(snapshotOf);
|
|
90
|
+
return {
|
|
91
|
+
items: items.slice((page - 1) * limit, page * limit),
|
|
92
|
+
total: items.length,
|
|
93
|
+
page,
|
|
94
|
+
totalPages: Math.max(1, Math.ceil(items.length / limit)),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
async get(idOrName) {
|
|
98
|
+
if (UUID.test(idOrName))
|
|
99
|
+
return snapshotOf(await guard("other", () => this.#client.images.get(idOrName)));
|
|
100
|
+
const found = (await guard("other", () => this.#client.images.list({ name: imageName(idOrName), limit: 1 }))).data[0];
|
|
101
|
+
if (!found)
|
|
102
|
+
throw notFound(`Snapshot ${idOrName}`);
|
|
103
|
+
return snapshotOf(found);
|
|
104
|
+
}
|
|
105
|
+
/** Builds a Runtime image named `name` from a registry image or a Daytona
|
|
106
|
+
* Image, streaming the build log to `onLogs`. */
|
|
107
|
+
async create(params, options = {}) {
|
|
108
|
+
if (params.resources)
|
|
109
|
+
throw new NotSupportedError("Resources on a snapshot", "Pass resources when creating each sandbox from it: daytona.create({ snapshot, resources }).");
|
|
110
|
+
if (params.entrypoint)
|
|
111
|
+
throw new NotSupportedError("An entrypoint on a snapshot", "Start the program in a session after create: process.executeSessionCommand(id, { command, runAsync: true }).");
|
|
112
|
+
const image = await guard("other", () => imageFor(this.#client, params.image, options.onLogs, imageName(params.name)));
|
|
113
|
+
return snapshotOf(image);
|
|
114
|
+
}
|
|
115
|
+
async delete(snapshot) {
|
|
116
|
+
const id = typeof snapshot === "string" ? (await this.get(snapshot)).id : snapshot.id;
|
|
117
|
+
await guard("other", () => this.#client.images.delete(id));
|
|
118
|
+
}
|
|
119
|
+
/** Runtime images do not go inactive: returns the snapshot as it is. */
|
|
120
|
+
async activate(snapshot) {
|
|
121
|
+
return this.get(typeof snapshot === "string" ? snapshot : snapshot.id);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/** `daytona.volume`: Daytona volumes as Runtime volumes. */
|
|
125
|
+
export class VolumeService {
|
|
126
|
+
#client;
|
|
127
|
+
constructor(client) {
|
|
128
|
+
this.#client = client;
|
|
129
|
+
}
|
|
130
|
+
async list() {
|
|
131
|
+
const all = await guard("other", async () => (await this.#client.volumes.list()).toArray(10_000));
|
|
132
|
+
return all.filter((one) => one.state !== "deleted").map(volumeOf);
|
|
133
|
+
}
|
|
134
|
+
async get(name, create = false) {
|
|
135
|
+
const found = (await guard("other", () => this.#client.volumes.list({ name, limit: 1 })))
|
|
136
|
+
.data[0];
|
|
137
|
+
if (found)
|
|
138
|
+
return volumeOf(found);
|
|
139
|
+
if (create)
|
|
140
|
+
return this.create(name);
|
|
141
|
+
throw notFound(`Volume ${name}`);
|
|
142
|
+
}
|
|
143
|
+
create(name) {
|
|
144
|
+
return Promise.reject(new NotSupportedError(`Creating the volume ${name} without a size`, `Runtime volumes have a fixed size: runtime.volumes.create({ name: "${name}", sizeMiB: 10240 }), then mount it by name.`));
|
|
145
|
+
}
|
|
146
|
+
async delete(volume) {
|
|
147
|
+
await guard("other", () => this.#client.volumes.delete(volume.id));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function unsupportedService(name, alternative) {
|
|
151
|
+
return new Proxy({}, {
|
|
152
|
+
get: (_target, property) => {
|
|
153
|
+
if (typeof property === "symbol" || property === "then")
|
|
154
|
+
return undefined;
|
|
155
|
+
return () => Promise.reject(new NotSupportedError(`Daytona's ${name}`, alternative));
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
/** Daytona's client. Uses RUNTIME_API_KEY (or a Runtime key in apiKey or
|
|
160
|
+
* DAYTONA_API_KEY, or the saved `npx withruntime login`). */
|
|
161
|
+
export class Daytona {
|
|
162
|
+
snapshot;
|
|
163
|
+
volume;
|
|
164
|
+
secret;
|
|
165
|
+
warmPool;
|
|
166
|
+
#client;
|
|
167
|
+
#create;
|
|
168
|
+
constructor(config = {}) {
|
|
169
|
+
this.#client = clientFor(config);
|
|
170
|
+
this.#create = config.withruntime?.create ?? {};
|
|
171
|
+
this.snapshot = new SnapshotService(this.#client);
|
|
172
|
+
this.volume = new VolumeService(this.#client);
|
|
173
|
+
this.secret = unsupportedService("secrets", "Pass credentials as envVars or per command, never in the command text.");
|
|
174
|
+
this.warmPool = unsupportedService("warm pools", "Runtime starts sandboxes from warm templates already; nothing to configure.");
|
|
175
|
+
}
|
|
176
|
+
async [Symbol.asyncDispose]() { }
|
|
177
|
+
/** Creates a sandbox and waits until it runs, with Daytona's defaults: 1
|
|
178
|
+
* vCPU, 1 GiB, 3 GiB disk, pausing after 15 minutes without calls. Funding
|
|
179
|
+
* is left to Runtime: the free trial while the account has trial time, then
|
|
180
|
+
* prepaid credit, exactly as withruntime's own create. */
|
|
181
|
+
async create(params = {}, options = {}) {
|
|
182
|
+
refuseCreate(params);
|
|
183
|
+
const client = params.withruntime?.client ?? this.#client;
|
|
184
|
+
const lifecycle = lifecycleOf(params);
|
|
185
|
+
const resources = { ...DEFAULT_RESOURCES, ...params.resources };
|
|
186
|
+
if (resources.gpu)
|
|
187
|
+
throw new NotSupportedError("GPUs", "Runtime runs sandboxes on CPUs; remove gpu from resources.");
|
|
188
|
+
const source = await this.#source(client, params, options.onSnapshotCreateLogs);
|
|
189
|
+
const volumes = await this.#volumes(client, params.volumes);
|
|
190
|
+
const network = networkRules(params);
|
|
191
|
+
// Daytona keeps the language in this label, so a sandbox found later with
|
|
192
|
+
// get() or list() runs codeRun in the language it was made for.
|
|
193
|
+
const labels = params.language && params.language !== "python"
|
|
194
|
+
? { ...params.labels, [LANGUAGE_LABEL]: params.language }
|
|
195
|
+
: params.labels && Object.keys(params.labels).length
|
|
196
|
+
? params.labels
|
|
197
|
+
: undefined;
|
|
198
|
+
const input = {
|
|
199
|
+
...(source.snapshot
|
|
200
|
+
? {}
|
|
201
|
+
: {
|
|
202
|
+
vcpu: resources.cpu,
|
|
203
|
+
memoryMiB: Math.round(resources.memory * 1024),
|
|
204
|
+
diskMiB: Math.round(resources.disk * 1024),
|
|
205
|
+
}),
|
|
206
|
+
timeoutSeconds: lifecycle.deadline
|
|
207
|
+
? Math.max(60, Math.min(lifecycle.windowSeconds, Math.floor((lifecycle.deadline - Date.now()) / 1000)))
|
|
208
|
+
: lifecycle.windowSeconds,
|
|
209
|
+
onLeaseEnd: lifecycle.ephemeral || lifecycle.deadline ? "stop" : "pause",
|
|
210
|
+
...(params.name ? { name: params.name } : {}),
|
|
211
|
+
...(labels ? { labels } : {}),
|
|
212
|
+
...(network ? { network } : {}),
|
|
213
|
+
...(volumes.length ? { volumes } : {}),
|
|
214
|
+
...source,
|
|
215
|
+
...this.#create,
|
|
216
|
+
...params.withruntime?.create,
|
|
217
|
+
};
|
|
218
|
+
const runtime = await guard("sandbox", () => client.sandboxes.create(input));
|
|
219
|
+
if (lifecycle.autoDeleteInterval > 0)
|
|
220
|
+
await guard("sandbox", () => runtime.setRetention(retentionDays(lifecycle.autoDeleteInterval))).catch(async (error) => {
|
|
221
|
+
await runtime.stop({ wait: false }).catch(() => undefined);
|
|
222
|
+
throw error;
|
|
223
|
+
});
|
|
224
|
+
const env = {
|
|
225
|
+
...params.envVars,
|
|
226
|
+
...(params.outboundProxyUrl
|
|
227
|
+
? { HTTP_PROXY: params.outboundProxyUrl, HTTPS_PROXY: params.outboundProxyUrl }
|
|
228
|
+
: {}),
|
|
229
|
+
};
|
|
230
|
+
return new Sandbox(runtime, client, {
|
|
231
|
+
env,
|
|
232
|
+
language: params.language ?? "python",
|
|
233
|
+
public: params.public ?? false,
|
|
234
|
+
lifecycle,
|
|
235
|
+
...("snapshot" in params && params.snapshot ? { snapshot: params.snapshot } : {}),
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
async #source(client, params, onLogs) {
|
|
239
|
+
if ("image" in params && params.image !== undefined) {
|
|
240
|
+
const image = await guard("other", () => imageFor(client, params.image, onLogs));
|
|
241
|
+
return { image: image.id };
|
|
242
|
+
}
|
|
243
|
+
const name = "snapshot" in params ? params.snapshot : undefined;
|
|
244
|
+
if (name === undefined || STOCK_SNAPSHOT.test(name))
|
|
245
|
+
return {};
|
|
246
|
+
if (UUID.test(name)) {
|
|
247
|
+
try {
|
|
248
|
+
await client.images.get(name);
|
|
249
|
+
return { image: name };
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
if (error.status !== 404)
|
|
253
|
+
throw error;
|
|
254
|
+
}
|
|
255
|
+
return { snapshot: name };
|
|
256
|
+
}
|
|
257
|
+
const image = (await guard("other", () => client.images.list({ name: imageName(name), state: "ready", limit: 1 }))).data[0];
|
|
258
|
+
if (image)
|
|
259
|
+
return { image: image.id };
|
|
260
|
+
const snapshot = (await guard("other", () => client.snapshots.list({ name, state: "ready", limit: 1 }))).data[0];
|
|
261
|
+
if (snapshot)
|
|
262
|
+
return { snapshot: snapshot.id };
|
|
263
|
+
throw new DaytonaNotFoundError(`No Runtime image or snapshot is named "${name}". Daytona snapshots do not move to Runtime; build the same ` +
|
|
264
|
+
`environment as a Runtime image with that name: daytona.snapshot.create({ name: "${name}", image }) with this ` +
|
|
265
|
+
`package, or \`npx withruntime image build --dockerfile Dockerfile --name ${imageName(name)}\`.`, 404);
|
|
266
|
+
}
|
|
267
|
+
async #volumes(client, mounts) {
|
|
268
|
+
const out = [];
|
|
269
|
+
for (const mount of mounts ?? []) {
|
|
270
|
+
if (mount.subpath)
|
|
271
|
+
throw new NotSupportedError("Mounting part of a volume (subpath)", "Mount the whole volume.");
|
|
272
|
+
let id = mount.volumeId;
|
|
273
|
+
if (!UUID.test(id)) {
|
|
274
|
+
const found = (await guard("other", () => client.volumes.list({ name: id, limit: 1 })))
|
|
275
|
+
.data[0];
|
|
276
|
+
if (!found)
|
|
277
|
+
throw notFound(`Volume ${id}`);
|
|
278
|
+
id = found.id;
|
|
279
|
+
}
|
|
280
|
+
out.push({ volumeId: id, path: mount.mountPath });
|
|
281
|
+
}
|
|
282
|
+
return out;
|
|
283
|
+
}
|
|
284
|
+
/** A sandbox by id or name. */
|
|
285
|
+
async get(sandboxIdOrName) {
|
|
286
|
+
const runtime = await guard("sandbox", () => find(this.#client, sandboxIdOrName));
|
|
287
|
+
return this.#adopt(runtime);
|
|
288
|
+
}
|
|
289
|
+
#adopt(runtime) {
|
|
290
|
+
const onLeaseEnd = runtime.info.onLeaseEnd;
|
|
291
|
+
return new Sandbox(runtime, this.#client, {
|
|
292
|
+
env: {},
|
|
293
|
+
language: runtime.info.labels[LANGUAGE_LABEL] ?? "python",
|
|
294
|
+
public: false,
|
|
295
|
+
lifecycle: {
|
|
296
|
+
windowSeconds: runtime.info.timeoutSeconds,
|
|
297
|
+
ephemeral: onLeaseEnd === "stop",
|
|
298
|
+
autoStopInterval: Math.round(runtime.info.timeoutSeconds / 60),
|
|
299
|
+
autoArchiveInterval: 0,
|
|
300
|
+
autoDeleteInterval: -1,
|
|
301
|
+
},
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
/** Live and stopped (paused) sandboxes, oldest first. Await it for the old
|
|
305
|
+
* paginated shape, `{ items, total, page, totalPages }`. */
|
|
306
|
+
list(query = {}) {
|
|
307
|
+
const known = new Set(["limit", "name", "labels", "states"]);
|
|
308
|
+
const other = Object.keys(query).find((key) => query[key] !== undefined && !known.has(key));
|
|
309
|
+
if (other)
|
|
310
|
+
throw new NotSupportedError(`Listing sandboxes by ${other}`, "Filter by name, labels or states, and sort or narrow the result yourself.");
|
|
311
|
+
const states = query.states?.flatMap((state) => state === "started"
|
|
312
|
+
? ["running"]
|
|
313
|
+
: state === "starting"
|
|
314
|
+
? ["starting", "resuming"]
|
|
315
|
+
: state === "stopping"
|
|
316
|
+
? ["pausing"]
|
|
317
|
+
: state === "stopped" || state === "paused"
|
|
318
|
+
? ["paused"]
|
|
319
|
+
: []);
|
|
320
|
+
const client = this.#client;
|
|
321
|
+
const adopt = (runtime) => this.#adopt(runtime);
|
|
322
|
+
const filter = {
|
|
323
|
+
...(query.labels ? { labels: query.labels } : {}),
|
|
324
|
+
...(query.name ? { name: query.name } : {}),
|
|
325
|
+
...(states ? { state: states } : {}),
|
|
326
|
+
...(query.limit ? { limit: Math.min(query.limit, 100) } : {}),
|
|
327
|
+
};
|
|
328
|
+
async function* iterate() {
|
|
329
|
+
const page = await guard("other", () => client.sandboxes.list(filter));
|
|
330
|
+
for await (const runtime of page)
|
|
331
|
+
yield adopt(runtime);
|
|
332
|
+
}
|
|
333
|
+
const iterator = iterate();
|
|
334
|
+
return Object.assign(iterator, {
|
|
335
|
+
then(onFulfilled, onRejected) {
|
|
336
|
+
const all = (async () => {
|
|
337
|
+
const page = await guard("other", () => client.sandboxes.list(filter));
|
|
338
|
+
const items = (await page.toArray(10_000)).map(adopt);
|
|
339
|
+
return { items, total: items.length, page: 1, totalPages: 1 };
|
|
340
|
+
})();
|
|
341
|
+
return all.then(onFulfilled, onRejected);
|
|
342
|
+
},
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
start(sandbox, timeout) {
|
|
346
|
+
return sandbox.start(timeout);
|
|
347
|
+
}
|
|
348
|
+
stop(sandbox) {
|
|
349
|
+
return sandbox.stop();
|
|
350
|
+
}
|
|
351
|
+
delete(sandbox, timeout) {
|
|
352
|
+
return sandbox.delete(timeout);
|
|
353
|
+
}
|
|
354
|
+
/** Daytona's older name for delete. */
|
|
355
|
+
remove(sandbox, timeout) {
|
|
356
|
+
return sandbox.delete(timeout);
|
|
357
|
+
}
|
|
358
|
+
fork(sandbox, params, timeout) {
|
|
359
|
+
return sandbox.fork(params, timeout);
|
|
360
|
+
}
|
|
361
|
+
_experimental_fork(sandbox, params, timeout) {
|
|
362
|
+
return sandbox.fork(params, timeout);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
function refuseCreate(params) {
|
|
366
|
+
const refusals = [
|
|
367
|
+
["spot", "Spot GPU sandboxes (spot)", "Remove it: Runtime runs sandboxes on CPUs."],
|
|
368
|
+
[
|
|
369
|
+
"linkedSandbox",
|
|
370
|
+
"Linked sandboxes (linkedSandbox)",
|
|
371
|
+
"Run both programs in one sandbox, or connect them through a preview address.",
|
|
372
|
+
],
|
|
373
|
+
["secrets", "Daytona secrets", "Pass credentials as envVars, never in the command text."],
|
|
374
|
+
[
|
|
375
|
+
"otelEndpointOverride",
|
|
376
|
+
"Sending sandbox telemetry elsewhere (otelEndpointOverride)",
|
|
377
|
+
"Remove it: Runtime does not export sandbox telemetry.",
|
|
378
|
+
],
|
|
379
|
+
];
|
|
380
|
+
for (const [field, feature, alternative] of refusals)
|
|
381
|
+
if (params[field] !== undefined)
|
|
382
|
+
throw new NotSupportedError(feature, alternative);
|
|
383
|
+
if (params.user !== undefined && params.user !== "daytona")
|
|
384
|
+
throw new NotSupportedError(`Running as the user "${params.user}"`, 'Commands run as the sandbox owner with passwordless sudo: prefix a command with "sudo" to run it as root.');
|
|
385
|
+
if (params.language !== undefined &&
|
|
386
|
+
!["python", "javascript", "typescript"].includes(params.language))
|
|
387
|
+
throw new NotSupportedError(`The language ${params.language}`, "Use python, javascript or typescript; run anything else with process.executeCommand.");
|
|
388
|
+
if (params.autoStopInterval !== undefined &&
|
|
389
|
+
params.autoPauseInterval !== undefined &&
|
|
390
|
+
params.autoStopInterval !== 0 &&
|
|
391
|
+
params.autoPauseInterval !== 0)
|
|
392
|
+
throw new DaytonaError("At most one of autoStopInterval and autoPauseInterval may be non-zero.", 400);
|
|
393
|
+
}
|
|
394
|
+
/** Daytona's lifecycle settings as the lease Runtime keeps. */
|
|
395
|
+
export function lifecycleOf(params) {
|
|
396
|
+
const autoStop = params.autoPauseInterval || (params.autoStopInterval ?? DEFAULT_AUTO_STOP_MINUTES);
|
|
397
|
+
const autoDelete = params.ephemeral ? 0 : (params.autoDeleteInterval ?? -1);
|
|
398
|
+
return {
|
|
399
|
+
windowSeconds: windowSeconds(autoStop),
|
|
400
|
+
...(params.ttlMinutes ? { deadline: Date.now() + params.ttlMinutes * 60_000 } : {}),
|
|
401
|
+
ephemeral: autoDelete === 0,
|
|
402
|
+
autoStopInterval: autoStop,
|
|
403
|
+
autoArchiveInterval: params.autoArchiveInterval ?? 10_080,
|
|
404
|
+
autoDeleteInterval: autoDelete,
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
/** The sandbox with this Runtime id, or the newest live one with this name. */
|
|
408
|
+
async function find(client, idOrName) {
|
|
409
|
+
if (UUID.test(idOrName))
|
|
410
|
+
return client.sandboxes.get(idOrName);
|
|
411
|
+
const all = await (await client.sandboxes.list({ name: idOrName })).toArray(1000);
|
|
412
|
+
const found = all.at(-1);
|
|
413
|
+
if (!found)
|
|
414
|
+
throw notFound(`Sandbox ${idOrName}`);
|
|
415
|
+
return found;
|
|
416
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
export declare const SOURCE_API = "DAYTONA_API";
|
|
2
|
+
export declare const SOURCE_DAEMON = "DAYTONA_DAEMON";
|
|
3
|
+
export declare const SOURCE_PROXY = "DAYTONA_PROXY";
|
|
4
|
+
export declare class DaytonaError extends Error {
|
|
5
|
+
statusCode?: number;
|
|
6
|
+
code?: string;
|
|
7
|
+
readonly source?: string;
|
|
8
|
+
headers?: unknown;
|
|
9
|
+
hint?: string;
|
|
10
|
+
requestId?: string;
|
|
11
|
+
constructor(message: string, statusCode?: number, headers?: unknown, code?: string, source?: string);
|
|
12
|
+
/** Daytona's older name for `code`. */
|
|
13
|
+
get errorCode(): string | undefined;
|
|
14
|
+
}
|
|
15
|
+
export declare class DaytonaBadRequestError extends DaytonaError {
|
|
16
|
+
}
|
|
17
|
+
export declare class DaytonaAuthenticationError extends DaytonaError {
|
|
18
|
+
}
|
|
19
|
+
export declare class DaytonaForbiddenError extends DaytonaError {
|
|
20
|
+
}
|
|
21
|
+
export declare class DaytonaNotFoundError extends DaytonaError {
|
|
22
|
+
}
|
|
23
|
+
export declare class DaytonaTimeoutError extends DaytonaError {
|
|
24
|
+
}
|
|
25
|
+
export declare class DaytonaConflictError extends DaytonaError {
|
|
26
|
+
}
|
|
27
|
+
export declare class DaytonaGoneError extends DaytonaError {
|
|
28
|
+
}
|
|
29
|
+
export declare class DaytonaUnprocessableEntityError extends DaytonaError {
|
|
30
|
+
}
|
|
31
|
+
export declare class DaytonaRateLimitError extends DaytonaError {
|
|
32
|
+
}
|
|
33
|
+
export declare class DaytonaInternalServerError extends DaytonaError {
|
|
34
|
+
}
|
|
35
|
+
export declare class DaytonaBadGatewayError extends DaytonaError {
|
|
36
|
+
}
|
|
37
|
+
export declare class DaytonaServiceUnavailableError extends DaytonaError {
|
|
38
|
+
}
|
|
39
|
+
export declare class DaytonaValidationError extends DaytonaBadRequestError {
|
|
40
|
+
}
|
|
41
|
+
export declare class DaytonaAuthorizationError extends DaytonaForbiddenError {
|
|
42
|
+
}
|
|
43
|
+
export declare class DaytonaInvalidArgumentError extends DaytonaValidationError {
|
|
44
|
+
}
|
|
45
|
+
export declare class DaytonaConnectionError extends DaytonaError {
|
|
46
|
+
}
|
|
47
|
+
export declare class DaytonaConnectionTimeoutError extends DaytonaConnectionError {
|
|
48
|
+
}
|
|
49
|
+
export declare class DaytonaGitAuthFailedError extends DaytonaAuthenticationError {
|
|
50
|
+
}
|
|
51
|
+
export declare class DaytonaGitRepoNotFoundError extends DaytonaNotFoundError {
|
|
52
|
+
}
|
|
53
|
+
export declare class DaytonaGitBranchNotFoundError extends DaytonaNotFoundError {
|
|
54
|
+
}
|
|
55
|
+
export declare class DaytonaGitBranchExistsError extends DaytonaConflictError {
|
|
56
|
+
}
|
|
57
|
+
export declare class DaytonaGitPushRejectedError extends DaytonaConflictError {
|
|
58
|
+
}
|
|
59
|
+
export declare class DaytonaGitDirtyWorktreeError extends DaytonaConflictError {
|
|
60
|
+
}
|
|
61
|
+
export declare class DaytonaGitMergeConflictError extends DaytonaConflictError {
|
|
62
|
+
}
|
|
63
|
+
export declare class DaytonaGitTransportFailedError extends DaytonaBadGatewayError {
|
|
64
|
+
}
|
|
65
|
+
export declare class DaytonaGitRemoteRejectedError extends DaytonaUnprocessableEntityError {
|
|
66
|
+
}
|
|
67
|
+
export declare class DaytonaFileNotFoundError extends DaytonaNotFoundError {
|
|
68
|
+
}
|
|
69
|
+
export declare class DaytonaFileAccessDeniedError extends DaytonaForbiddenError {
|
|
70
|
+
}
|
|
71
|
+
export declare class DaytonaInvalidFilePathError extends DaytonaBadRequestError {
|
|
72
|
+
}
|
|
73
|
+
export declare class DaytonaFileReadFailedError extends DaytonaInternalServerError {
|
|
74
|
+
}
|
|
75
|
+
export declare class DaytonaLspServerNotInitializedError extends DaytonaBadRequestError {
|
|
76
|
+
}
|
|
77
|
+
export declare class DaytonaProcessExecutionTimeoutError extends DaytonaTimeoutError {
|
|
78
|
+
}
|
|
79
|
+
export declare class DaytonaProcessNotFoundError extends DaytonaNotFoundError {
|
|
80
|
+
}
|
|
81
|
+
export declare class DaytonaSessionEndedError extends DaytonaGoneError {
|
|
82
|
+
}
|
|
83
|
+
export declare class DaytonaCommandAlreadyCompletedError extends DaytonaGoneError {
|
|
84
|
+
}
|
|
85
|
+
export declare class DaytonaA11yUnavailableError extends DaytonaServiceUnavailableError {
|
|
86
|
+
}
|
|
87
|
+
export declare class DaytonaRecordingStillActiveError extends DaytonaConflictError {
|
|
88
|
+
}
|
|
89
|
+
export declare class DaytonaRecordingFfmpegNotFoundError extends DaytonaServiceUnavailableError {
|
|
90
|
+
}
|
|
91
|
+
/** A call that Daytona supports and Runtime does not, or not in the same
|
|
92
|
+
* way. Thrown before anything is done, never after doing something
|
|
93
|
+
* different. `feature` names what was asked for; `alternative` says what to
|
|
94
|
+
* use on Runtime instead. */
|
|
95
|
+
export declare class NotSupportedError extends DaytonaError {
|
|
96
|
+
readonly feature: string;
|
|
97
|
+
readonly alternative: string;
|
|
98
|
+
constructor(feature: string, alternative: string, message?: string);
|
|
99
|
+
}
|
|
100
|
+
/** Which object a call was about, to name a 404 the way Daytona would. */
|
|
101
|
+
export type Subject = "sandbox" | "file" | "process" | "other";
|
|
102
|
+
/** Turns a Runtime SDK error into the Daytona error a caller written for
|
|
103
|
+
* Daytona expects. Anything that is not a Runtime error passes through. */
|
|
104
|
+
export declare function translate(error: unknown, subject?: Subject): unknown;
|
|
105
|
+
/** Runs `work`, turning any Runtime error into its Daytona counterpart. */
|
|
106
|
+
export declare function guard<T>(subject: Subject, work: () => Promise<T>): Promise<T>;
|