withruntime 0.4.0 → 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.
Files changed (87) hide show
  1. package/DAYTONA.md +129 -0
  2. package/E2B.md +2 -2
  3. package/README.md +47 -9
  4. package/VERCEL.md +127 -0
  5. package/dist/ai/index.d.ts +33 -0
  6. package/dist/ai/index.js +38 -0
  7. package/dist/claude-agent-sdk/index.d.ts +7 -0
  8. package/dist/claude-agent-sdk/index.js +65 -0
  9. package/dist/cli.d.ts +6 -0
  10. package/dist/cli.js +939 -102
  11. package/dist/client.d.ts +25 -2
  12. package/dist/client.js +14 -1
  13. package/dist/credentials.d.ts +10 -0
  14. package/dist/credentials.js +56 -1
  15. package/dist/daytona/client.d.ts +44 -0
  16. package/dist/daytona/client.js +40 -0
  17. package/dist/daytona/context.d.ts +26 -0
  18. package/dist/daytona/context.js +22 -0
  19. package/dist/daytona/daytona.d.ts +185 -0
  20. package/dist/daytona/daytona.js +416 -0
  21. package/dist/daytona/errors.d.ts +106 -0
  22. package/dist/daytona/errors.js +182 -0
  23. package/dist/daytona/filesystem.d.ts +84 -0
  24. package/dist/daytona/filesystem.js +206 -0
  25. package/dist/daytona/git.d.ts +33 -0
  26. package/dist/daytona/git.js +128 -0
  27. package/dist/daytona/image.d.ts +45 -0
  28. package/dist/daytona/image.js +140 -0
  29. package/dist/daytona/index.d.ts +50 -0
  30. package/dist/daytona/index.js +50 -0
  31. package/dist/daytona/process.d.ts +86 -0
  32. package/dist/daytona/process.js +339 -0
  33. package/dist/daytona/sandbox.d.ts +196 -0
  34. package/dist/daytona/sandbox.js +448 -0
  35. package/dist/e2b/sandbox.d.ts +22 -2
  36. package/dist/e2b/sandbox.js +39 -7
  37. package/dist/errors.d.ts +10 -4
  38. package/dist/errors.js +26 -6
  39. package/dist/image-context.d.ts +39 -0
  40. package/dist/image-context.js +176 -0
  41. package/dist/index.d.ts +19 -2
  42. package/dist/index.js +17 -2
  43. package/dist/keys.d.ts +43 -0
  44. package/dist/keys.js +196 -0
  45. package/dist/login.js +14 -2
  46. package/dist/openai-agents/index.d.ts +132 -0
  47. package/dist/openai-agents/index.js +791 -0
  48. package/dist/products/audit.d.ts +48 -0
  49. package/dist/products/audit.js +10 -0
  50. package/dist/products/images.d.ts +113 -7
  51. package/dist/products/images.js +186 -27
  52. package/dist/products/index.d.ts +11 -0
  53. package/dist/products/index.js +17 -1
  54. package/dist/products/observability.d.ts +186 -0
  55. package/dist/products/observability.js +117 -0
  56. package/dist/products/secrets.d.ts +40 -0
  57. package/dist/products/secrets.js +24 -0
  58. package/dist/products/switching.d.ts +89 -0
  59. package/dist/products/switching.js +25 -0
  60. package/dist/sandbox.d.ts +26 -1
  61. package/dist/sandbox.js +101 -1
  62. package/dist/ssh.d.ts +21 -0
  63. package/dist/ssh.js +312 -0
  64. package/dist/tar.d.ts +1 -0
  65. package/dist/tar.js +4 -4
  66. package/dist/tools/index.d.ts +62 -0
  67. package/dist/tools/index.js +180 -0
  68. package/dist/transport.d.ts +12 -2
  69. package/dist/transport.js +31 -4
  70. package/dist/tunnel.d.ts +67 -0
  71. package/dist/tunnel.js +311 -0
  72. package/dist/types.d.ts +57 -1
  73. package/dist/vercel/client.d.ts +40 -0
  74. package/dist/vercel/client.js +39 -0
  75. package/dist/vercel/command.d.ts +70 -0
  76. package/dist/vercel/command.js +148 -0
  77. package/dist/vercel/errors.d.ts +53 -0
  78. package/dist/vercel/errors.js +113 -0
  79. package/dist/vercel/filesystem.d.ts +150 -0
  80. package/dist/vercel/filesystem.js +248 -0
  81. package/dist/vercel/index.d.ts +30 -0
  82. package/dist/vercel/index.js +38 -0
  83. package/dist/vercel/sandbox.d.ts +317 -0
  84. package/dist/vercel/sandbox.js +726 -0
  85. package/dist/vercel/snapshot.d.ts +93 -0
  86. package/dist/vercel/snapshot.js +123 -0
  87. package/package.json +56 -4
