@miosa/sdk 3.5.0 → 3.7.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/README.md CHANGED
@@ -53,6 +53,7 @@ await sbx.pause();
53
53
  | Resource | Description |
54
54
  |---|---|
55
55
  | `miosa.sandboxes` | Lightweight code-execution VMs — exec, files, snapshots, previews |
56
+ | `miosa.runtimes` | Selectable sandbox runtimes (firecracker / soma / auto) with gate state |
56
57
  | `miosa.computers` | Full Linux desktop VMs with desktop control for agents |
57
58
  | `miosa.deployments` | Versioned production releases with rollback |
58
59
  | `miosa.appDocuments` | Durable generated apps with exact-version review approvals and immutable publication bindings |
@@ -276,6 +277,37 @@ await sbx.pause();
276
277
  await sbx.resume();
277
278
  ```
278
279
 
280
+ ### Selecting a runtime
281
+
282
+ A runtime is the microVM engine behind a sandbox. Pass `runtime` on create to
283
+ choose one; the SDK sends it as the wire field `runtime_profile`:
284
+
285
+ ```ts
286
+ // Full microVM (the default). Sent on the wire as "standard".
287
+ const fx = await miosa.sandboxes.create({ runtime: "firecracker" });
288
+
289
+ // Fastest start for supported Linux images.
290
+ const soma = await miosa.sandboxes.create({ runtime: "soma" });
291
+
292
+ // Let the platform pick.
293
+ const auto = await miosa.sandboxes.create({ runtime: "auto" });
294
+ ```
295
+
296
+ Omitting `runtime` leaves `runtime_profile` off the request, so the server
297
+ applies its own default (Firecracker). List what your org can use and each
298
+ runtime's capabilities:
299
+
300
+ ```ts
301
+ const runtimes = await miosa.runtimes.list();
302
+ for (const rt of runtimes) {
303
+ console.log(rt.id, rt.label, rt.available ? "available" : rt.unavailable_reason);
304
+ }
305
+ ```
306
+
307
+ `available` is the live gate for your org; when it is false,
308
+ `unavailable_reason` carries a machine code (`GLOBAL_GATE_CLOSED` or
309
+ `ORG_RESTRICTED`).
310
+
279
311
  ### Cancelling sandbox commands
280
312
 
281
313
  Pass an `AbortSignal` to `sandbox.exec.run(command, { signal, timeoutSec })` or `sandbox.exec.stream(command, { signal, timeoutSec })`.
@@ -293,6 +325,61 @@ Cancellation requires the server's request-owned streaming implementation and th
293
325
  If deletion is still in progress, the handle reports `destroying` and exposes `sandbox.data.operation_id` when supplied by the server.
294
326
  Use `sandbox.refresh()` to verify completion; an acknowledgement alone does not prove resource cleanup.
295
327
 
328
+ ## Browser automation with CDP
329
+
330
+ A sandbox browser speaks the Chrome DevTools Protocol. Mint a scoped, expiring,
331
+ revocable grant with `miosa.sandboxes.browserCdpUrl(id)`. Pass
332
+ `{ ttlSeconds }` (60-604800) to request a lifetime:
333
+
334
+ ```ts
335
+ const grant = await miosa.sandboxes.browserCdpUrl(sbx.id, { ttlSeconds: 3600 });
336
+ console.log(grant.cdp_host_http_url); // https://cdp-<id8>-<token>.sandbox.miosa.ai
337
+ ```
338
+
339
+ The grant returns every endpoint a CDP client needs:
340
+
341
+ | Field | What it is |
342
+ |---|---|
343
+ | `cdp_url` | `wss://` CDP endpoint for header/session auth |
344
+ | `cdp_ws_url` | `wss://` CDP endpoint carrying the grant token in the path |
345
+ | `cdp_http_url` | `https://` CDP endpoint carrying the grant token in the path |
346
+ | `cdp_host` | Header-auth CDP host (`cdp-<id8>-<token>.sandbox.miosa.ai`) |
347
+ | `cdp_host_http_url` | `https://` host form; answers `/json`, `/json/version`, `/json/list`, `/json/new` with `webSocketDebuggerUrl` rewritten to the same host's `/devtools/*` sockets |
348
+ | `cdp_host_ws_url` | `wss://` host form; serves the `/devtools/<browser\|page>/<id>` sockets |
349
+ | `cdp_token_id` / `cdp_expires_at` / `epoch` | Grant id, ISO-8601 expiry and generation |
350
+ | `cdp_debugger_address` | Optional `host:port` for Selenium's `debuggerAddress`. This endpoint does not return it - it appears on the browser-start payload - so it may be absent |
351
+
352
+ The SDK only mints the grant - it never starts or proxies a browser. Run a
353
+ CDP-speaking browser inside the sandbox, then choose whichever endpoint your
354
+ client understands. The path-token URLs (`cdp_ws_url`, `cdp_http_url`) are for
355
+ clients that cannot set headers; `cdp_url` is the header-auth `wss://` form.
356
+
357
+ Point Selenium at the debugger address. Use the `cdp_debugger_address` from the
358
+ browser-start payload when present, or `127.0.0.1:9222` when you forward the
359
+ port with the MIOSA CLI:
360
+
361
+ ```py
362
+ # Selenium - 127.0.0.1:9222 after `miosa sandboxes forward <id> 9222`, or the
363
+ # cdp_debugger_address supplied by the browser-start payload.
364
+ from selenium import webdriver
365
+ from selenium.webdriver.chrome.options import Options
366
+
367
+ options = Options()
368
+ options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
369
+ driver = webdriver.Chrome(options=options)
370
+ driver.get("https://example.com")
371
+ ```
372
+
373
+ Point chromedp (Go) at the header-auth host as its base URL:
374
+
375
+ ```go
376
+ // chromedp
377
+ allocCtx, cancel := chromedp.NewRemoteAllocator(ctx, grant.cdp_host_http_url)
378
+ defer cancel()
379
+ browserCtx, cancel := chromedp.NewContext(allocCtx)
380
+ defer cancel()
381
+ ```
382
+
296
383
  ## Publish from sandbox
