@miosa/sdk 3.1.0 → 3.2.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/dist/index.d.ts CHANGED
@@ -7432,14 +7432,27 @@ declare class Sandbox {
7432
7432
  * Returns `true` once the sandbox is ready, `false` on `event: timeout`
7433
7433
  * or when the local timeout elapses before ready.
7434
7434
  *
7435
+ * Throws {@link MiosaError} with code `SANDBOX_BOOT_FAILED` as soon as the
7436
+ * sandbox is observed in a terminal failure state (`error` or `destroyed`)
7437
+ * while waiting, instead of silently exhausting the timeout and returning
7438
+ * `false` — a permanent boot failure and "still booting, keep waiting" must
7439
+ * never look the same to the caller. The readiness SSE stream itself has no
7440
+ * dedicated failure event today (the server only ever emits
7441
+ * `ready`/`status`/`timeout`), so on `event: timeout` this makes one
7442
+ * authoritative {@link readiness} check before giving up, to catch a
7443
+ * failure that landed right at the boundary.
7444
+ *
7435
7445
  * If the SSE endpoint returns 404 (server pre-dates the streaming
7436
- * endpoint) this transparently falls back to polling
7437
- * {@link readiness} every 10 ms until ready or timeout.
7446
+ * endpoint) this transparently falls back to polling {@link readiness}
7447
+ * every 10 ms until ready, timeout, or terminal failure.
7438
7448
  */
7439
7449
  waitUntilReady(options?: {
7440
7450
  timeout?: number;
7441
7451
  stream?: boolean;
7442
7452
  }): Promise<boolean>;
7453
+ private bootFailedError;
7454
+ /** Best-effort final check so an SSE `event: timeout` does not mask a boot failure that just landed. */
7455
+ private throwIfTerminallyFailed;
7443
7456
  /**
7444
7457
  * Readiness answers from the server; `assertRunning` reads the local
7445
7458
  * snapshot. Leaving that snapshot behind meant a caller could await
package/dist/index.js CHANGED
@@ -168,7 +168,7 @@ var TokenRefreshFailedError = class extends MiosaError {
168
168
  };
169
169
 
170
170
  // src/version.ts
171
- var SDK_VERSION = "3.1.0";
171
+ var SDK_VERSION = "3.2.0";
172
172
  var SDK_USER_AGENT = `@miosa/sdk/${SDK_VERSION}`;
173
173
 
174
174
  // src/http.ts
@@ -373,7 +373,7 @@ var HttpClient = class {
373
373
  async *streamFrames(path, options = {}) {
374
374
  const method = options.method ?? "GET";
375
375
  let headers = this.baseHeaders({
376
- Accept: "text/event-stream",
376
+ Accept: "text/event-stream, application/json, */*",
377
377
  ...options.headers
378
378
  });
379
379
  let body5 = null;
@@ -8459,6 +8459,9 @@ var SANDBOX_TIER_BY_CPU = {
8459
8459
  8: { size: "large", memoryMb: 16384 },
8460
8460
  16: { size: "xl", memoryMb: 32768 }
8461
8461
  };
8462
+ function isTerminalSandboxFailure(state) {
8463
+ return state === "error" || state === "destroyed";
8464
+ }
8462
8465
  var AGENT_WORKSPACE_TIMEOUT_SEC = 86400;
8463
8466
  var AGENT_WORKSPACE_IDLE_TIMEOUT_SEC = 1800;
8464
8467
  var AGENT_WORKSPACE_SNAPSHOT_EXPIRATION_DAYS = 30;
