withruntime 0.10.0 → 0.11.1

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 (94) hide show
  1. package/BLAXEL.md +7 -8
  2. package/DAYTONA.md +40 -35
  3. package/E2B.md +70 -57
  4. package/README.md +3 -3
  5. package/README.src.md +3 -3
  6. package/VERCEL.md +23 -20
  7. package/compatibility-lock.json +63 -84
  8. package/dist/api-defaults.d.ts +1 -1
  9. package/dist/api-defaults.js +1 -1
  10. package/dist/blaxel/lookup.d.ts +2 -1
  11. package/dist/blaxel/lookup.js +2 -1
  12. package/dist/blaxel/sandbox.d.ts +7 -5
  13. package/dist/blaxel/sandbox.js +15 -10
  14. package/dist/cli.js +112 -17
  15. package/dist/client.d.ts +17 -1
  16. package/dist/client.js +46 -3
  17. package/dist/compat/files.js +5 -1
  18. package/dist/compat/lease.d.ts +37 -0
  19. package/dist/compat/lease.js +93 -0
  20. package/dist/credentials.d.ts +9 -0
  21. package/dist/credentials.js +26 -4
  22. package/dist/daytona/computer-use.d.ts +162 -0
  23. package/dist/daytona/computer-use.js +324 -0
  24. package/dist/daytona/context.d.ts +10 -0
  25. package/dist/daytona/context.js +24 -0
  26. package/dist/daytona/daytona.d.ts +20 -0
  27. package/dist/daytona/daytona.js +150 -26
  28. package/dist/daytona/filesystem.js +8 -0
  29. package/dist/daytona/index.d.ts +2 -26
  30. package/dist/daytona/index.js +2 -7
  31. package/dist/daytona/process.d.ts +63 -6
  32. package/dist/daytona/process.js +224 -23
  33. package/dist/daytona/sandbox.d.ts +25 -6
  34. package/dist/daytona/sandbox.js +60 -27
  35. package/dist/e2b/client.d.ts +5 -0
  36. package/dist/e2b/client.js +5 -1
  37. package/dist/e2b/commands.d.ts +15 -6
  38. package/dist/e2b/commands.js +83 -18
  39. package/dist/e2b/errors.d.ts +7 -0
  40. package/dist/e2b/errors.js +20 -0
  41. package/dist/e2b/filesystem.d.ts +2 -1
  42. package/dist/e2b/filesystem.js +43 -6
  43. package/dist/e2b/index.d.ts +2 -2
  44. package/dist/e2b/index.js +1 -1
  45. package/dist/e2b/pty.js +6 -3
  46. package/dist/e2b/sandbox.d.ts +20 -6
  47. package/dist/e2b/sandbox.js +207 -31
  48. package/dist/e2b/users.d.ts +30 -0
  49. package/dist/e2b/users.js +185 -0
  50. package/dist/errors.d.ts +6 -0
  51. package/dist/errors.js +6 -0
  52. package/dist/identity.js +2 -1
  53. package/dist/index.d.ts +3 -1
  54. package/dist/index.js +2 -1
  55. package/dist/mcp.d.ts +2 -1
  56. package/dist/mcp.js +6 -1
  57. package/dist/modal/index.js +6 -2
  58. package/dist/network-cli.js +33 -5
  59. package/dist/products/browser.d.ts +61 -0
  60. package/dist/products/browser.js +27 -0
  61. package/dist/products/desktop.d.ts +4 -3
  62. package/dist/products/desktop.js +7 -32
  63. package/dist/products/images.d.ts +3 -1
  64. package/dist/products/images.js +14 -2
  65. package/dist/products/index.d.ts +2 -0
  66. package/dist/products/index.js +2 -0
  67. package/dist/products/jobs.d.ts +7 -5
  68. package/dist/products/jobs.js +7 -3
  69. package/dist/products/mcp.d.ts +5 -1
  70. package/dist/products/mcp.js +29 -8
  71. package/dist/products/network-products.d.ts +8 -1
  72. package/dist/products/network-products.js +4 -1
  73. package/dist/products/observability.d.ts +1 -1
  74. package/dist/products/private-network.d.ts +22 -0
  75. package/dist/products/private-network.js +10 -0
  76. package/dist/products/secrets.d.ts +2 -2
  77. package/dist/runloop/index.js +6 -2
  78. package/dist/sandbox.d.ts +44 -14
  79. package/dist/sandbox.js +162 -48
  80. package/dist/tar.d.ts +2 -0
  81. package/dist/tar.js +74 -16
  82. package/dist/transport.d.ts +33 -7
  83. package/dist/transport.js +171 -36
  84. package/dist/types.d.ts +59 -11
  85. package/dist/vercel/filesystem.js +3 -1
  86. package/dist/vercel/index.d.ts +1 -7
  87. package/dist/vercel/index.js +1 -3
  88. package/dist/vercel/sandbox-user.d.ts +70 -0
  89. package/dist/vercel/sandbox-user.js +206 -0
  90. package/dist/vercel/sandbox.d.ts +57 -15
  91. package/dist/vercel/sandbox.js +219 -47
  92. package/dist/wait.d.ts +12 -0
  93. package/dist/wait.js +47 -0
  94. package/package.json +1 -1