297
384
 
298
385
  Preview is mutable; publish creates a durable deployment version. Static output
@@ -398,6 +485,99 @@ console.log(rotated.viewer_password);
398
485
  await computer.destroy();
399
486
  ```
400
487
 
488
+ ## Computer use
489
+
490
+ Drive a computer by action name. The names are the members of Anthropic's `computer_toolset_20260801`, and every result is typed.
491
+
492
+ ```ts
493
+ const shot = await computer.act("screenshot"); // imageBase64, width, height
494
+ const at = await computer.act("cursor_position"); // x, y
495
+ await computer.act("left_click", { coordinate: [512, 384] });
496
+ await computer.act("key", { text: "ctrl+s" });
497
+
498
+ const view = await computer.look(); // screenshot and accessibility tree in one call
499
+ await computer.waitForDesktop(); // ready and answering
500
+ await computer.waitUntilIdle(); // screen stopped changing
501
+ const viewer = await computer.viewerUrl({ ttlSeconds: 3600 }); // { url, expiresAt, ... }
502
+ ```
503
+
504
+ The rest of the desktop is on `computer.desktop`: `hotkey`, `keyDown`, `keyUp`, `mouseDown`, `mouseUp`, `getClipboard`, `setClipboard`, `screenSize`, `accessibilityTree`, `environment`, `setWallpaper`, `screenshotRegion` and window calls (`windowSize`, `resizeWindow`, `moveWindow`, `maximizeWindow`, `minimizeWindow`, `closeWindow`).
505
+
506
+ `computer` and `sandbox` implement `Symbol.asyncDispose`, so `await using computer = await miosa.computers.create(...)` destroys it when the scope ends (TypeScript 5.2 or newer; Node 18.18 or newer).
507
+
508
+ ### Let Claude drive it
509
+
510
+ ```ts
511
+ import { miosaComputerToolset } from "@miosa/sdk/computer-use";
512
+
513
+ const toolset = miosaComputerToolset(computer, {
514
+ confirm: async ({ member, input }) => member !== "type" || askHuman(input), // required
515
+ });
516
+ // tools: [toolset] in anthropic.beta.messages.toolRunner(...), or toolset.toJSON() and toolset.toolResult(block) in your own loop.
517
+ ```
518
+
519
+ `@miosa/sdk/computer-use` subclasses Anthropic's `BetaAbstractComputerToolset20260801`, so the batch rules (stop at the first failure, `Not executed: an earlier computer action in this turn failed.` for the rest, `toolset_name` on every result) come from Anthropic's runner.
520
+ It needs the optional peer `@anthropic-ai/sdk` 0.133 or newer.
521
+ `confirm` is required because the toolset can type and press keys; the alternative is to switch `type`, `key` and `hold_key` off in `configs`.
522
+ `zoom` is a region screenshot.
523
+ `triple_click` is off by default because the desktop has no triple-click route; `emulateTripleClick: true` sends a click and then a double-click.
524
+ Screens are sent at their native size, so pick a 1024x768 or 1280x720 computer.
525
+ For older models use `miosaComputerToolLegacy(computer, { version, displayWidthPx, displayHeightPx, confirm })`.
526
+
527
+ See `examples/computer-use-claude.ts`.
528
+
529
+ ## End-user tokens (platform builders)
530
+
531
+ `miosa.tokens.createScoped()` is the path for a platform that serves many customers.
532
+ Your server mints a short-lived token for one end user and one workspace, and the browser holds only that token.
533
+ It carries the scopes you ask for and never more than the minting key holds.
534
+
535
+ ```ts
536
+ const { token, expires_at } = await miosa.tokens.createScoped({
537
+ userId: "end-user-123",
538
+ workspaceId: "ws_abc",
539
+ scopes: ["sandboxes:create", "sandboxes:read"],
540
+ expiresInSeconds: 3600,
541
+ });
542
+ // give `token` to the browser: new Miosa({ apiKey: token })
543
+ ```
544
+
545
+ See `sdks/docs/guides/build-a-multi-tenant-platform.md` for the whole flow.
546
+
547
+ ## Helpers
548
+
549
+ `@miosa/sdk/helpers` puts the calls an agent loop reaches for in one import, keyed by computer id.
550
+
551
+ | Helper | Does |
552
+ |---|---|
553
+ | `waitUntilReady(miosa, id)` | poll until the computer is `active` or `running` |
554
+ | `waitForDesktop(miosa, id)` | ready, and the desktop answers |
555
+ | `waitUntilIdle(miosa, id)` | the screen stopped changing |
556
+ | `waitForPrompt(miosa, runId)` | wait for an agent run to finish |
557
+ | `streamPrompt(miosa, runId)` | follow an agent run's activity |
558
+ | `streamEvents(miosa, id, { subscribe })` | follow window, file, process, clipboard and idle events |
559
+ | `streamCommand(miosa, id, command)` | run a command and follow its output |
560
+ | `execCommand(miosa, id, command)` | run a command and get the result |
561
+ | `readText` / `writeText` | UTF-8 files |
562
+ | `stopAndRemove(miosa, id)` | stop, then destroy; safe to call twice |
563
+
564
+ Timeouts raise a `MiosaError` with a stable code (`COMPUTER_READY_TIMEOUT`, `DESKTOP_READY_TIMEOUT`, `DESKTOP_IDLE_TIMEOUT`) and `retryable: true`.
565
+
566
+ ## Fail fast
567
+
568
+ Pass `failFast: true` to `sandboxes.create`, `fork`, `resume`, `computers.create` or `computer.start` to shed load instead of waiting for capacity.
569
+ When no ready machine is free the server answers `503 no_ready_machine` in about 1.5 seconds, and the SDK raises `NoReadyMachineError`.
570
+ A fail-fast request is never retried by the client, because the refusal is the point.
571
+
572
+ ```ts
573
+ try {
574
+ const sbx = await miosa.sandboxes.create({ failFast: true, size: "large" });
575
+ } catch (error) {
576
+ if (error instanceof NoReadyMachineError) return fallback(); // retryAfterMs is the server's hint
577
+ throw error;
578
+ }
579
+ ```
580
+
401
581
  ## White-label / multi-tenant
402
582
 
403
583
  ```ts
