veryfront 0.1.274 → 0.1.276

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.
@@ -18,6 +18,7 @@ import {
18
18
  } from "../errors/index.js";
19
19
  import { getVeryfrontCloudAuthToken } from "../platform/cloud/resolver.js";
20
20
  import { getHostEnv } from "../platform/compat/process.js";
21
+ import { LazySandbox, type LazySandboxOptions } from "./lazy-sandbox.js";
21
22
 
22
23
  /** Options for command execution: working directory, timeout, and environment variables. */
23
24
  export interface ExecOptions {
@@ -39,6 +40,25 @@ export interface SandboxOptions {
39
40
  projectId?: string;
40
41
  }
41
42
 
43
+ export function resolveSandboxApiUrl(options: SandboxOptions = {}): string {
44
+ return options.apiUrl ||
45
+ getHostEnv("VERYFRONT_API_URL") ||
46
+ "https://api.veryfront.com";
47
+ }
48
+
49
+ export function resolveSandboxAuthToken(options: SandboxOptions = {}): string {
50
+ const authToken = options.authToken?.trim() || getVeryfrontCloudAuthToken();
51
+ if (authToken) return authToken;
52
+
53
+ throw toError(
54
+ createError({
55
+ type: "config",
56
+ message:
57
+ "Sandbox auth not configured. Set VERYFRONT_API_TOKEN, provide request-scoped Veryfront credentials, or pass authToken explicitly.",
58
+ }),
59
+ );
60
+ }
61
+
42
62
  /** Result of a command execution: stdout, stderr, and exit code. */
43
63
  export interface ExecResult {
44
64
  stdout: string;
@@ -117,22 +137,11 @@ export class Sandbox {
117
137
  ) {}
118
138
 
119
139
  private static resolveApiUrl(options: SandboxOptions = {}): string {
120
- return options.apiUrl ||
121
- getHostEnv("VERYFRONT_API_URL") ||
122
- "https://api.veryfront.com";
140
+ return resolveSandboxApiUrl(options);
123
141
  }
124
142
 
125
143
  private static resolveAuthToken(options: SandboxOptions = {}): string {
126
- const authToken = options.authToken?.trim() || getVeryfrontCloudAuthToken();
127
- if (authToken) return authToken;
128
-
129
- throw toError(
130
- createError({
131
- type: "config",
132
- message:
133
- "Sandbox auth not configured. Set VERYFRONT_API_TOKEN, provide request-scoped Veryfront credentials, or pass authToken explicitly.",
134
- }),
135
- );
144
+ return resolveSandboxAuthToken(options);
136
145
  }
137
146
 
138
147
  /** Create a new sandbox session. Claims a warm pod or creates a new one. */
@@ -232,26 +241,12 @@ export class Sandbox {
232
241
  maxWaitMs = 60_000,
233
242
  pollIntervalMs = 2_000,
234
243
  ): Promise<void> {
235
- const start = Date.now();
236
- while (Date.now() - start < maxWaitMs) {
237
- // no cleanup needed: one-shot
238
- await new Promise((r) => dntShim.setTimeout(r, pollIntervalMs));
239
-
240
- const res = await fetch(`${apiUrl}/sandbox-sessions/${id}`, {
241
- headers: { Authorization: `Bearer ${authToken}` },
242
- });
244
+ await waitForSandboxReady({ apiUrl, id, authToken, maxWaitMs, pollIntervalMs });
245
+ }
243
246
 
244
- if (res.ok) {
245
- const data = await res.json();
246
- if (data.status === "running") return;
247
- if (data.status === "error" || data.status === "deleting") {
248
- throw INITIALIZATION_ERROR.create({
249
- detail: `Sandbox failed to start: status=${data.status}`,
250
- });
251
- }
252
- }
253
- }
254
- throw TIMEOUT_ERROR.create({ detail: "Sandbox did not become ready within timeout" });
247
+ /** Create a lazily-provisioned sandbox session with automatic heartbeats. */
248
+ static createLazy(options: LazySandboxOptions = {}): LazySandbox {
249
+ return new LazySandbox(options);
255
250
  }
256
251
 
257
252
  /** Execute a bash command in the sandbox and return buffered result. */
@@ -486,3 +481,37 @@ export class Sandbox {
486
481
  return this.endpoint;
487
482
  }
488
483
  }
484
+
485
+ export async function waitForSandboxReady(input: {
486
+ apiUrl: string;
487
+ id: string;
488
+ authToken: string;
489
+ maxWaitMs?: number;
490
+ pollIntervalMs?: number;
491
+ }): Promise<void> {
492
+ const maxWaitMs = input.maxWaitMs ?? 60_000;
493
+ const pollIntervalMs = input.pollIntervalMs ?? 2_000;
494
+ const start = Date.now();
495
+
496
+ while (Date.now() - start < maxWaitMs) {
497
+ await new Promise((resolve) => dntShim.setTimeout(resolve, pollIntervalMs));
498
+
499
+ const res = await fetch(`${input.apiUrl}/sandbox-sessions/${input.id}`, {
500
+ headers: { Authorization: `Bearer ${input.authToken}` },
501
+ });
502
+
503
+ if (!res.ok) {
504
+ continue;
505
+ }
506
+
507
+ const data = await res.json();
508
+ if (data.status === "running") return;
509
+ if (data.status === "error" || data.status === "deleting") {
510
+ throw INITIALIZATION_ERROR.create({
511
+ detail: `Sandbox failed to start: status=${data.status}`,
512
+ });
513
+ }
514
+ }
515
+
516
+ throw TIMEOUT_ERROR.create({ detail: "Sandbox did not become ready within timeout" });
517
+ }
@@ -1,3 +1,3 @@
1
1
  // Keep in sync with deno.json version.
2
2
  // scripts/release.ts updates this constant during releases.
3
- export const VERSION = "0.1.274";
3
+ export const VERSION = "0.1.276";