package/dist/client.js CHANGED
@@ -4,7 +4,7 @@ import { clientFactories, clientProductAliases } from "./products/index.js";
4
4
  import { usageExport as makeUsageExport } from "./products/observability.js";
5
5
  import { Sandbox, deleteSandbox, sandboxPage } from "./sandbox.js";
6
6
  import { Snapshots } from "./snapshots.js";
7
- import { Transport, missingKey } from "./transport.js";
7
+ import { DEFAULT_BASE_URL, Transport, missingKey } from "./transport.js";
8
8
  /** The key `runtime login` saved for this machine and this API origin, found
9
9
  * on first use. A constructor override must never receive another API's key. */
10
10
  const savedKey = async (apiOrigin) => {
@@ -30,10 +30,14 @@ export class Runtime {
30
30
  /** Date-range settlements, paged with exact charges and the server's CSV. */
31
31
  usageExport;
32
32
  constructor(options = {}) {
33
+ // The saved key is found by the origin as given, as `runtime login` saved
34
+ // it; the calls go where that origin is reachable from here, which in a
35
+ // sandbox is runtime.internal (transport.ts, `reachable`).
36
+ const origin = options.baseUrl || env("RUNTIME_API_URL") || DEFAULT_BASE_URL;
33
37
  this.transport = new Transport({
34
38
  // A key given, then RUNTIME_API_KEY, then (in Node and Bun) the key
35
39
  // `runtime login` saved for this machine, read on the first call.
36
- apiKey: options.apiKey ?? env("RUNTIME_API_KEY") ?? (() => savedKey(this.transport.baseUrl)),
40
+ apiKey: options.apiKey ?? env("RUNTIME_API_KEY") ?? (() => savedKey(origin)),
37
41
  baseUrl: options.baseUrl ?? env("RUNTIME_API_URL"),
38
42
  ...(options.fetch ? { fetch: options.fetch } : {}),
39
43
  ...(options.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}),
@@ -97,6 +101,9 @@ export class Sandboxes {
97
101
  * free, up to `waitForCapacityMs` (the client's, two minutes by default). */
98
102
  async create(input = {}, options = {}) {
99
103
  const { wait, ...body } = input;
104
+ const began = performance.now();
105
+ // Time spent waiting for capacity is the room's, not the deadline's.
106
+ let waited = 0;
100
107
  const info = await this.t.json({
101
108
  method: "POST",
102
109
  path: "/v1/sandboxes",
@@ -104,13 +111,22 @@ export class Sandboxes {
104
111
  wait: wait === false ? 0 : 60,
105
112
  ...options,
106
113
  waitForCapacityMs: options.waitForCapacityMs ?? this.t.waitForCapacityMs,
114
+ onCapacityWait: (refusal, waitMs) => {
115
+ waited += waitMs;
116
+ options.onCapacityWait?.(refusal, waitMs);
117
+ },
107
118
  });
108
119
  const sandbox = new Sandbox(this.t, info);
109
120
  if (wait !== false && info.state !== "running") {
121
+ // One deadline for the whole create: the wait for running gets what the
122
+ // create left of it (1 ms when nothing is left, so it ends as a timeout).
123
+ const { timeoutMs } = options;
110
124
  await sandbox.waitFor("running", {
111
125
  timeoutSeconds: WAIT_FOR_TIMEOUT_SECONDS,
112
126
  signal: options.signal,
113
- timeoutMs: options.timeoutMs,
127
+ timeoutMs: timeoutMs
128
+ ? Math.max(1, Math.ceil(timeoutMs - (performance.now() - began - waited)))
129
+ : timeoutMs,
114
130
  idempotencyKey: options.idempotencyKey,
115
131
  });
116
132
  if (sandbox.state !== "running")
@@ -156,6 +172,33 @@ export class Sandboxes {
156
172
  };
157
173
  return sandboxPage(this.t, await this.t.json({ method: "GET", path: "/v1/sandboxes", query, ...options }), query, options);
158
174
  }
175
+ /** Stops every live sandbox whose labels all match, eight at a time, and
176
+ * says which stopped and which failed; one failure does not stop the rest.
177
+ * Needs at least one label, so stopping everything is never one call. */
178
+ async stopAll(filter, options = {}) {
179
+ if (!filter?.labels || Object.keys(filter.labels).length === 0)
180
+ throw new RuntimeError({
181
+ message: "stopAll needs at least one label to match.",
182
+ code: "invalid_request",
183
+ status: 0,
184
+ hint: "Stop one sandbox with sandbox.stop(), or label the ones to stop together.",
185
+ });
186
+ const live = await (await this.list({ labels: filter.labels, limit: 100 }, options)).toArray(Infinity);
187
+ // One key cannot name several stops: each stop makes its own.
188
+ const { idempotencyKey: _one, ...each } = options;
189
+ // In list order, oldest first, whichever finishes first.
190
+ const errors = new Array(live.length);
191
+ let next = 0;
192
+ const worker = async () => {
193
+ for (let at = next++; at < live.length; at = next++)
194
+ await live[at].stop(each).catch((error) => (errors[at] = error ?? "failed"));
195
+ };
196
+ await Promise.all(Array.from({ length: Math.min(8, live.length) }, worker));
197
+ return {
198
+ stopped: live.filter((_, at) => errors[at] === undefined).map((sbx) => sbx.id),
199
+ failed: live.flatMap((sbx, at) => errors[at] === undefined ? [] : [{ id: sbx.id, error: errors[at] }]),
200
+ };
201
+ }
159
202
  }
160
203
  export class FeedbackApi {
161
204
  t;
@@ -63,10 +63,14 @@ export class GuestFiles {
63
63
  if (!overwrite) {
64
64
  // cp -n alone reports success when it skips a raced destination. Stage
65
65
  // privately, then publish without replacement and verify it moved.
66
+ // mv -n that skips succeeds before coreutils 9.2 and fails from it on
67
+ // (the guest's 9.4 says "not replacing"), so a skip is told by the
68
+ // staged copy still being there beside a destination; with none there,
69
+ // mv's own error stands.
66
70
  await checked(sandbox, [
67
71
  "bash",
68
72
  "-c",
69
- 'set -e; parent=$(dirname -- "$2"); stage="$parent/.runtime-copy-$4"; mkdir -m 700 -- "$stage"; trap \'rm -rf -- "$stage"\' EXIT; if [ "$3" = true ]; then cp -R -n -- "$1" "$stage/item"; else cp -n -- "$1" "$stage/item"; fi; mv -n -T -- "$stage/item" "$2"; if [ -e "$stage/item" ] || [ -L "$stage/item" ]; then printf "Destination exists: %s\\n" "$2" >&2; exit 73; fi',
73
+ 'set -e; parent=$(dirname -- "$2"); stage="$parent/.runtime-copy-$4"; mkdir -m 700 -- "$stage"; trap \'rm -rf -- "$stage"\' EXIT; if [ "$3" = true ]; then cp -R -- "$1" "$stage/item"; else cp -- "$1" "$stage/item"; fi; mv -n -T -- "$stage/item" "$2" 2>"$stage/mv.err" || :; if [ -e "$stage/item" ] || [ -L "$stage/item" ]; then if [ -e "$2" ] || [ -L "$2" ]; then printf "Destination exists: %s\\n" "$2" >&2; exit 73; fi; cat -- "$stage/mv.err" >&2; exit 1; fi',
70
74
  "bash",
71
75
  this.path(from),
72
76
  this.path(to),
@@ -0,0 +1,37 @@
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
+ endsAt?: string | null;
9
+ };
10
+ extend(seconds: number): Promise<unknown>;
11
+ refresh(): Promise<unknown>;
12
+ }
13
+ /** Whole seconds to add to a lease ending at `expiresAt` (epoch ms) so it
14
+ * reaches toward `until`, at most an hour ahead of `now`; 0 when more than
15
+ * `marginMs` is left or there is nothing to add. */
16
+ export declare function extensionSeconds(expiresAt: number, until: number, now: number, marginMs: number): number;
17
+ /** Keeps a running sandbox's lease reaching toward `until()`: on `check()`,
18
+ * and once a minute on a timer that never keeps a Node or Bun process alive.
19
+ * When the process ends, the lease runs out within the hour and the sandbox
20
+ * pauses or stops as it was told to at create. A paused or stopped sandbox is
21
+ * left alone; the adapter wakes it on its next call. */
22
+ export declare class LeaseKeeper {
23
+ #private;
24
+ constructor(options: {
25
+ sandbox: () => Leased;
26
+ /** Epoch ms the lease should reach; Infinity for as long as this lives. */
27
+ until: () => number;
28
+ /** Extend only when less than this is left. */
29
+ marginMs: () => number;
30
+ everyMs?: number;
31
+ });
32
+ /** Extends the lease if it is near its end and should go further; `now`
33
+ * extends it as far as it may go whatever is left. One call at a time. */
34
+ check(now?: boolean): Promise<void>;
35
+ /** Stops extending: after stop() or delete(). */
36
+ end(): void;
37
+ }
@@ -0,0 +1,93 @@
1
+ import { RuntimeError } from "../errors.js";
2
+ /* A rival's sandbox may be asked to live longer than one Runtime time limit
3
+ (an hour at most, ARCHITECTURE.md section 10): Vercel's `timeout` over an
4
+ hour, Daytona's `autoStopInterval` over an hour. The drop-ins keep the
5
+ limit reaching toward the time asked for while their sandbox object lives,
6
+ one extension at a time, never past that time. A sandbox created with no
7
+ time limit renews itself on the server (0300; `endsAt` null) and is left
8
+ alone. */
9
+ /** The most one lease runs ahead of now. */
10
+ export const LEASE_MAX_SECONDS = 3600;
11
+ /** Whole seconds to add to a lease ending at `expiresAt` (epoch ms) so it
12
+ * reaches toward `until`, at most an hour ahead of `now`; 0 when more than
13
+ * `marginMs` is left or there is nothing to add. */
14
+ export function extensionSeconds(expiresAt, until, now, marginMs) {
15
+ // A lease with no readable end (one that never ends) is left alone.
16
+ if (!Number.isFinite(expiresAt) || expiresAt - now > marginMs)
17
+ return 0;
18
+ const target = Math.min(until, now + LEASE_MAX_SECONDS * 1000);
19
+ return Math.max(0, Math.floor((target - expiresAt) / 1000));
20
+ }
21
+ /** Keeps a running sandbox's lease reaching toward `until()`: on `check()`,
22
+ * and once a minute on a timer that never keeps a Node or Bun process alive.
23
+ * When the process ends, the lease runs out within the hour and the sandbox
24
+ * pauses or stops as it was told to at create. A paused or stopped sandbox is
25
+ * left alone; the adapter wakes it on its next call. */
26
+ export class LeaseKeeper {
27
+ #sandbox;
28
+ #until;
29
+ #marginMs;
30
+ #everyMs;
31
+ #timer;
32
+ #pending;
33
+ #ended = false;
34
+ constructor(options) {
35
+ this.#sandbox = options.sandbox;
36
+ this.#until = options.until;
37
+ this.#marginMs = options.marginMs;
38
+ this.#everyMs = options.everyMs ?? 60_000;
39
+ }
40
+ /** Starts the timer when the lease must outlive the next extension. */
41
+ #schedule() {
42
+ if (this.#ended || this.#timer)
43
+ return;
44
+ const info = this.#sandbox().info;
45
+ if (info.endsAt === null)
46
+ return;
47
+ const expiresAt = Date.parse(info.endsAt ?? info.expiresAt);
48
+ if (!Number.isFinite(expiresAt) || this.#until() <= expiresAt)
49
+ return;
50
+ this.#timer = setTimeout(() => {
51
+ this.#timer = undefined;
52
+ void this.check().catch(() => undefined);
53
+ }, this.#everyMs);
54
+ this.#timer.unref?.();
55
+ }
56
+ /** Extends the lease if it is near its end and should go further; `now`
57
+ * extends it as far as it may go whatever is left. One call at a time. */
58
+ check(now = false) {
59
+ if (this.#ended)
60
+ return Promise.resolve();
61
+ this.#pending ??= this.#extend(now).finally(() => {
62
+ this.#pending = undefined;
63
+ this.#schedule();
64
+ });
65
+ return this.#pending;
66
+ }
67
+ async #extend(now) {
68
+ const sandbox = this.#sandbox();
69
+ // No time limit: the server renews it, and an extension would change nothing.
70
+ if (sandbox.state !== "running" || sandbox.info.endsAt === null)
71
+ return;
72
+ const seconds = extensionSeconds(Date.parse(sandbox.info.endsAt ?? sandbox.info.expiresAt), this.#until(), Date.now(), now ? Infinity : this.#marginMs());
73
+ if (seconds < 1)
74
+ return;
75
+ try {
76
+ await sandbox.extend(seconds);
77
+ }
78
+ catch (error) {
79
+ // The lease may have ended since the sandbox was last read; the next
80
+ // call through the adapter says what state it is in.
81
+ if (!(error instanceof RuntimeError && error.status === 409))
82
+ throw error;
83
+ await sandbox.refresh().catch(() => undefined);
84
+ }
85
+ }
86
+ /** Stops extending: after stop() or delete(). */
87
+ end() {
88
+ this.#ended = true;
89
+ if (this.#timer)
90
+ clearTimeout(this.#timer);
91
+ this.#timer = undefined;
92
+ }
93
+ }
@@ -10,6 +10,15 @@ export type SavedConnection = {
10
10
  /** The account's name when it was saved, for `runtime account`. */
11
11
  orgName?: string;
12
12
  };
13
+ /** Saved accounts could not be updated because another command holds their
14
+ * lock: still `busy` after the whole wait, or `interrupted`, left by a command
15
+ * that died holding it. The message names the lock file to remove. */
16
+ export declare class CredentialsLockedError extends Error {
17
+ readonly lockFile: string;
18
+ readonly reason: "busy" | "interrupted";
19
+ readonly name = "CredentialsLockedError";
20
+ constructor(message: string, lockFile: string, reason: "busy" | "interrupted");
21
+ }
13
22
  export declare function connectionOrigins(env: NodeJS.ProcessEnv): {
14
23
  api: string;
15
24
  auth: string;
@@ -4,6 +4,23 @@ import { lstat, mkdir, open, rename, unlink } from "node:fs/promises";
4
4
  import { homedir } from "node:os";
5
5
  import { isAbsolute, join } from "node:path";
6
6
  import { apiOrigin, missingKey } from "./transport.js";
7
+ /** Saved accounts could not be updated because another command holds their
8
+ * lock: still `busy` after the whole wait, or `interrupted`, left by a command
9
+ * that died holding it. The message names the lock file to remove. */
10
+ export class CredentialsLockedError extends Error {
11
+ lockFile;
12
+ reason;
13
+ name = "CredentialsLockedError";
14
+ constructor(message, lockFile, reason) {
15
+ super(message);
16
+ this.lockFile = lockFile;
17
+ this.reason = reason;
18
+ }
19
+ }
20
+ /** How long a save waits for another command's update to finish. An update
21
+ * is one read, modify and write of small files, so only a heavily loaded
22
+ * machine comes near it. */
23
+ const LOCK_WAIT_MS = 30_000;
7
24
  /** How many other accounts' connections one machine keeps beside the one in use. */
8
25
  const SAVED_ACCOUNTS = 20;
9
26
  export function connectionOrigins(env) {
@@ -107,7 +124,7 @@ export function connectionStore(env, directory = defaultDirectory(env)) {
107
124
  * Never steal a lock: stale cleanup can otherwise delete a new live lock. */
108
125
  async function updateAccounts(update) {
109
126
  await privateDirectory(true);
110
- const until = performance.now() + 10_000;
127
+ const until = performance.now() + LOCK_WAIT_MS;
111
128
  let handle;
112
129
  for (;;) {
113
130
  try {
@@ -127,16 +144,21 @@ export function connectionStore(env, directory = defaultDirectory(env)) {
127
144
  // The holder may not have finished writing its process id yet.
128
145
  }
129
146
  if (typeof pid === "number" && Number.isSafeInteger(pid) && pid > 0) {
147
+ let gone = false;
130
148
  try {
131
149
  process.kill(pid, 0);
132
150
  }
133
151
  catch (error) {
134
- if (error.code === "ESRCH")
135
- throw new Error(`A previous Runtime credential update was interrupted. Remove ${lockFile} and retry.`);
152
+ gone = error.code === "ESRCH";
136
153
  }
154
+ // A holder that finished between our read and our check has exited
155
+ // too, and its lock is gone or another's: wait for the lock again.
156
+ // Only a lock still naming the dead process was left by one that died.
157
+ if (gone && (await readPrivate(lockFile, 1024, "credential update lock")) === text)
158
+ throw new CredentialsLockedError(`A previous Runtime credential update was interrupted. Remove ${lockFile} and retry.`, lockFile, "interrupted");
137
159
  }
138
160
  if (performance.now() >= until)
139
- throw new Error(`Another Runtime command is updating saved accounts. Retry when it finishes. If no command is running, remove ${lockFile} and retry.`);
161
+ throw new CredentialsLockedError(`Another Runtime command is updating saved accounts. Retry when it finishes. If no command is running, remove ${lockFile} and retry.`, lockFile, "busy");
140
162
  await new Promise((resolve) => setTimeout(resolve, 25));
141
163
  }
142
164
  try {
@@ -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 {};