@@ -0,0 +1,463 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // src/errors.ts
9
+ function defaultRetryable(status) {
10
+ return status === 408 || status === 429 || status >= 500;
11
+ }
12
+ var MiosaError = class _MiosaError extends Error {
13
+ status;
14
+ code;
15
+ details;
16
+ requestId;
17
+ retryable;
18
+ /**
19
+ * Server-supplied retry hint in milliseconds, taken from the canonical
20
+ * error shape's `retry_after_ms` (nested under `error` or top-level) or,
21
+ * failing that, the HTTP `Retry-After` header. `undefined` when the
22
+ * response carried neither, in which case a caller should fall back to
23
+ * its own backoff policy.
24
+ */
25
+ retryAfterMs;
26
+ constructor(message, status, code, details, requestId, retryable = defaultRetryable(status), retryAfterMs) {
27
+ super(message);
28
+ this.name = "MiosaError";
29
+ this.status = status;
30
+ this.code = code;
31
+ this.details = details;
32
+ this.requestId = requestId;
33
+ this.retryable = retryable;
34
+ this.retryAfterMs = retryAfterMs;
35
+ }
36
+ /**
37
+ * @param retryAfterHeaderMs The `Retry-After` header value, already
38
+ * converted to milliseconds by the caller. Used only when the body does
39
+ * not carry the more precise `retry_after_ms`.
40
+ */
41
+ static fromResponse(status, body, requestId, retryAfterHeaderMs) {
42
+ const nested = typeof body.error === "object" ? body.error : void 0;
43
+ const flatError = typeof body.error === "string" ? body.error : void 0;
44
+ const flatErrorIsCode = !!flatError && (/^[A-Z][A-Z0-9_]+$/.test(flatError) || /^[a-z][a-z0-9]*(_[a-z0-9]+)+$/.test(flatError));
45
+ const message = nested?.message ?? body.message ?? body.detail ?? body.reason ?? flatError ?? `HTTP ${status}`;
46
+ const code = nested?.code ?? body.code ?? (flatErrorIsCode ? flatError : "UNKNOWN_ERROR");
47
+ const details = nested?.details ?? body.details ?? (body.detail || body.reason ? { detail: body.detail, reason: body.reason } : void 0) ?? extraFields(body, nested);
48
+ requestId ??= nested?.request_id ?? body.request_id;
49
+ const retryable = nested?.retryable ?? body.retryable ?? RETRYABLE_BY_CODE[code] ?? defaultRetryable(status);
50
+ const retryAfterMs = nested?.retry_after_ms ?? body.retry_after_ms ?? retryAfterHeaderMs;
51
+ const connectError = connectErrorFromCode(code, message, status, details, requestId, retryable) ?? typedErrorFromCode(code, message, status, details, requestId, retryable, retryAfterMs);
52
+ const built = connectError ?? (status === 401 || status === 403 ? new AuthError(message, status, code, details, requestId, retryable) : status === 404 ? new NotFoundError(message, code, details, requestId, retryable) : status === 429 ? new RateLimitError(
53
+ message,
54
+ details,
55
+ requestId,
56
+ retryAfterMs === void 0 ? void 0 : retryAfterMs / 1e3,
57
+ retryable,
58
+ // Keep the server's own code (SERVICE_ACCOUNT_LIMIT, ...) when it sent one.
59
+ code === "UNKNOWN_ERROR" ? "RATE_LIMITED" : code
60
+ ) : status === 402 ? new InsufficientCreditsError(
61
+ message,
62
+ details,
63
+ requestId,
64
+ retryable,
65
+ code === "UNKNOWN_ERROR" ? "INSUFFICIENT_CREDITS" : code
66
+ ) : status >= 400 && status < 500 ? new ValidationError(message, status, code, details, requestId, retryable) : new _MiosaError(message, status, code, details, requestId, retryable));
67
+ built.retryAfterMs = retryAfterMs;
68
+ return built;
69
+ }
70
+ };
71
+ var ENVELOPE_KEYS = /* @__PURE__ */ new Set([
72
+ "error",
73
+ "message",
74
+ "code",
75
+ "detail",
76
+ "details",
77
+ "reason",
78
+ "request_id",
79
+ "retryable",
80
+ "retry_after_ms",
81
+ "ok",
82
+ "success",
83
+ "status"
84
+ ]);
85
+ var NESTED_KEYS = /* @__PURE__ */ new Set(["code", "message", "details", "retryable", "request_id", "retry_after_ms"]);
86
+ function extraFields(body, nested) {
87
+ const extras = {};
88
+ for (const [key, value] of Object.entries(body)) {
89
+ if (!ENVELOPE_KEYS.has(key)) extras[key] = value;
90
+ }
91
+ if (nested) {
92
+ for (const [key, value] of Object.entries(nested)) {
93
+ if (!NESTED_KEYS.has(key)) extras[key] = value;
94
+ }
95
+ }
96
+ return Object.keys(extras).length > 0 ? extras : void 0;
97
+ }
98
+ function connectErrorFromCode(code, message, status, details, requestId, retryable) {
99
+ switch (code) {
100
+ case "PROJECT_NOT_LINKED":
101
+ return new ProjectNotLinkedError(message, status, details, requestId, retryable);
102
+ case "SUBJECT_NOT_ALLOWED":
103
+ return new SubjectNotAllowedError(message, status, details, requestId, retryable);
104
+ case "SCOPE_NOT_ALLOWED":
105
+ return new ScopeNotAllowedError(message, status, details, requestId, retryable);
106
+ case "MANAGED_PROVIDER_BINDING_ONLY":
107
+ return new ManagedProviderBindingOnlyError(message, status, details, requestId, retryable);
108
+ case "INSTALLATION_REQUIRED":
109
+ return new InstallationRequiredError(message, status, details, requestId, retryable);
110
+ case "USER_AUTHORIZATION_REQUIRED":
111
+ return new UserAuthorizationRequiredError(message, status, details, requestId, retryable);
112
+ case "EGRESS_HOST_NOT_ALLOWED":
113
+ return new EgressHostNotAllowedError(message, status, details, requestId, retryable);
114
+ case "TOKEN_REFRESH_FAILED":
115
+ return new TokenRefreshFailedError(message, status, details, requestId, retryable);
116
+ default:
117
+ return void 0;
118
+ }
119
+ }
120
+ var AuthError = class extends MiosaError {
121
+ constructor(message, status = 401, code = "UNAUTHORIZED", details, requestId, retryable) {
122
+ super(message, status, code, details, requestId, retryable);
123
+ this.name = "AuthError";
124
+ }
125
+ };
126
+ var NotFoundError = class extends MiosaError {
127
+ constructor(message, code = "NOT_FOUND", details, requestId, retryable) {
128
+ super(message, 404, code, details, requestId, retryable);
129
+ this.name = "NotFoundError";
130
+ }
131
+ };
132
+ var RateLimitError = class extends MiosaError {
133
+ retryAfter;
134
+ constructor(message, details, requestId, retryAfter, retryable, code = "RATE_LIMITED") {
135
+ super(message, 429, code, details, requestId, retryable);
136
+ this.name = "RateLimitError";
137
+ this.retryAfter = retryAfter;
138
+ }
139
+ };
140
+ var InsufficientCreditsError = class extends MiosaError {
141
+ constructor(message, details, requestId, retryable, code = "INSUFFICIENT_CREDITS") {
142
+ super(message, 402, code, details, requestId, retryable);
143
+ this.name = "InsufficientCreditsError";
144
+ }
145
+ };
146
+ var ValidationError = class extends MiosaError {
147
+ constructor(message, status, code = "VALIDATION_ERROR", details, requestId, retryable) {
148
+ super(message, status, code, details, requestId, retryable);
149
+ this.name = "ValidationError";
150
+ }
151
+ };
152
+ var TimeoutError = class extends MiosaError {
153
+ constructor(message = "Request timed out") {
154
+ super(message, 408, "TIMEOUT", void 0, void 0, true);
155
+ this.name = "TimeoutError";
156
+ }
157
+ };
158
+ var NetworkError = class extends MiosaError {
159
+ cause;
160
+ constructor(message, cause) {
161
+ super(message, 0, "NETWORK_ERROR", void 0, void 0, true);
162
+ this.name = "NetworkError";
163
+ this.cause = cause;
164
+ }
165
+ };
166
+ var ProjectNotLinkedError = class extends MiosaError {
167
+ constructor(message, status = 403, details, requestId, retryable) {
168
+ super(message, status, "PROJECT_NOT_LINKED", details, requestId, retryable);
169
+ this.name = "ProjectNotLinkedError";
170
+ }
171
+ };
172
+ var SubjectNotAllowedError = class extends MiosaError {
173
+ constructor(message, status = 403, details, requestId, retryable) {
174
+ super(message, status, "SUBJECT_NOT_ALLOWED", details, requestId, retryable);
175
+ this.name = "SubjectNotAllowedError";
176
+ }
177
+ };
178
+ var ScopeNotAllowedError = class extends MiosaError {
179
+ constructor(message, status = 403, details, requestId, retryable) {
180
+ super(message, status, "SCOPE_NOT_ALLOWED", details, requestId, retryable);
181
+ this.name = "ScopeNotAllowedError";
182
+ }
183
+ };
184
+ var ManagedProviderBindingOnlyError = class extends MiosaError {
185
+ constructor(message, status = 403, details, requestId, retryable) {
186
+ super(message, status, "MANAGED_PROVIDER_BINDING_ONLY", details, requestId, retryable);
187
+ this.name = "ManagedProviderBindingOnlyError";
188
+ }
189
+ };
190
+ var InstallationRequiredError = class extends MiosaError {
191
+ constructor(message, status = 409, details, requestId, retryable) {
192
+ super(message, status, "INSTALLATION_REQUIRED", details, requestId, retryable);
193
+ this.name = "InstallationRequiredError";
194
+ }
195
+ };
196
+ var UserAuthorizationRequiredError = class extends MiosaError {
197
+ constructor(message, status = 403, details, requestId, retryable) {
198
+ super(message, status, "USER_AUTHORIZATION_REQUIRED", details, requestId, retryable);
199
+ this.name = "UserAuthorizationRequiredError";
200
+ }
201
+ };
202
+ var EgressHostNotAllowedError = class extends MiosaError {
203
+ constructor(message, status = 403, details, requestId, retryable) {
204
+ super(message, status, "EGRESS_HOST_NOT_ALLOWED", details, requestId, retryable);
205
+ this.name = "EgressHostNotAllowedError";
206
+ }
207
+ };
208
+ var TokenRefreshFailedError = class extends MiosaError {
209
+ constructor(message, status = 502, details, requestId, retryable) {
210
+ super(message, status, "TOKEN_REFRESH_FAILED", details, requestId, retryable);
211
+ this.name = "TokenRefreshFailedError";
212
+ }
213
+ };
214
+ var RETRYABLE_BY_CODE = {
215
+ SANDBOX_STARTING: true,
216
+ COMPUTER_STARTING: true,
217
+ ENVIRONMENT_SCRUB_FAILED: true,
218
+ CHAT_BUSY: true,
219
+ ENVIRONMENT_MEMORY_WITHHELD: false,
220
+ NO_AGENT_RUN: false,
221
+ MEMBER_LIMIT_REACHED: false,
222
+ NO_READY_MACHINE: true,
223
+ no_ready_machine: true
224
+ };
225
+ var NoReadyMachineError = class extends MiosaError {
226
+ constructor(message, status = 503, details, requestId, retryable = true, retryAfterMs) {
227
+ super(message, status, "no_ready_machine", details, requestId, retryable, retryAfterMs);
228
+ this.name = "NoReadyMachineError";
229
+ }
230
+ };
231
+ var InvalidIdError = class extends ValidationError {
232
+ constructor(message, status = 400, details, requestId, retryable) {
233
+ super(message, status, "INVALID_ID", details, requestId, retryable);
234
+ this.name = "InvalidIdError";
235
+ }
236
+ };
237
+ var OwnCredentialsRequiredError = class extends ValidationError {
238
+ constructor(message, status = 422, details, requestId, retryable) {
239
+ super(message, status, "OWN_CREDENTIALS_REQUIRED", details, requestId, retryable);
240
+ this.name = "OwnCredentialsRequiredError";
241
+ }
242
+ };
243
+ var EnvironmentNotFoundError = class extends NotFoundError {
244
+ constructor(message, details, requestId, retryable) {
245
+ super(message, "ENVIRONMENT_NOT_FOUND", details, requestId, retryable);
246
+ this.name = "EnvironmentNotFoundError";
247
+ }
248
+ };
249
+ var UnknownEnvironmentError = class extends ValidationError {
250
+ constructor(message, status = 422, details, requestId, retryable) {
251
+ super(message, status, "ENVIRONMENT_NOT_FOUND", details, requestId, retryable);
252
+ this.name = "UnknownEnvironmentError";
253
+ }
254
+ };
255
+ var EnvironmentNameTakenError = class extends ValidationError {
256
+ constructor(message, status = 409, details, requestId, retryable) {
257
+ super(message, status, "ENVIRONMENT_NAME_TAKEN", details, requestId, retryable);
258
+ this.name = "EnvironmentNameTakenError";
259
+ }
260
+ };
261
+ var EnvironmentIsDefaultError = class extends ValidationError {
262
+ constructor(message, status = 409, details, requestId, retryable) {
263
+ super(message, status, "ENVIRONMENT_IS_DEFAULT", details, requestId, retryable);
264
+ this.name = "EnvironmentIsDefaultError";
265
+ }
266
+ };
267
+ var EnvironmentScrubFailedError = class extends ValidationError {
268
+ constructor(message, status = 409, details, requestId, retryable = true) {
269
+ super(message, status, "ENVIRONMENT_SCRUB_FAILED", details, requestId, retryable);
270
+ this.name = "EnvironmentScrubFailedError";
271
+ }
272
+ };
273
+ var EnvironmentMemoryWithheldError = class extends ValidationError {
274
+ constructor(message, status = 409, details, requestId, retryable = false) {
275
+ super(message, status, "ENVIRONMENT_MEMORY_WITHHELD", details, requestId, retryable);
276
+ this.name = "EnvironmentMemoryWithheldError";
277
+ }
278
+ /** `details.reasons`: why the memory was withheld. Empty when absent. */
279
+ get reasons() {
280
+ const reasons = this.details?.reasons;
281
+ return Array.isArray(reasons) ? reasons.filter((r) => typeof r === "string") : [];
282
+ }
283
+ };
284
+ var MachineKeyScopeError = class extends AuthError {
285
+ constructor(message, status = 403, details, requestId, retryable) {
286
+ super(message, status, "MACHINE_KEY_SCOPE", details, requestId, retryable);
287
+ this.name = "MachineKeyScopeError";
288
+ }
289
+ };
290
+ var MachineStartingError = class extends ValidationError {
291
+ constructor(message, status = 409, code = "SANDBOX_STARTING", details, requestId, retryable = true) {
292
+ super(message, status, code, details, requestId, retryable);
293
+ this.name = "MachineStartingError";
294
+ }
295
+ };
296
+ var SandboxStartingError = class extends MachineStartingError {
297
+ constructor(message, status = 409, details, requestId, retryable = true) {
298
+ super(message, status, "SANDBOX_STARTING", details, requestId, retryable);
299
+ this.name = "SandboxStartingError";
300
+ }
301
+ };
302
+ var ComputerStartingError = class extends MachineStartingError {
303
+ constructor(message, status = 409, details, requestId, retryable = true) {
304
+ super(message, status, "COMPUTER_STARTING", details, requestId, retryable);
305
+ this.name = "ComputerStartingError";
306
+ }
307
+ };
308
+ var CreditRequiredError = class extends InsufficientCreditsError {
309
+ constructor(message, details, requestId, retryable) {
310
+ super(message, details, requestId, retryable, "CREDIT_REQUIRED");
311
+ this.name = "CreditRequiredError";
312
+ }
313
+ };
314
+ var TeamMemberCapReachedError = class extends InsufficientCreditsError {
315
+ constructor(message, details, requestId, retryable) {
316
+ super(message, details, requestId, retryable, "TEAM_MEMBER_CAP_REACHED");
317
+ this.name = "TeamMemberCapReachedError";
318
+ }
319
+ };
320
+ var MemberLimitReachedError = class extends RateLimitError {
321
+ constructor(message, details, requestId, retryAfter, retryable = false) {
322
+ super(message, details, requestId, retryAfter, retryable, "MEMBER_LIMIT_REACHED");
323
+ this.name = "MemberLimitReachedError";
324
+ }
325
+ };
326
+ var BillToLockedError = class extends AuthError {
327
+ constructor(message, status = 403, details, requestId, retryable) {
328
+ super(message, status, "BILL_TO_LOCKED", details, requestId, retryable);
329
+ this.name = "BillToLockedError";
330
+ }
331
+ };
332
+ var BillToForbiddenError = class extends AuthError {
333
+ constructor(message, status = 403, details, requestId, retryable) {
334
+ super(message, status, "BILL_TO_FORBIDDEN", details, requestId, retryable);
335
+ this.name = "BillToForbiddenError";
336
+ }
337
+ };
338
+ var BillToSuspendedError = class extends AuthError {
339
+ constructor(message, status = 403, details, requestId, retryable) {
340
+ super(message, status, "BILL_TO_SUSPENDED", details, requestId, retryable);
341
+ this.name = "BillToSuspendedError";
342
+ }
343
+ };
344
+ var OrgNotFoundError = class extends NotFoundError {
345
+ constructor(message, details, requestId, retryable) {
346
+ super(message, "ORG_NOT_FOUND", details, requestId, retryable);
347
+ this.name = "OrgNotFoundError";
348
+ }
349
+ };
350
+ var AmbiguousOrgError = class extends ValidationError {
351
+ constructor(message, status = 409, details, requestId, retryable) {
352
+ super(message, status, "AMBIGUOUS_ORG", details, requestId, retryable);
353
+ this.name = "AmbiguousOrgError";
354
+ }
355
+ };
356
+ var SnapshotInUseError = class extends ValidationError {
357
+ constructor(message, status = 409, details, requestId, retryable) {
358
+ super(message, status, "SNAPSHOT_IN_USE", details, requestId, retryable);
359
+ this.name = "SnapshotInUseError";
360
+ }
361
+ /** `details.dependents`: every thing that still needs the snapshot's bytes. */
362
+ get dependents() {
363
+ const dependents = this.details?.dependents;
364
+ return Array.isArray(dependents) ? dependents : [];
365
+ }
366
+ };
367
+ var RunSessionNotResumableError = class extends ValidationError {
368
+ constructor(message, status = 409, details, requestId, retryable) {
369
+ super(message, status, "RUN_SESSION_NOT_RESUMABLE", details, requestId, retryable);
370
+ this.name = "RunSessionNotResumableError";
371
+ }
372
+ get reason() {
373
+ const reason = this.details?.reason;
374
+ return typeof reason === "string" ? reason : void 0;
375
+ }
376
+ };
377
+ var ChatBusyError = class extends ValidationError {
378
+ constructor(message, status = 409, details, requestId, retryable = true) {
379
+ super(message, status, "CHAT_BUSY", details, requestId, retryable);
380
+ this.name = "ChatBusyError";
381
+ }
382
+ };
383
+ var NoAgentRunError = class extends ValidationError {
384
+ constructor(message, status = 409, details, requestId, retryable = false) {
385
+ super(message, status, "NO_AGENT_RUN", details, requestId, retryable);
386
+ this.name = "NoAgentRunError";
387
+ }
388
+ };
389
+ var InvalidSetupFileError = class extends ValidationError {
390
+ constructor(message, status = 422, details, requestId, retryable) {
391
+ super(message, status, "INVALID_SETUP_FILE", details, requestId, retryable);
392
+ this.name = "InvalidSetupFileError";
393
+ }
394
+ get reason() {
395
+ const reason = this.details?.reason;
396
+ return typeof reason === "string" ? reason : void 0;
397
+ }
398
+ };
399
+ function typedErrorFromCode(code, message, status, details, requestId, retryable, retryAfterMs) {
400
+ switch (code) {
401
+ case "no_ready_machine":
402
+ case "NO_READY_MACHINE":
403
+ return new NoReadyMachineError(message, status, details, requestId, retryable, retryAfterMs);
404
+ case "INVALID_ID":
405
+ return new InvalidIdError(message, status, details, requestId, retryable);
406
+ case "OWN_CREDENTIALS_REQUIRED":
407
+ return new OwnCredentialsRequiredError(message, status, details, requestId, retryable);
408
+ case "ENVIRONMENT_NOT_FOUND":
409
+ return status === 404 ? new EnvironmentNotFoundError(message, details, requestId, retryable) : new UnknownEnvironmentError(message, status, details, requestId, retryable);
410
+ case "ENVIRONMENT_NAME_TAKEN":
411
+ return new EnvironmentNameTakenError(message, status, details, requestId, retryable);
412
+ case "ENVIRONMENT_IS_DEFAULT":
413
+ return new EnvironmentIsDefaultError(message, status, details, requestId, retryable);
414
+ case "ENVIRONMENT_SCRUB_FAILED":
415
+ return new EnvironmentScrubFailedError(message, status, details, requestId, retryable);
416
+ case "ENVIRONMENT_MEMORY_WITHHELD":
417
+ return new EnvironmentMemoryWithheldError(message, status, details, requestId, retryable);
418
+ case "MACHINE_KEY_SCOPE":
419
+ return new MachineKeyScopeError(message, status, details, requestId, retryable);
420
+ case "SANDBOX_STARTING":
421
+ return new SandboxStartingError(message, status, details, requestId, retryable);
422
+ case "COMPUTER_STARTING":
423
+ return new ComputerStartingError(message, status, details, requestId, retryable);
424
+ case "CREDIT_REQUIRED":
425
+ return new CreditRequiredError(message, details, requestId, retryable);
426
+ case "TEAM_MEMBER_CAP_REACHED":
427
+ return new TeamMemberCapReachedError(message, details, requestId, retryable);
428
+ case "MEMBER_LIMIT_REACHED":
429
+ return new MemberLimitReachedError(
430
+ message,
431
+ details,
432
+ requestId,
433
+ retryAfterMs === void 0 ? void 0 : retryAfterMs / 1e3,
434
+ retryable
435
+ );
436
+ case "BILL_TO_LOCKED":
437
+ return new BillToLockedError(message, status, details, requestId, retryable);
438
+ case "BILL_TO_FORBIDDEN":
439
+ return new BillToForbiddenError(message, status, details, requestId, retryable);
440
+ case "BILL_TO_SUSPENDED":
441
+ return new BillToSuspendedError(message, status, details, requestId, retryable);
442
+ case "ORG_NOT_FOUND":
443
+ return new OrgNotFoundError(message, details, requestId, retryable);
444
+ case "AMBIGUOUS_ORG":
445
+ return new AmbiguousOrgError(message, status, details, requestId, retryable);
446
+ case "SNAPSHOT_IN_USE":
447
+ return new SnapshotInUseError(message, status, details, requestId, retryable);
448
+ case "RUN_SESSION_NOT_RESUMABLE":
449
+ return new RunSessionNotResumableError(message, status, details, requestId, retryable);
450
+ case "CHAT_BUSY":
451
+ return new ChatBusyError(message, status, details, requestId, retryable);
452
+ case "NO_AGENT_RUN":
453
+ return new NoAgentRunError(message, status, details, requestId, retryable);
454
+ case "INVALID_SETUP_FILE":
455
+ return new InvalidSetupFileError(message, status, details, requestId, retryable);
456
+ default:
457
+ return void 0;
458
+ }
459
+ }
460
+
461
+ export { AmbiguousOrgError, AuthError, BillToForbiddenError, BillToLockedError, BillToSuspendedError, ChatBusyError, ComputerStartingError, CreditRequiredError, EgressHostNotAllowedError, EnvironmentIsDefaultError, EnvironmentMemoryWithheldError, EnvironmentNameTakenError, EnvironmentNotFoundError, EnvironmentScrubFailedError, InstallationRequiredError, InsufficientCreditsError, InvalidIdError, InvalidSetupFileError, MachineKeyScopeError, MachineStartingError, ManagedProviderBindingOnlyError, MemberLimitReachedError, MiosaError, NetworkError, NoAgentRunError, NoReadyMachineError, NotFoundError, OrgNotFoundError, OwnCredentialsRequiredError, ProjectNotLinkedError, RateLimitError, RunSessionNotResumableError, SandboxStartingError, ScopeNotAllowedError, SnapshotInUseError, SubjectNotAllowedError, TeamMemberCapReachedError, TimeoutError, TokenRefreshFailedError, UnknownEnvironmentError, UserAuthorizationRequiredError, ValidationError, __require };
462
+ //# sourceMappingURL=chunk-BMWUKYWU.js.map
463
+ //# sourceMappingURL=chunk-BMWUKYWU.js.map