@@ -0,0 +1,196 @@
1
+ import type { Runtime } from "../client.js";
2
+ import type { RuntimeSandbox } from "./client.js";
3
+ import { DaytonaNotFoundError } from "./errors.js";
4
+ import { FileSystem } from "./filesystem.js";
5
+ import { Git } from "./git.js";
6
+ import { Process } from "./process.js";
7
+ /** How the sandbox's lease follows Daytona's lifecycle settings. */
8
+ export interface Lifecycle {
9
+ /** Seconds without a call from this client before the sandbox pauses
10
+ * (Daytona's autoStopInterval), 60 to 3600. */
11
+ windowSeconds: number;
12
+ /** Epoch ms past which the lease is never extended (ttlMinutes). */
13
+ deadline?: number;
14
+ /** stop() ends the sandbox instead of pausing it (ephemeral, or
15
+ * autoDeleteInterval 0). */
16
+ ephemeral: boolean;
17
+ autoStopInterval: number;
18
+ autoArchiveInterval: number;
19
+ autoDeleteInterval: number;
20
+ }
21
+ export interface SandboxOptions {
22
+ env: Record<string, string>;
23
+ language: string;
24
+ public: boolean;
25
+ lifecycle: Lifecycle;
26
+ snapshot?: string;
27
+ }
28
+ export type SandboxState = "started" | "starting" | "stopping" | "stopped" | "paused" | "destroying" | "destroyed";
29
+ export interface PortPreviewUrl {
30
+ sandboxId: string;
31
+ port: number;
32
+ url: string;
33
+ /** Private previews: send it as the `x-runtime-preview-token` header
34
+ * (Daytona's header is x-daytona-preview-token). "" when public. */
35
+ token: string;
36
+ }
37
+ export interface InterpreterContext {
38
+ id: string;
39
+ cwd: string;
40
+ language: string;
41
+ active: boolean;
42
+ }
43
+ export interface OutputMessage {
44
+ output: string;
45
+ }
46
+ export interface ExecutionError {
47
+ name: string;
48
+ value: string;
49
+ traceback?: string;
50
+ }
51
+ export interface ExecutionResult {
52
+ stdout: string;
53
+ stderr: string;
54
+ error?: ExecutionError;
55
+ }
56
+ /** `sandbox.codeInterpreter`: Daytona's stateful Python over Runtime's
57
+ * interpreter. */
58
+ export declare class CodeInterpreter {
59
+ #private;
60
+ constructor(sandbox: () => Promise<RuntimeSandbox>, env: () => Record<string, string>);
61
+ runCode(code: string, options?: {
62
+ context?: InterpreterContext;
63
+ envs?: Record<string, string>;
64
+ timeout?: number;
65
+ onStdout?: (message: OutputMessage) => unknown;
66
+ onStderr?: (message: OutputMessage) => unknown;
67
+ onError?: (error: ExecutionError) => unknown;
68
+ }): Promise<ExecutionResult>;
69
+ createContext(cwd?: string): Promise<InterpreterContext>;
70
+ listContexts(): Promise<InterpreterContext[]>;
71
+ deleteContext(context: InterpreterContext): Promise<void>;
72
+ }
73
+ /** A sandbox, with Daytona's fields and methods. `sandbox.withruntime` is the
74
+ * Runtime sandbox underneath, for anything Daytona has no name for. */
75
+ export declare class Sandbox {
76
+ #private;
77
+ readonly fs: FileSystem;
78
+ readonly process: Process;
79
+ readonly git: Git;
80
+ readonly codeInterpreter: CodeInterpreter;
81
+ env: Record<string, string>;
82
+ readonly public: boolean;
83
+ readonly snapshot: string | undefined;
84
+ /** Use daytona.create or daytona.get. */
85
+ constructor(runtime: RuntimeSandbox, client: Runtime, options: SandboxOptions);
86
+ /** The Runtime sandbox underneath: previews, network, snapshots, desktop,
87
+ * terminal and the rest of Runtime's SDK. */
88
+ get withruntime(): RuntimeSandbox;
89
+ get id(): string;
90
+ get name(): string;
91
+ get organizationId(): string;
92
+ /** Daytona's user name, so `/home/${sandbox.user}` leads to the working
93
+ * directory. Commands run as Runtime's sandbox owner, with passwordless sudo. */
94
+ get user(): string;
95
+ get labels(): Record<string, string>;
96
+ get target(): string;
97
+ get cpu(): number;
98
+ get gpu(): number;
99
+ /** GiB. */
100
+ get memory(): number;
101
+ /** GiB. */
102
+ get disk(): number;
103
+ get state(): SandboxState;
104
+ get errorReason(): string | undefined;
105
+ get recoverable(): boolean;
106
+ get autoStopInterval(): number;
107
+ get autoArchiveInterval(): number;
108
+ get autoDeleteInterval(): number;
109
+ get createdAt(): string;
110
+ get updatedAt(): string;
111
+ /** Wakes a stopped (paused) sandbox, keeping its files and memory. */
112
+ start(_timeout?: number): Promise<void>;
113
+ /** Stops the sandbox: Runtime pauses it, keeping its files and memory, so
114
+ * start() carries on. An ephemeral sandbox ends instead. */
115
+ stop(_timeout?: number, _force?: boolean): Promise<void>;
116
+ /** Pauses the sandbox with its memory. */
117
+ pause(_timeout?: number): Promise<void>;
118
+ /** Runtime has no archive tier: a stopped sandbox stays paused, kept for
119
+ * its retention (30 days paid, 7 on the trial, or autoDeleteInterval). */
120
+ archive(): Promise<void>;
121
+ /** Ends the sandbox for good. */
122
+ delete(_timeout?: number): Promise<void>;
123
+ waitUntilStarted(timeout?: number): Promise<void>;
124
+ waitUntilStopped(timeout?: number): Promise<void>;
125
+ refreshData(): Promise<void>;
126
+ /** Counts as activity: moves the lease a full autoStop window on. */
127
+ refreshActivity(): Promise<void>;
128
+ /** The sandbox pauses after `interval` minutes without a call from this
129
+ * client (1 to 60; 0 is 60). */
130
+ setAutostopInterval(interval: number): Promise<void>;
131
+ setAutoPauseInterval(interval: number): Promise<void>;
132
+ /** Runtime has no archive tier; recorded only. */
133
+ setAutoArchiveInterval(interval: number): Promise<void>;
134
+ /** 0: stop() ends the sandbox. More: a stopped sandbox is kept that many
135
+ * minutes, rounded up to whole days (Runtime's retention). */
136
+ setAutoDeleteInterval(interval: number): Promise<void>;
137
+ setTtl(ttlMinutes: number): Promise<void>;
138
+ /** Changes the environment later commands get from this object. */
139
+ updateEnv(env: Record<string, string>, options?: {
140
+ unset?: string[];
141
+ }): Promise<void>;
142
+ updateNetworkSettings(settings: {
143
+ networkBlockAll?: boolean;
144
+ networkAllowList?: string;
145
+ domainAllowList?: string;
146
+ }): Promise<void>;
147
+ /** A preview address for `port`: public when the sandbox was created with
148
+ * `public: true`, else private with a token. */
149
+ getPreviewLink(port: number): Promise<PortPreviewUrl>;
150
+ getUserHomeDir(): Promise<string>;
151
+ getUserRootDir(): Promise<string>;
152
+ getWorkDir(): Promise<string>;
153
+ /** A copy of this sandbox with its files, memory and running processes. */
154
+ fork(params?: {
155
+ name?: string;
156
+ }, _timeout?: number): Promise<Sandbox>;
157
+ _experimental_fork(params?: {
158
+ name?: string;
159
+ }, timeout?: number): Promise<Sandbox>;
160
+ /** Keeps this sandbox (files, memory, processes) as a Runtime snapshot
161
+ * named `name`; `daytona.create({ snapshot: name })` starts from it. */
162
+ createSnapshot(name: string, _timeout?: number): Promise<void>;
163
+ _experimental_createSnapshot(name: string, timeout?: number): Promise<void>;
164
+ get computerUse(): never;
165
+ setLabels(): Promise<never>;
166
+ recover(): Promise<never>;
167
+ resize(): Promise<never>;
168
+ waitForResizeComplete(): Promise<never>;
169
+ getMetrics(): Promise<never>;
170
+ getMetricsLatest(): Promise<never>;
171
+ createLspServer(): never;
172
+ updateSecrets(): Promise<never>;
173
+ getSignedPreviewUrl(): Promise<never>;
174
+ expireSignedPreviewUrl(): Promise<never>;
175
+ rotateSigningKey(): Promise<never>;
176
+ uploadUrl(): Promise<never>;
177
+ downloadUrl(): Promise<never>;
178
+ createSshAccess(): Promise<never>;
179
+ revokeSshAccess(): Promise<never>;
180
+ validateSshAccess(): Promise<never>;
181
+ }
182
+ /** Daytona's autoStopInterval (minutes; 0 is off) as the lease window. */
183
+ export declare function windowSeconds(autoStopMinutes: number): number;
184
+ /** Minutes as Runtime's retention: whole days, 1 to 365. */
185
+ export declare function retentionDays(minutes: number): number;
186
+ /** Daytona's network settings as Runtime's rules, or undefined for the
187
+ * default (the public web). */
188
+ export declare function networkRules(settings: {
189
+ networkBlockAll?: boolean;
190
+ networkAllowList?: string;
191
+ domainAllowList?: string;
192
+ }): {
193
+ internet: boolean;
194
+ allow?: string[];
195
+ } | undefined;
196
+ export declare function notFound(what: string): DaytonaNotFoundError;
@@ -0,0 +1,448 @@
1
+ import { RuntimeError } from "../errors.js";
2
+ import { HOME, HOME_LINK } from "./context.js";
3
+ import { DaytonaError, DaytonaNotFoundError, guard, NotSupportedError } from "./errors.js";
4
+ import { FileSystem } from "./filesystem.js";
5
+ import { Git } from "./git.js";
6
+ import { Process } from "./process.js";
7
+ function refusal(feature, alternative) {
8
+ return Promise.reject(new NotSupportedError(feature, alternative));
9
+ }
10
+ /** `sandbox.codeInterpreter`: Daytona's stateful Python over Runtime's
11
+ * interpreter. */
12
+ export class CodeInterpreter {
13
+ #sandbox;
14
+ #env;
15
+ #envContext;
16
+ constructor(sandbox, env) {
17
+ this.#sandbox = sandbox;
18
+ this.#env = env;
19
+ }
20
+ /** The sandbox's envVars reach code through one context made for them. */
21
+ async #defaultContext() {
22
+ const env = this.#env();
23
+ if (!Object.keys(env).length)
24
+ return "python";
25
+ this.#envContext ??= (async () => {
26
+ const runtime = await this.#sandbox();
27
+ const made = await guard("sandbox", () => runtime.interpreter.contexts.create({ language: "python", cwd: HOME, env }));
28
+ return made.id;
29
+ })();
30
+ return this.#envContext;
31
+ }
32
+ async runCode(code, options = {}) {
33
+ if (options.envs && Object.keys(options.envs).length)
34
+ throw new NotSupportedError("Per-run environment variables (runCode envs)", "Pass envVars when creating the sandbox, or set os.environ in the code.");
35
+ const runtime = await this.#sandbox();
36
+ const context = options.context?.id ?? (await this.#defaultContext());
37
+ const execution = await guard("sandbox", () => runtime.interpreter.run(code, {
38
+ language: "python",
39
+ context,
40
+ ...(options.timeout ? { timeoutMs: options.timeout * 1000 } : {}),
41
+ ...(options.onStdout
42
+ ? { onStdout: (output) => void options.onStdout({ output }) }
43
+ : {}),
44
+ ...(options.onStderr
45
+ ? { onStderr: (output) => void options.onStderr({ output }) }
46
+ : {}),
47
+ ...(options.onError
48
+ ? { onError: (error) => void options.onError(error) }
49
+ : {}),
50
+ }));
51
+ return {
52
+ stdout: execution.stdout,
53
+ stderr: execution.stderr,
54
+ ...(execution.error ? { error: execution.error } : {}),
55
+ };
56
+ }
57
+ async createContext(cwd) {
58
+ const runtime = await this.#sandbox();
59
+ const env = this.#env();
60
+ const made = await guard("sandbox", () => runtime.interpreter.contexts.create({
61
+ language: "python",
62
+ cwd: cwd ?? HOME,
63
+ ...(Object.keys(env).length ? { env } : {}),
64
+ }));
65
+ return { id: made.id, cwd: made.cwd, language: made.language, active: true };
66
+ }
67
+ async listContexts() {
68
+ const runtime = await this.#sandbox();
69
+ const all = await guard("sandbox", () => runtime.interpreter.contexts.list());
70
+ return all.map((one) => ({ id: one.id, cwd: one.cwd, language: one.language, active: true }));
71
+ }
72
+ async deleteContext(context) {
73
+ const runtime = await this.#sandbox();
74
+ await guard("sandbox", () => runtime.interpreter.contexts.remove(context.id));
75
+ }
76
+ }
77
+ /** A sandbox, with Daytona's fields and methods. `sandbox.withruntime` is the
78
+ * Runtime sandbox underneath, for anything Daytona has no name for. */
79
+ export class Sandbox {
80
+ fs;
81
+ process;
82
+ git;
83
+ codeInterpreter;
84
+ env;
85
+ public;
86
+ snapshot;
87
+ #rt;
88
+ #client;
89
+ #options;
90
+ #home;
91
+ #pausedByPause = false;
92
+ /** Use daytona.create or daytona.get. */
93
+ constructor(runtime, client, options) {
94
+ this.#rt = runtime;
95
+ this.#client = client;
96
+ this.#options = options;
97
+ this.env = { ...options.env };
98
+ this.public = options.public;
99
+ this.snapshot = options.snapshot;
100
+ const ctx = {
101
+ live: () => this.#live(),
102
+ language: options.language,
103
+ ensureHome: (text) => this.#ensureHome(text),
104
+ };
105
+ // A getter, so the modules see the environment updateEnv sets.
106
+ Object.defineProperty(ctx, "env", { get: () => this.env });
107
+ this.fs = new FileSystem(ctx);
108
+ this.process = new Process(ctx);
109
+ this.git = new Git(ctx);
110
+ this.codeInterpreter = new CodeInterpreter(() => this.#live(), () => this.env);
111
+ }
112
+ /** The Runtime sandbox underneath: previews, network, snapshots, desktop,
113
+ * terminal and the rest of Runtime's SDK. */
114
+ get withruntime() {
115
+ return this.#rt;
116
+ }
117
+ get id() {
118
+ return this.#rt.id;
119
+ }
120
+ get name() {
121
+ return this.#rt.info.name ?? this.#rt.id;
122
+ }
123
+ get organizationId() {
124
+ return "";
125
+ }
126
+ /** Daytona's user name, so `/home/${sandbox.user}` leads to the working
127
+ * directory. Commands run as Runtime's sandbox owner, with passwordless sudo. */
128
+ get user() {
129
+ return "daytona";
130
+ }
131
+ get labels() {
132
+ return { ...this.#rt.info.labels };
133
+ }
134
+ get target() {
135
+ return "us";
136
+ }
137
+ get cpu() {
138
+ return this.#rt.info.vcpu;
139
+ }
140
+ get gpu() {
141
+ return 0;
142
+ }
143
+ /** GiB. */
144
+ get memory() {
145
+ return this.#rt.info.memoryMiB / 1024;
146
+ }
147
+ /** GiB. */
148
+ get disk() {
149
+ return this.#rt.info.diskMiB / 1024;
150
+ }
151
+ get state() {
152
+ switch (this.#rt.state) {
153
+ case "running":
154
+ return "started";
155
+ case "starting":
156
+ case "resuming":
157
+ return "starting";
158
+ case "pausing":
159
+ return "stopping";
160
+ case "paused":
161
+ return this.#pausedByPause ? "paused" : "stopped";
162
+ case "stopping":
163
+ return "destroying";
164
+ default:
165
+ return "destroyed";
166
+ }
167
+ }
168
+ get errorReason() {
169
+ return this.#rt.info.stopReason ?? undefined;
170
+ }
171
+ get recoverable() {
172
+ return false;
173
+ }
174
+ get autoStopInterval() {
175
+ return this.#options.lifecycle.autoStopInterval;
176
+ }
177
+ get autoArchiveInterval() {
178
+ return this.#options.lifecycle.autoArchiveInterval;
179
+ }
180
+ get autoDeleteInterval() {
181
+ return this.#options.lifecycle.autoDeleteInterval;
182
+ }
183
+ get createdAt() {
184
+ return this.#rt.info.createdAt;
185
+ }
186
+ get updatedAt() {
187
+ return this.#rt.info.pausedAt ?? this.#rt.info.readyAt ?? this.#rt.info.createdAt;
188
+ }
189
+ /** The sandbox, its lease moved on when less than half of the autoStop
190
+ * window is left: every call through this object counts as activity, as
191
+ * Daytona's API calls do. */
192
+ async #live(force = false) {
193
+ const lifecycle = this.#options.lifecycle;
194
+ if (this.#rt.state !== "running")
195
+ return this.#rt;
196
+ const left = Date.parse(this.#rt.info.expiresAt) - Date.now();
197
+ if (!force && left > lifecycle.windowSeconds * 500)
198
+ return this.#rt;
199
+ let seconds = Math.ceil(lifecycle.windowSeconds - left / 1000);
200
+ if (lifecycle.deadline !== undefined)
201
+ seconds = Math.min(seconds, Math.floor((lifecycle.deadline - Date.now() - left) / 1000));
202
+ if (seconds < 1)
203
+ return this.#rt;
204
+ try {
205
+ await this.#rt.extend(seconds);
206
+ }
207
+ catch (error) {
208
+ // The lease may have ended since this object last looked; the call
209
+ // itself then says what state the sandbox is in.
210
+ if (!(error instanceof RuntimeError && error.status === 409))
211
+ throw error;
212
+ await this.#rt.refresh().catch(() => undefined);
213
+ }
214
+ return this.#rt;
215
+ }
216
+ #ensureHome(text) {
217
+ if (this.#home || !text?.includes("/home/daytona"))
218
+ return this.#home ?? Promise.resolve();
219
+ this.#home = (async () => {
220
+ const runtime = await this.#live();
221
+ await guard("sandbox", () => runtime.exec(HOME_LINK)).catch(() => undefined);
222
+ })();
223
+ return this.#home;
224
+ }
225
+ // ---- lifecycle ----------------------------------------------------------
226
+ /** Wakes a stopped (paused) sandbox, keeping its files and memory. */
227
+ async start(_timeout) {
228
+ await guard("sandbox", () => this.#rt.refresh());
229
+ const state = this.#rt.state;
230
+ if (state === "stopped" || state === "stopping")
231
+ throw new DaytonaError(`Sandbox ${this.id} was deleted and cannot start.`, 410);
232
+ if (state === "paused" || state === "pausing")
233
+ await guard("sandbox", () => this.#rt.wake({ timeoutSeconds: this.#options.lifecycle.windowSeconds }));
234
+ this.#pausedByPause = false;
235
+ }
236
+ /** Stops the sandbox: Runtime pauses it, keeping its files and memory, so
237
+ * start() carries on. An ephemeral sandbox ends instead. */
238
+ async stop(_timeout, _force) {
239
+ await guard("sandbox", () => this.#rt.refresh());
240
+ const state = this.#rt.state;
241
+ if (state === "stopped" || state === "stopping")
242
+ return;
243
+ if (this.#options.lifecycle.ephemeral) {
244
+ await guard("sandbox", () => this.#rt.stop());
245
+ return;
246
+ }
247
+ if (state !== "paused")
248
+ await guard("sandbox", () => this.#rt.pause());
249
+ this.#pausedByPause = false;
250
+ }
251
+ /** Pauses the sandbox with its memory. */
252
+ async pause(_timeout) {
253
+ await guard("sandbox", () => this.#rt.refresh());
254
+ if (this.#rt.state === "running")
255
+ await guard("sandbox", () => this.#rt.pause());
256
+ this.#pausedByPause = true;
257
+ }
258
+ /** Runtime has no archive tier: a stopped sandbox stays paused, kept for
259
+ * its retention (30 days paid, 7 on the trial, or autoDeleteInterval). */
260
+ async archive() {
261
+ await this.stop();
262
+ }
263
+ /** Ends the sandbox for good. */
264
+ async delete(_timeout) {
265
+ await guard("sandbox", () => this.#rt.refresh());
266
+ if (this.#rt.state !== "stopped")
267
+ await guard("sandbox", () => this.#rt.stop({ wait: false }));
268
+ }
269
+ async waitUntilStarted(timeout = 60) {
270
+ await guard("sandbox", () => this.#rt.waitFor("running", { timeoutSeconds: timeout || 60 }));
271
+ if (this.#rt.state !== "running")
272
+ throw new DaytonaError(`Sandbox ${this.id} is ${this.state}, not started.`);
273
+ }
274
+ async waitUntilStopped(timeout = 60) {
275
+ await guard("sandbox", () => this.#rt.waitFor("paused", { timeoutSeconds: timeout || 60 }));
276
+ }
277
+ async refreshData() {
278
+ await guard("sandbox", () => this.#rt.refresh());
279
+ }
280
+ /** Counts as activity: moves the lease a full autoStop window on. */
281
+ async refreshActivity() {
282
+ await guard("sandbox", () => this.#live(true));
283
+ }
284
+ /** The sandbox pauses after `interval` minutes without a call from this
285
+ * client (1 to 60; 0 is 60). */
286
+ async setAutostopInterval(interval) {
287
+ const lifecycle = this.#options.lifecycle;
288
+ lifecycle.autoStopInterval = interval;
289
+ lifecycle.windowSeconds = windowSeconds(interval);
290
+ await guard("sandbox", () => this.#live());
291
+ }
292
+ setAutoPauseInterval(interval) {
293
+ return this.setAutostopInterval(interval);
294
+ }
295
+ /** Runtime has no archive tier; recorded only. */
296
+ async setAutoArchiveInterval(interval) {
297
+ this.#options.lifecycle.autoArchiveInterval = interval;
298
+ }
299
+ /** 0: stop() ends the sandbox. More: a stopped sandbox is kept that many
300
+ * minutes, rounded up to whole days (Runtime's retention). */
301
+ async setAutoDeleteInterval(interval) {
302
+ const lifecycle = this.#options.lifecycle;
303
+ lifecycle.autoDeleteInterval = interval;
304
+ lifecycle.ephemeral = interval === 0;
305
+ if (interval > 0)
306
+ await guard("sandbox", () => this.#rt.setRetention(retentionDays(interval)));
307
+ }
308
+ async setTtl(ttlMinutes) {
309
+ if (ttlMinutes === 0) {
310
+ delete this.#options.lifecycle.deadline;
311
+ return;
312
+ }
313
+ const deadline = Date.parse(this.#rt.info.createdAt) + ttlMinutes * 60_000;
314
+ if (Date.parse(this.#rt.info.expiresAt) > deadline)
315
+ throw new NotSupportedError("A time to live shorter than the current lease", "Runtime leases only move later; call stop() or delete() when the work is done.");
316
+ this.#options.lifecycle.deadline = deadline;
317
+ }
318
+ // ---- settings -----------------------------------------------------------
319
+ /** Changes the environment later commands get from this object. */
320
+ async updateEnv(env, options = {}) {
321
+ this.env = { ...this.env, ...env };
322
+ for (const name of options.unset ?? [])
323
+ delete this.env[name];
324
+ }
325
+ async updateNetworkSettings(settings) {
326
+ const rules = networkRules(settings);
327
+ const runtime = await this.#live();
328
+ await guard("sandbox", () => runtime.network.set(rules ?? { internet: true }));
329
+ }
330
+ /** A preview address for `port`: public when the sandbox was created with
331
+ * `public: true`, else private with a token. */
332
+ async getPreviewLink(port) {
333
+ const runtime = await this.#live();
334
+ const preview = await guard("sandbox", () => runtime.previews.create(port, { visibility: this.public ? "public" : "private" }));
335
+ return {
336
+ sandboxId: this.id,
337
+ port,
338
+ url: preview.url.replace(/\/$/, ""),
339
+ token: preview.token ?? "",
340
+ };
341
+ }
342
+ getUserHomeDir() {
343
+ return Promise.resolve(HOME);
344
+ }
345
+ getUserRootDir() {
346
+ return Promise.resolve(HOME);
347
+ }
348
+ getWorkDir() {
349
+ return Promise.resolve(HOME);
350
+ }
351
+ // ---- forks and snapshots --------------------------------------------------
352
+ /** A copy of this sandbox with its files, memory and running processes. */
353
+ async fork(params = {}, _timeout) {
354
+ const copy = await guard("sandbox", () => this.#rt.fork({ ...(params.name ? { name: params.name } : {}) }));
355
+ return new Sandbox(copy, this.#client, {
356
+ ...this.#options,
357
+ env: this.env,
358
+ lifecycle: { ...this.#options.lifecycle },
359
+ });
360
+ }
361
+ _experimental_fork(params = {}, timeout) {
362
+ return this.fork(params, timeout);
363
+ }
364
+ /** Keeps this sandbox (files, memory, processes) as a Runtime snapshot
365
+ * named `name`; `daytona.create({ snapshot: name })` starts from it. */
366
+ async createSnapshot(name, _timeout) {
367
+ await guard("sandbox", () => this.#rt.snapshot({ name }));
368
+ }
369
+ _experimental_createSnapshot(name, timeout) {
370
+ return this.createSnapshot(name, timeout);
371
+ }
372
+ // ---- what Runtime does differently -----------------------------------------
373
+ get computerUse() {
374
+ throw new NotSupportedError("Daytona's computer use", "Use Runtime's desktop: `await sandbox.withruntime.desktop.start()` (see the desktop guide).");
375
+ }
376
+ setLabels() {
377
+ return refusal("Changing a sandbox's labels", "Runtime sets labels once, at create: pass labels to daytona.create.");
378
+ }
379
+ recover() {
380
+ return refusal("Recovering a failed sandbox", "Create a new sandbox, or start one from a snapshot.");
381
+ }
382
+ resize() {
383
+ return refusal("Resizing a sandbox", "Create a new one with the resources you need; fork() or createSnapshot() carries the state.");
384
+ }
385
+ waitForResizeComplete() {
386
+ return this.resize();
387
+ }
388
+ getMetrics() {
389
+ return refusal("Sandbox metrics", "Runtime reports CPU, memory and charges per sandbox in `npx withruntime usage` and runtime.usage().");
390
+ }
391
+ getMetricsLatest() {
392
+ return this.getMetrics();
393
+ }
394
+ createLspServer() {
395
+ throw new NotSupportedError("Daytona's language servers", "Start one in a session: process.executeSessionCommand(id, { command: 'pyright-langserver --stdio', runAsync: true }).");
396
+ }
397
+ updateSecrets() {
398
+ return refusal("Daytona secrets", "Pass credentials as envVars or per command, never in the command text.");
399
+ }
400
+ getSignedPreviewUrl() {
401
+ return refusal("Signed preview URLs", "Use getPreviewLink(port) and send its token as the x-runtime-preview-token header, or create the sandbox with public: true.");
402
+ }
403
+ expireSignedPreviewUrl() {
404
+ return this.getSignedPreviewUrl();
405
+ }
406
+ rotateSigningKey() {
407
+ return refusal("Rotating the preview signing key", "Use `await sandbox.withruntime.previews.rotate(port)`, which refuses every token issued for that port.");
408
+ }
409
+ uploadUrl() {
410
+ return refusal("Signed upload URLs", "Use sandbox.fs.uploadFile(data, path).");
411
+ }
412
+ downloadUrl() {
413
+ return refusal("Signed download URLs", "Use sandbox.fs.downloadFile(path).");
414
+ }
415
+ createSshAccess() {
416
+ return refusal("SSH access", "Use `npx withruntime sandbox shell <id>` or sandbox.withruntime.terminal().");
417
+ }
418
+ revokeSshAccess() {
419
+ return this.createSshAccess();
420
+ }
421
+ validateSshAccess() {
422
+ return this.createSshAccess();
423
+ }
424
+ }
425
+ /** Daytona's autoStopInterval (minutes; 0 is off) as the lease window. */
426
+ export function windowSeconds(autoStopMinutes) {
427
+ if (autoStopMinutes <= 0)
428
+ return 3600;
429
+ return Math.min(3600, Math.max(60, Math.round(autoStopMinutes * 60)));
430
+ }
431
+ /** Minutes as Runtime's retention: whole days, 1 to 365. */
432
+ export function retentionDays(minutes) {
433
+ return Math.min(365, Math.max(1, Math.ceil(minutes / 1440)));
434
+ }
435
+ /** Daytona's network settings as Runtime's rules, or undefined for the
436
+ * default (the public web). */
437
+ export function networkRules(settings) {
438
+ if (settings.networkBlockAll)
439
+ return { internet: false };
440
+ const allow = [settings.networkAllowList, settings.domainAllowList]
441
+ .flatMap((list) => (list ?? "").split(","))
442
+ .map((one) => one.trim())
443
+ .filter(Boolean);
444
+ return allow.length ? { internet: true, allow } : undefined;
445
+ }
446
+ export function notFound(what) {
447
+ return new DaytonaNotFoundError(`${what} was not found.`, 404);
448
+ }
@@ -165,8 +165,13 @@ export declare class Sandbox {
165
165
  getPublicHost(port: number): Promise<string>;
166
166
  get pty(): never;
167
167
  get git(): never;
168
- getMetrics(): Promise<never>;
169
- static getMetrics(): Promise<never>;
168
+ /** E2B's metrics, from Runtime's measured readings (`sbx.metrics()`): CPU
169
+ * as a percent of the sandbox's vCPUs and resident memory, one entry per
170
+ * host reading (every minute by default) between `start` and `end`, kept
171
+ * 24 hours at that resolution. Disk use inside the sandbox is not measured:
172
+ * `diskUsed` is null and `diskTotal` is the disk's size. */
173
+ getMetrics(opts?: MetricsOpts): Promise<E2BSandboxMetrics[]>;
174
+ static getMetrics(sandboxId: string, opts?: MetricsOpts & SandboxApiOpts): Promise<E2BSandboxMetrics[]>;
170
175
  updateNetwork(): Promise<never>;
171
176
  uploadUrl(): Promise<never>;
172
177
  downloadUrl(): Promise<never>;
@@ -181,3 +186,18 @@ export declare class SandboxPaginator {
181
186
  get nextToken(): string | undefined;
182
187
  nextItems(): Promise<SandboxInfo[]>;
183
188
  }
189
+ type MetricsOpts = {
190
+ start?: Date | number;
191
+ end?: Date | number;
192
+ };
193
+ export type E2BSandboxMetrics = {
194
+ timestamp: Date;
195
+ cpuUsedPct: number;
196
+ cpuCount: number;
197
+ memUsed: number;
198
+ memTotal: number;
199
+ /** Not measured by Runtime: null. */
200
+ diskUsed: number | null;
201
+ diskTotal: number;
202
+ };
203
+ export {};