withruntime 0.10.0 → 0.11.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 +40 -34
- package/E2B.md +56 -57
- package/VERCEL.md +21 -19
- package/compatibility-lock.json +8 -84
- package/dist/cli.js +73 -2
- package/dist/client.d.ts +12 -0
- package/dist/client.js +27 -0
- package/dist/compat/lease.d.ts +36 -0
- package/dist/compat/lease.js +87 -0
- package/dist/daytona/computer-use.d.ts +162 -0
- package/dist/daytona/computer-use.js +324 -0
- package/dist/daytona/context.d.ts +10 -0
- package/dist/daytona/context.js +24 -0
- package/dist/daytona/daytona.d.ts +20 -0
- package/dist/daytona/daytona.js +123 -16
- package/dist/daytona/filesystem.js +8 -0
- package/dist/daytona/index.d.ts +2 -26
- package/dist/daytona/index.js +2 -7
- package/dist/daytona/process.d.ts +63 -6
- package/dist/daytona/process.js +224 -23
- package/dist/daytona/sandbox.d.ts +19 -5
- package/dist/daytona/sandbox.js +39 -25
- package/dist/e2b/client.d.ts +5 -0
- package/dist/e2b/client.js +5 -1
- package/dist/e2b/commands.d.ts +15 -6
- package/dist/e2b/commands.js +83 -18
- package/dist/e2b/errors.d.ts +7 -0
- package/dist/e2b/errors.js +20 -0
- package/dist/e2b/filesystem.d.ts +2 -1
- package/dist/e2b/filesystem.js +43 -6
- package/dist/e2b/index.d.ts +2 -2
- package/dist/e2b/index.js +1 -1
- package/dist/e2b/pty.js +6 -3
- package/dist/e2b/sandbox.d.ts +15 -5
- package/dist/e2b/sandbox.js +190 -28
- package/dist/e2b/users.d.ts +30 -0
- package/dist/e2b/users.js +185 -0
- package/dist/index.d.ts +1 -0
- package/dist/mcp.d.ts +2 -1
- package/dist/mcp.js +6 -1
- package/dist/network-cli.js +28 -0
- package/dist/products/browser.d.ts +60 -0
- package/dist/products/browser.js +37 -0
- package/dist/products/desktop.d.ts +2 -2
- package/dist/products/desktop.js +2 -2
- package/dist/products/images.d.ts +3 -1
- package/dist/products/images.js +14 -2
- package/dist/products/index.d.ts +2 -0
- package/dist/products/index.js +2 -0
- package/dist/products/network-products.d.ts +7 -0
- package/dist/products/network-products.js +3 -0
- package/dist/products/private-network.d.ts +22 -0
- package/dist/products/private-network.js +10 -0
- package/dist/sandbox.d.ts +22 -0
- package/dist/sandbox.js +47 -0
- package/dist/transport.d.ts +1 -1
- package/dist/transport.js +1 -1
- package/dist/types.d.ts +5 -2
- package/dist/vercel/index.d.ts +1 -7
- package/dist/vercel/index.js +1 -3
- package/dist/vercel/sandbox-user.d.ts +70 -0
- package/dist/vercel/sandbox-user.js +206 -0
- package/dist/vercel/sandbox.d.ts +47 -12
- package/dist/vercel/sandbox.js +201 -42
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -88,7 +88,7 @@ Observability
|
|
|
88
88
|
Events and metrics to an OpenTelemetry endpoint
|
|
89
89
|
|
|
90
90
|
Products
|
|
91
|
-
sandbox Linux microVMs: exec, shell, files, code, previews, network, desktop
|
|
91
|
+
sandbox Linux microVMs: exec, shell, files, code, previews, network, desktop, browser
|
|
92
92
|
snapshot Saved sandboxes, disk and memory, to start or fork from
|
|
93
93
|
image Custom images from a Dockerfile, any public or private image, or a package list
|
|
94
94
|
volume Persistent disks to attach to sandboxes
|
|
@@ -97,7 +97,7 @@ Products
|
|
|
97
97
|
port A public TCP port to a sandbox: databases, game servers
|
|
98
98
|
address A dedicated outbound address, for allow-lists
|
|
99
99
|
tunnel A WireGuard tunnel from your own network into your sandboxes
|
|
100
|
-
network Account-wide network settings:
|
|
100
|
+
network Account-wide network settings: your own proxy, sandboxes reaching each other by name
|
|
101
101
|
Each has its own help: \`runtime sandbox help\`, \`runtime image help\`...
|
|
102
102
|
|
|
103
103
|
Every command takes --json. Keys: RUNTIME_API_KEY, or the connection from \`runtime login\`.
|
|
@@ -131,11 +131,15 @@ const SANDBOX_HELP = `runtime sandbox <command>
|
|
|
131
131
|
cat <id> <path> Print a file
|
|
132
132
|
files <id> [path] [--depth 1] [--glob '**/*.py']
|
|
133
133
|
stop <id> | pause <id> | wake <id> | restart <id>
|
|
134
|
+
stop --label k=v [--label k=v]... Stop every live sandbox with all those labels
|
|
134
135
|
rm <id> Delete it for good: stops it, deletes its disk and
|
|
135
136
|
paused memory, revokes its previews; snapshots stay
|
|
136
137
|
switch-image <id> <image> --keep-workspace Move it to another image, keeping /workspace (your home),
|
|
137
138
|
volumes, env and previews; processes restart, the rest of
|
|
138
139
|
its disk is lost (snapshot it first to keep everything)
|
|
140
|
+
resize <id> [--vcpu 2] [--memory 4096] --restart
|
|
141
|
+
Change its size by a restart: the whole disk stays,
|
|
142
|
+
programs stop (snapshot it first to keep memory)
|
|
139
143
|
extend <id> <seconds> More time before the lease ends
|
|
140
144
|
update <id> [--name n] [--label k=v]... [--env K=V]... [--unset-env K]... [--idle-pause <seconds>] [--auto-wake on|off]
|
|
141
145
|
[--persistent on|off] [--max-total-cost <usd>|none]
|
|
@@ -180,6 +184,8 @@ const SANDBOX_HELP = `runtime sandbox <command>
|
|
|
180
184
|
| type <text> | press <keys> | windows
|
|
181
185
|
desktop <id> record start [--fps 10] [--max-seconds 1800] [--max-mib 512] | record stop <recId>
|
|
182
186
|
| record ls | record fetch <recId> [file.mp4] | record rm <recId>
|
|
187
|
+
browser <id> start [--headed] [--width 1280] [--height 800] | get | stop
|
|
188
|
+
Chromium for CDP agents: prints its cdpUrl
|
|
183
189
|
|
|
184
190
|
Examples
|
|
185
191
|
id=$(runtime sandbox create)
|
|
@@ -410,6 +416,7 @@ const SANDBOX_VERBS = [
|
|
|
410
416
|
"rm",
|
|
411
417
|
"delete",
|
|
412
418
|
"switch-image",
|
|
419
|
+
"resize",
|
|
413
420
|
"pause",
|
|
414
421
|
"wake",
|
|
415
422
|
"restart",
|
|
@@ -437,6 +444,7 @@ const SANDBOX_VERBS = [
|
|
|
437
444
|
"session",
|
|
438
445
|
"network",
|
|
439
446
|
"desktop",
|
|
447
|
+
"browser",
|
|
440
448
|
"metrics",
|
|
441
449
|
"watch",
|
|
442
450
|
"mcp",
|
|
@@ -1495,6 +1503,21 @@ async function sandbox(argv, env, out) {
|
|
|
1495
1503
|
print(describe(sbx.info), sbx.info);
|
|
1496
1504
|
return 0;
|
|
1497
1505
|
}
|
|
1506
|
+
case "resize": {
|
|
1507
|
+
const args = parse(rest, ["restart"], ["vcpu", "memory"]);
|
|
1508
|
+
const sbx = await use(need(args.positional[0], `a sandbox, e.g. ${me} sandbox resize <id> --memory 4096 --restart`));
|
|
1509
|
+
const size = {
|
|
1510
|
+
...(integer(args, "vcpu") !== undefined ? { vcpu: integer(args, "vcpu") } : {}),
|
|
1511
|
+
...(integer(args, "memory") !== undefined ? { memoryMiB: integer(args, "memory") } : {}),
|
|
1512
|
+
};
|
|
1513
|
+
if (size.vcpu === undefined && size.memoryMiB === undefined)
|
|
1514
|
+
throw usage(`Name a new size, e.g. ${me} sandbox resize ${sbx.id} --memory 4096 --restart`);
|
|
1515
|
+
if (!args.flags.has("restart"))
|
|
1516
|
+
throw usage(`A resize restarts it: its whole disk stays and its programs stop. Add --restart to say so, or snapshot it first (${me} sandbox snapshot ${sbx.id}) to keep its memory too.`);
|
|
1517
|
+
await sbx.resize(size, { restart: true });
|
|
1518
|
+
print(describe(sbx.info), sbx.info);
|
|
1519
|
+
return 0;
|
|
1520
|
+
}
|
|
1498
1521
|
case "rm":
|
|
1499
1522
|
case "delete": {
|
|
1500
1523
|
const sbx = await use(need(rest[0], `a sandbox, e.g. ${me} sandbox rm <id>`));
|
|
@@ -1506,6 +1529,23 @@ async function sandbox(argv, env, out) {
|
|
|
1506
1529
|
case "pause":
|
|
1507
1530
|
case "wake":
|
|
1508
1531
|
case "restart": {
|
|
1532
|
+
if (verb === "stop" && rest.some((word) => /^--label(=|$)/.test(word))) {
|
|
1533
|
+
const args = parse(rest, [], ["label"]);
|
|
1534
|
+
if (args.positional.length)
|
|
1535
|
+
throw usage("Give a sandbox id or --label, not both.");
|
|
1536
|
+
const { stopped, failed } = await runtime.sandboxes.stopAll({
|
|
1537
|
+
labels: pairs(args, "label"),
|
|
1538
|
+
});
|
|
1539
|
+
const said = (error) => (error instanceof Error ? error.message : String(error));
|
|
1540
|
+
print([
|
|
1541
|
+
stopped.length || failed.length
|
|
1542
|
+
? `${stopped.length} stopped${failed.length ? `, ${failed.length} failed` : ""}.`
|
|
1543
|
+
: "No live sandbox has those labels.",
|
|
1544
|
+
...stopped.map((id) => `${id} stopped`),
|
|
1545
|
+
...failed.map((f) => `${f.id} failed: ${said(f.error)}`),
|
|
1546
|
+
].join("\n"), { stopped, failed: failed.map((f) => ({ id: f.id, error: said(f.error) })) });
|
|
1547
|
+
return failed.length ? 1 : 0;
|
|
1548
|
+
}
|
|
1509
1549
|
const sbx = await get(rest[0]);
|
|
1510
1550
|
await sbx[verb]();
|
|
1511
1551
|
print(`${sbx.id} ${sbx.state}`, sbx.info);
|
|
@@ -1893,6 +1933,8 @@ async function sandbox(argv, env, out) {
|
|
|
1893
1933
|
}
|
|
1894
1934
|
case "desktop":
|
|
1895
1935
|
return desktop(await use(rest[0]), rest.slice(1), out);
|
|
1936
|
+
case "browser":
|
|
1937
|
+
return browser(await use(rest[0]), rest.slice(1), out);
|
|
1896
1938
|
case "watch":
|
|
1897
1939
|
return (await import("./cli-extras.js")).watchCommand(await use(rest[0]), rest.slice(1), out, kit);
|
|
1898
1940
|
case "mcp":
|
|
@@ -2227,6 +2269,35 @@ async function desktop(sbx, argv, out) {
|
|
|
2227
2269
|
}
|
|
2228
2270
|
throw usage(`${me} sandbox desktop <id> start|stop|screenshot|open|click|type|press|windows|record`);
|
|
2229
2271
|
}
|
|
2272
|
+
async function browser(sbx, argv, out) {
|
|
2273
|
+
const [action, ...rest] = argv;
|
|
2274
|
+
const print = (human, value) => out.write(out.json ? JSON.stringify(value) : human);
|
|
2275
|
+
switch (action) {
|
|
2276
|
+
case "start": {
|
|
2277
|
+
const args = parse(rest, ["headed"], ["width", "height"]);
|
|
2278
|
+
const started = await sbx.browser.start({
|
|
2279
|
+
...(args.flags.has("headed") ? { headless: false } : {}),
|
|
2280
|
+
...(integer(args, "width") !== undefined ? { width: integer(args, "width") } : {}),
|
|
2281
|
+
...(integer(args, "height") !== undefined ? { height: integer(args, "height") } : {}),
|
|
2282
|
+
});
|
|
2283
|
+
print(`${started.version}${started.headless ? "" : `, on the desktop: ${started.streamUrl}`}\n` +
|
|
2284
|
+
`CDP: ${started.cdpUrl}\n(private; it expires ${started.expiresAt ?? "never"})`, started);
|
|
2285
|
+
return 0;
|
|
2286
|
+
}
|
|
2287
|
+
case "get":
|
|
2288
|
+
case undefined: {
|
|
2289
|
+
const state = await sbx.browser.get();
|
|
2290
|
+
print(state.running ? `${state.version}\nCDP: ${state.cdpUrl}` : "No browser running.", state);
|
|
2291
|
+
return 0;
|
|
2292
|
+
}
|
|
2293
|
+
case "stop": {
|
|
2294
|
+
const stopped = await sbx.browser.stop();
|
|
2295
|
+
print(stopped.stopped ? "Browser stopped." : "No browser was running.", stopped);
|
|
2296
|
+
return 0;
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
throw usage(`${me} sandbox browser <id> start [--headed]|get|stop`);
|
|
2300
|
+
}
|
|
2230
2301
|
const KEYS_HELP = `runtime keys <command>
|
|
2231
2302
|
|
|
2232
2303
|
create [--name <name>] [--read-only] [--daily-limit <usd>] [--account-wide]
|
package/dist/client.d.ts
CHANGED
|
@@ -118,6 +118,18 @@ export declare class Sandboxes {
|
|
|
118
118
|
name?: string;
|
|
119
119
|
limit?: number;
|
|
120
120
|
}, options?: RequestOptions): Promise<Page<Sandbox>>;
|
|
121
|
+
/** Stops every live sandbox whose labels all match, eight at a time, and
|
|
122
|
+
* says which stopped and which failed; one failure does not stop the rest.
|
|
123
|
+
* Needs at least one label, so stopping everything is never one call. */
|
|
124
|
+
stopAll(filter: {
|
|
125
|
+
labels: Record<string, string>;
|
|
126
|
+
}, options?: RequestOptions): Promise<{
|
|
127
|
+
stopped: string[];
|
|
128
|
+
failed: {
|
|
129
|
+
id: string;
|
|
130
|
+
error: unknown;
|
|
131
|
+
}[];
|
|
132
|
+
}>;
|
|
121
133
|
}
|
|
122
134
|
export declare class FeedbackApi {
|
|
123
135
|
private readonly t;
|
package/dist/client.js
CHANGED
|
@@ -156,6 +156,33 @@ export class Sandboxes {
|
|
|
156
156
|
};
|
|
157
157
|
return sandboxPage(this.t, await this.t.json({ method: "GET", path: "/v1/sandboxes", query, ...options }), query, options);
|
|
158
158
|
}
|
|
159
|
+
/** Stops every live sandbox whose labels all match, eight at a time, and
|
|
160
|
+
* says which stopped and which failed; one failure does not stop the rest.
|
|
161
|
+
* Needs at least one label, so stopping everything is never one call. */
|
|
162
|
+
async stopAll(filter, options = {}) {
|
|
163
|
+
if (!filter?.labels || Object.keys(filter.labels).length === 0)
|
|
164
|
+
throw new RuntimeError({
|
|
165
|
+
message: "stopAll needs at least one label to match.",
|
|
166
|
+
code: "invalid_request",
|
|
167
|
+
status: 0,
|
|
168
|
+
hint: "Stop one sandbox with sandbox.stop(), or label the ones to stop together.",
|
|
169
|
+
});
|
|
170
|
+
const live = await (await this.list({ labels: filter.labels, limit: 100 }, options)).toArray(Infinity);
|
|
171
|
+
// One key cannot name several stops: each stop makes its own.
|
|
172
|
+
const { idempotencyKey: _one, ...each } = options;
|
|
173
|
+
// In list order, oldest first, whichever finishes first.
|
|
174
|
+
const errors = new Array(live.length);
|
|
175
|
+
let next = 0;
|
|
176
|
+
const worker = async () => {
|
|
177
|
+
for (let at = next++; at < live.length; at = next++)
|
|
178
|
+
await live[at].stop(each).catch((error) => (errors[at] = error ?? "failed"));
|
|
179
|
+
};
|
|
180
|
+
await Promise.all(Array.from({ length: Math.min(8, live.length) }, worker));
|
|
181
|
+
return {
|
|
182
|
+
stopped: live.filter((_, at) => errors[at] === undefined).map((sbx) => sbx.id),
|
|
183
|
+
failed: live.flatMap((sbx, at) => errors[at] === undefined ? [] : [{ id: sbx.id, error: errors[at] }]),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
159
186
|
}
|
|
160
187
|
export class FeedbackApi {
|
|
161
188
|
t;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** The most one lease runs ahead of now. */
|
|
2
|
+
export declare const LEASE_MAX_SECONDS = 3600;
|
|
3
|
+
/** What the keeper needs of a Runtime sandbox. */
|
|
4
|
+
export interface Leased {
|
|
5
|
+
readonly state: string;
|
|
6
|
+
readonly info: {
|
|
7
|
+
expiresAt: string;
|
|
8
|
+
};
|
|
9
|
+
extend(seconds: number): Promise<unknown>;
|
|
10
|
+
refresh(): Promise<unknown>;
|
|
11
|
+
}
|
|
12
|
+
/** Whole seconds to add to a lease ending at `expiresAt` (epoch ms) so it
|
|
13
|
+
* reaches toward `until`, at most an hour ahead of `now`; 0 when more than
|
|
14
|
+
* `marginMs` is left or there is nothing to add. */
|
|
15
|
+
export declare function extensionSeconds(expiresAt: number, until: number, now: number, marginMs: number): number;
|
|
16
|
+
/** Keeps a running sandbox's lease reaching toward `until()`: on `check()`,
|
|
17
|
+
* and once a minute on a timer that never keeps a Node or Bun process alive.
|
|
18
|
+
* When the process ends, the lease runs out within the hour and the sandbox
|
|
19
|
+
* pauses or stops as it was told to at create. A paused or stopped sandbox is
|
|
20
|
+
* left alone; the adapter wakes it on its next call. */
|
|
21
|
+
export declare class LeaseKeeper {
|
|
22
|
+
#private;
|
|
23
|
+
constructor(options: {
|
|
24
|
+
sandbox: () => Leased;
|
|
25
|
+
/** Epoch ms the lease should reach; Infinity for as long as this lives. */
|
|
26
|
+
until: () => number;
|
|
27
|
+
/** Extend only when less than this is left. */
|
|
28
|
+
marginMs: () => number;
|
|
29
|
+
everyMs?: number;
|
|
30
|
+
});
|
|
31
|
+
/** Extends the lease if it is near its end and should go further; `now`
|
|
32
|
+
* extends it as far as it may go whatever is left. One call at a time. */
|
|
33
|
+
check(now?: boolean): Promise<void>;
|
|
34
|
+
/** Stops extending: after stop() or delete(). */
|
|
35
|
+
end(): void;
|
|
36
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { RuntimeError } from "../errors.js";
|
|
2
|
+
/* A rival's sandbox may be asked to live longer than one Runtime lease (an
|
|
3
|
+
hour at most, ARCHITECTURE.md section 10): Vercel's `timeout` over an hour,
|
|
4
|
+
Daytona's `autoStopInterval` over an hour or 0. The drop-ins keep the lease
|
|
5
|
+
reaching toward the time asked for while their sandbox object lives, one
|
|
6
|
+
extension at a time, never past that time. */
|
|
7
|
+
/** The most one lease runs ahead of now. */
|
|
8
|
+
export const LEASE_MAX_SECONDS = 3600;
|
|
9
|
+
/** Whole seconds to add to a lease ending at `expiresAt` (epoch ms) so it
|
|
10
|
+
* reaches toward `until`, at most an hour ahead of `now`; 0 when more than
|
|
11
|
+
* `marginMs` is left or there is nothing to add. */
|
|
12
|
+
export function extensionSeconds(expiresAt, until, now, marginMs) {
|
|
13
|
+
// A lease with no readable end (one that never ends) is left alone.
|
|
14
|
+
if (!Number.isFinite(expiresAt) || expiresAt - now > marginMs)
|
|
15
|
+
return 0;
|
|
16
|
+
const target = Math.min(until, now + LEASE_MAX_SECONDS * 1000);
|
|
17
|
+
return Math.max(0, Math.floor((target - expiresAt) / 1000));
|
|
18
|
+
}
|
|
19
|
+
/** Keeps a running sandbox's lease reaching toward `until()`: on `check()`,
|
|
20
|
+
* and once a minute on a timer that never keeps a Node or Bun process alive.
|
|
21
|
+
* When the process ends, the lease runs out within the hour and the sandbox
|
|
22
|
+
* pauses or stops as it was told to at create. A paused or stopped sandbox is
|
|
23
|
+
* left alone; the adapter wakes it on its next call. */
|
|
24
|
+
export class LeaseKeeper {
|
|
25
|
+
#sandbox;
|
|
26
|
+
#until;
|
|
27
|
+
#marginMs;
|
|
28
|
+
#everyMs;
|
|
29
|
+
#timer;
|
|
30
|
+
#pending;
|
|
31
|
+
#ended = false;
|
|
32
|
+
constructor(options) {
|
|
33
|
+
this.#sandbox = options.sandbox;
|
|
34
|
+
this.#until = options.until;
|
|
35
|
+
this.#marginMs = options.marginMs;
|
|
36
|
+
this.#everyMs = options.everyMs ?? 60_000;
|
|
37
|
+
}
|
|
38
|
+
/** Starts the timer when the lease must outlive the next extension. */
|
|
39
|
+
#schedule() {
|
|
40
|
+
if (this.#ended || this.#timer)
|
|
41
|
+
return;
|
|
42
|
+
const expiresAt = Date.parse(this.#sandbox().info.expiresAt);
|
|
43
|
+
if (!Number.isFinite(expiresAt) || this.#until() <= expiresAt)
|
|
44
|
+
return;
|
|
45
|
+
this.#timer = setTimeout(() => {
|
|
46
|
+
this.#timer = undefined;
|
|
47
|
+
void this.check().catch(() => undefined);
|
|
48
|
+
}, this.#everyMs);
|
|
49
|
+
this.#timer.unref?.();
|
|
50
|
+
}
|
|
51
|
+
/** Extends the lease if it is near its end and should go further; `now`
|
|
52
|
+
* extends it as far as it may go whatever is left. One call at a time. */
|
|
53
|
+
check(now = false) {
|
|
54
|
+
if (this.#ended)
|
|
55
|
+
return Promise.resolve();
|
|
56
|
+
this.#pending ??= this.#extend(now).finally(() => {
|
|
57
|
+
this.#pending = undefined;
|
|
58
|
+
this.#schedule();
|
|
59
|
+
});
|
|
60
|
+
return this.#pending;
|
|
61
|
+
}
|
|
62
|
+
async #extend(now) {
|
|
63
|
+
const sandbox = this.#sandbox();
|
|
64
|
+
if (sandbox.state !== "running")
|
|
65
|
+
return;
|
|
66
|
+
const seconds = extensionSeconds(Date.parse(sandbox.info.expiresAt), this.#until(), Date.now(), now ? Infinity : this.#marginMs());
|
|
67
|
+
if (seconds < 1)
|
|
68
|
+
return;
|
|
69
|
+
try {
|
|
70
|
+
await sandbox.extend(seconds);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
// The lease may have ended since the sandbox was last read; the next
|
|
74
|
+
// call through the adapter says what state it is in.
|
|
75
|
+
if (!(error instanceof RuntimeError && error.status === 409))
|
|
76
|
+
throw error;
|
|
77
|
+
await sandbox.refresh().catch(() => undefined);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/** Stops extending: after stop() or delete(). */
|
|
81
|
+
end() {
|
|
82
|
+
this.#ended = true;
|
|
83
|
+
if (this.#timer)
|
|
84
|
+
clearTimeout(this.#timer);
|
|
85
|
+
this.#timer = undefined;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import type { RuntimeSandbox } from "./client.js";
|
|
2
|
+
type Live = () => Promise<RuntimeSandbox>;
|
|
3
|
+
export interface ScreenshotRegion {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}
|
|
9
|
+
export interface ScreenshotOptions {
|
|
10
|
+
showCursor?: boolean;
|
|
11
|
+
format?: string;
|
|
12
|
+
quality?: number;
|
|
13
|
+
scale?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface Position {
|
|
16
|
+
x?: number;
|
|
17
|
+
y?: number;
|
|
18
|
+
}
|
|
19
|
+
export interface ScreenshotResponse {
|
|
20
|
+
cursorPosition?: Position;
|
|
21
|
+
/** The image, base64. */
|
|
22
|
+
screenshot?: string;
|
|
23
|
+
sizeBytes?: number;
|
|
24
|
+
}
|
|
25
|
+
export interface DisplayInfo {
|
|
26
|
+
height?: number;
|
|
27
|
+
id?: number;
|
|
28
|
+
isActive?: boolean;
|
|
29
|
+
width?: number;
|
|
30
|
+
x?: number;
|
|
31
|
+
y?: number;
|
|
32
|
+
}
|
|
33
|
+
export interface WindowInfo {
|
|
34
|
+
height?: number;
|
|
35
|
+
id?: number;
|
|
36
|
+
isActive?: boolean;
|
|
37
|
+
title?: string;
|
|
38
|
+
width?: number;
|
|
39
|
+
x?: number;
|
|
40
|
+
y?: number;
|
|
41
|
+
}
|
|
42
|
+
export interface ProcessStatus {
|
|
43
|
+
autoRestart?: boolean;
|
|
44
|
+
pid?: number;
|
|
45
|
+
priority?: number;
|
|
46
|
+
running?: boolean;
|
|
47
|
+
}
|
|
48
|
+
export interface ComputerUseStartResponse {
|
|
49
|
+
message?: string;
|
|
50
|
+
status?: Record<string, ProcessStatus>;
|
|
51
|
+
}
|
|
52
|
+
export type ComputerUseStopResponse = ComputerUseStartResponse;
|
|
53
|
+
export interface ComputerUseStatusResponse {
|
|
54
|
+
status?: string;
|
|
55
|
+
}
|
|
56
|
+
export interface Recording {
|
|
57
|
+
durationSeconds?: number;
|
|
58
|
+
endTime?: string;
|
|
59
|
+
fileName: string;
|
|
60
|
+
filePath: string;
|
|
61
|
+
id: string;
|
|
62
|
+
sizeBytes?: number;
|
|
63
|
+
startTime: string;
|
|
64
|
+
status: string;
|
|
65
|
+
}
|
|
66
|
+
export interface ListRecordingsResponse {
|
|
67
|
+
recordings: Recording[];
|
|
68
|
+
}
|
|
69
|
+
/** `sandbox.computerUse.mouse`. */
|
|
70
|
+
export declare class Mouse {
|
|
71
|
+
#private;
|
|
72
|
+
/** Use sandbox.computerUse.mouse. */
|
|
73
|
+
constructor(live: Live);
|
|
74
|
+
getPosition(): Promise<Position>;
|
|
75
|
+
move(x: number, y: number): Promise<Position>;
|
|
76
|
+
click(x: number, y: number, button?: string, double?: boolean): Promise<Position>;
|
|
77
|
+
drag(startX: number, startY: number, endX: number, endY: number, button?: string): Promise<Position>;
|
|
78
|
+
/** `amount` wheel clicks up or down at (x, y). */
|
|
79
|
+
scroll(x: number, y: number, direction: "up" | "down", amount?: number): Promise<boolean>;
|
|
80
|
+
}
|
|
81
|
+
/** `sandbox.computerUse.keyboard`. Key names are Daytona's (enter, esc,
|
|
82
|
+
* ctrl, cmd, pageup, f5) or xdotool's (Return, Escape, Prior). */
|
|
83
|
+
export declare class Keyboard {
|
|
84
|
+
#private;
|
|
85
|
+
/** Use sandbox.computerUse.keyboard. */
|
|
86
|
+
constructor(live: Live);
|
|
87
|
+
/** Types `text`, `delay` milliseconds between keys. */
|
|
88
|
+
type(text: string, delay?: number): Promise<void>;
|
|
89
|
+
press(key: string, modifiers?: string[]): Promise<void>;
|
|
90
|
+
/** A combination such as "ctrl+c" or "ctrl+shift+t". */
|
|
91
|
+
hotkey(keys: string): Promise<void>;
|
|
92
|
+
}
|
|
93
|
+
/** `sandbox.computerUse.screenshot`: the whole screen, PNG or JPEG. */
|
|
94
|
+
export declare class Screenshot {
|
|
95
|
+
#private;
|
|
96
|
+
/** Use sandbox.computerUse.screenshot. */
|
|
97
|
+
constructor(live: Live);
|
|
98
|
+
takeFullScreen(showCursor?: boolean): Promise<ScreenshotResponse>;
|
|
99
|
+
takeRegion(_region: ScreenshotRegion, _showCursor?: boolean): Promise<ScreenshotResponse>;
|
|
100
|
+
takeCompressed(options?: ScreenshotOptions): Promise<ScreenshotResponse>;
|
|
101
|
+
takeCompressedRegion(_region: ScreenshotRegion, _options?: ScreenshotOptions): Promise<ScreenshotResponse>;
|
|
102
|
+
}
|
|
103
|
+
/** `sandbox.computerUse.display`. */
|
|
104
|
+
export declare class Display {
|
|
105
|
+
#private;
|
|
106
|
+
/** Use sandbox.computerUse.display. */
|
|
107
|
+
constructor(live: Live);
|
|
108
|
+
/** The one screen, its size read from a screenshot. */
|
|
109
|
+
getInfo(): Promise<{
|
|
110
|
+
displays?: DisplayInfo[];
|
|
111
|
+
}>;
|
|
112
|
+
getWindows(): Promise<{
|
|
113
|
+
windows?: WindowInfo[];
|
|
114
|
+
}>;
|
|
115
|
+
}
|
|
116
|
+
/** `sandbox.computerUse.recording`: screen recordings to MP4. */
|
|
117
|
+
export declare class RecordingService {
|
|
118
|
+
#private;
|
|
119
|
+
/** Use sandbox.computerUse.recording. */
|
|
120
|
+
constructor(live: Live);
|
|
121
|
+
/** Starts recording. Runtime names the file itself; `label` is not used. */
|
|
122
|
+
start(_label?: string): Promise<Recording>;
|
|
123
|
+
stop(id: string): Promise<Recording>;
|
|
124
|
+
list(): Promise<ListRecordingsResponse>;
|
|
125
|
+
get(id: string): Promise<Recording>;
|
|
126
|
+
delete(id: string): Promise<void>;
|
|
127
|
+
/** Saves the MP4 to `localPath`, making its directory. */
|
|
128
|
+
download(id: string, localPath: string): Promise<void>;
|
|
129
|
+
}
|
|
130
|
+
/** `sandbox.computerUse.accessibility`: Runtime's desktop has no
|
|
131
|
+
* accessibility tree; every method throws NotSupportedError. */
|
|
132
|
+
export declare class Accessibility {
|
|
133
|
+
#private;
|
|
134
|
+
getTree(_options?: unknown): Promise<never>;
|
|
135
|
+
findNodes(_options?: unknown): Promise<never>;
|
|
136
|
+
focusNode(_id: string): Promise<never>;
|
|
137
|
+
invokeNode(_id: string, _action?: string): Promise<never>;
|
|
138
|
+
setNodeValue(_id: string, _value: string): Promise<never>;
|
|
139
|
+
}
|
|
140
|
+
/** `sandbox.computerUse`: a Linux desktop driven like a person would. */
|
|
141
|
+
export declare class ComputerUse {
|
|
142
|
+
#private;
|
|
143
|
+
readonly mouse: Mouse;
|
|
144
|
+
readonly keyboard: Keyboard;
|
|
145
|
+
readonly screenshot: Screenshot;
|
|
146
|
+
readonly display: Display;
|
|
147
|
+
readonly recording: RecordingService;
|
|
148
|
+
readonly accessibility: Accessibility;
|
|
149
|
+
/** Use sandbox.computerUse. */
|
|
150
|
+
constructor(live: Live);
|
|
151
|
+
/** Starts the desktop. A sandbox's first start installs it, which takes a
|
|
152
|
+
* minute or two; this waits for that. */
|
|
153
|
+
start(): Promise<ComputerUseStartResponse>;
|
|
154
|
+
stop(): Promise<ComputerUseStopResponse>;
|
|
155
|
+
/** "active" while the desktop runs, else "inactive". */
|
|
156
|
+
getStatus(): Promise<ComputerUseStatusResponse>;
|
|
157
|
+
getProcessStatus(_processName: string): Promise<never>;
|
|
158
|
+
restartProcess(_processName: string): Promise<never>;
|
|
159
|
+
getProcessLogs(_processName: string): Promise<never>;
|
|
160
|
+
getProcessErrors(_processName: string): Promise<never>;
|
|
161
|
+
}
|
|
162
|
+
export {};
|