@@ -9432,18 +9435,32 @@ var Sandbox = class _Sandbox {
9432
9435
  * Returns `true` once the sandbox is ready, `false` on `event: timeout`
9433
9436
  * or when the local timeout elapses before ready.
9434
9437
  *
9438
+ * Throws {@link MiosaError} with code `SANDBOX_BOOT_FAILED` as soon as the
9439
+ * sandbox is observed in a terminal failure state (`error` or `destroyed`)
9440
+ * while waiting, instead of silently exhausting the timeout and returning
9441
+ * `false` — a permanent boot failure and "still booting, keep waiting" must
9442
+ * never look the same to the caller. The readiness SSE stream itself has no
9443
+ * dedicated failure event today (the server only ever emits
9444
+ * `ready`/`status`/`timeout`), so on `event: timeout` this makes one
9445
+ * authoritative {@link readiness} check before giving up, to catch a
9446
+ * failure that landed right at the boundary.
9447
+ *
9435
9448
  * If the SSE endpoint returns 404 (server pre-dates the streaming
9436
- * endpoint) this transparently falls back to polling
9437
- * {@link readiness} every 10 ms until ready or timeout.
9449
+ * endpoint) this transparently falls back to polling {@link readiness}
9450
+ * every 10 ms until ready, timeout, or terminal failure.
9438
9451
  */
9439
9452
  async waitUntilReady(options = {}) {
9440
9453
  const timeout = options.timeout ?? 30;
9441
9454
  const stream = options.stream ?? true;
9442
9455
  if (stream) {
9443
9456
  const sseResult = await this.tryReadinessStream(timeout);
9444
- if (sseResult !== null) {
9445
- if (sseResult) await this.adoptReadyState();
9446
- return sseResult;
9457
+ if (sseResult === true) {
9458
+ await this.adoptReadyState();
9459
+ return true;
9460
+ }
9461
+ if (sseResult === false) {
9462
+ await this.throwIfTerminallyFailed();
9463
+ return false;
9447
9464
  }
9448
9465
  }
9449
9466
  const deadlineMs = Date.now() + timeout * 1e3;
@@ -9454,12 +9471,39 @@ var Sandbox = class _Sandbox {
9454
9471
  await this.adoptReadyState();
9455
9472
  return true;
9456
9473
  }
9457
- } catch {
9474
+ if (isTerminalSandboxFailure(data.state)) {
9475
+ throw this.bootFailedError(data.state);
9476
+ }
9477
+ } catch (err) {
9478
+ if (err instanceof MiosaError && err.code === "SANDBOX_BOOT_FAILED") {
9479
+ throw err;
9480
+ }
9458
9481
  }
9459
9482
  await new Promise((resolve) => setTimeout(resolve, 10));
9460
9483
  }
9461
9484
  return false;
9462
9485
  }
9486
+ bootFailedError(state) {
9487
+ return new MiosaError(
9488
+ `Sandbox ${this.id} entered terminal state '${state}' while waiting for readiness`,
9489
+ 502,
9490
+ "SANDBOX_BOOT_FAILED",
9491
+ { sandbox_id: this.id, state }
9492
+ );
9493
+ }
9494
+ /** Best-effort final check so an SSE `event: timeout` does not mask a boot failure that just landed. */
9495
+ async throwIfTerminallyFailed() {
9496
+ try {
9497
+ const data = await this.readiness();
9498
+ if (isTerminalSandboxFailure(data?.state)) {
9499
+ throw this.bootFailedError(data.state);
9500
+ }
9501
+ } catch (err) {
9502
+ if (err instanceof MiosaError && err.code === "SANDBOX_BOOT_FAILED") {
9503
+ throw err;
9504
+ }
9505
+ }
9506
+ }
9463
9507
  /**
9464
9508
  * Readiness answers from the server; `assertRunning` reads the local
9465
9509
  * snapshot. Leaving that snapshot behind meant a caller could await
@@ -9486,7 +9530,11 @@ var Sandbox = class _Sandbox {
9486
9530
  try {
9487
9531
  const headers = {
9488
9532
  Authorization: `Bearer ${this.http.apiKey}`,
9489
- Accept: "text/event-stream",
9533
+ // Combined defensively: a bare `text/event-stream` Accept header 406s
9534
+ // on some `:accepts`-guarded routes (seen on the databases stream
9535
+ // route). Offering json/`*/*` as fallbacks is free when SSE is
9536
+ // actually returned.
9537
+ Accept: "text/event-stream, application/json, */*",
9490
9538
  "User-Agent": SDK_USER_AGENT
9491
9539
  };
9492
9540
  const response = await fetch(