tensorlake 0.4.50 → 0.5.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/bin/darwin-arm64/tensorlake +0 -0
- package/dist/bin/darwin-arm64/tl +0 -0
- package/dist/bin/linux-x64/tensorlake +0 -0
- package/dist/bin/linux-x64/tl +0 -0
- package/dist/bin/win32-x64/tensorlake.exe +0 -0
- package/dist/bin/win32-x64/tl.exe +0 -0
- package/dist/index.cjs +312 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +185 -8
- package/dist/index.d.ts +185 -8
- package/dist/index.js +312 -28
- package/dist/index.js.map +1 -1
- package/dist/{sandbox-image-C79FXqQk.d.cts → sandbox-image-CMJ_FOOV.d.cts} +17 -1
- package/dist/{sandbox-image-C79FXqQk.d.ts → sandbox-image-CMJ_FOOV.d.ts} +17 -1
- package/dist/sandbox-image.cjs +299 -15
- package/dist/sandbox-image.cjs.map +1 -1
- package/dist/sandbox-image.d.cts +1 -1
- package/dist/sandbox-image.d.ts +1 -1
- package/dist/sandbox-image.js +304 -15
- package/dist/sandbox-image.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -31,10 +31,11 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
31
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
32
|
|
|
33
33
|
// src/defaults.ts
|
|
34
|
-
var API_URL, API_KEY, NAMESPACE, SANDBOX_PROXY_URL, DEFAULT_HTTP_TIMEOUT_MS, MAX_RETRIES, RETRY_BACKOFF_MS, RETRYABLE_STATUS_CODES;
|
|
34
|
+
var SDK_VERSION, API_URL, API_KEY, NAMESPACE, SANDBOX_PROXY_URL, DEFAULT_HTTP_TIMEOUT_MS, MAX_RETRIES, RETRY_BACKOFF_MS, RETRYABLE_STATUS_CODES;
|
|
35
35
|
var init_defaults = __esm({
|
|
36
36
|
"src/defaults.ts"() {
|
|
37
37
|
"use strict";
|
|
38
|
+
SDK_VERSION = "0.4.49";
|
|
38
39
|
API_URL = process.env.TENSORLAKE_API_URL ?? "https://api.tensorlake.ai";
|
|
39
40
|
API_KEY = process.env.TENSORLAKE_API_KEY ?? void 0;
|
|
40
41
|
NAMESPACE = process.env.INDEXIFY_NAMESPACE ?? "default";
|
|
@@ -132,6 +133,12 @@ var init_errors = __esm({
|
|
|
132
133
|
});
|
|
133
134
|
|
|
134
135
|
// src/http.ts
|
|
136
|
+
function withTraceId(value, traceId) {
|
|
137
|
+
if (value == null) {
|
|
138
|
+
return { traceId };
|
|
139
|
+
}
|
|
140
|
+
return Object.assign(value, { traceId });
|
|
141
|
+
}
|
|
135
142
|
function hasHeader(headers, name) {
|
|
136
143
|
const lowered = name.toLowerCase();
|
|
137
144
|
return Object.keys(headers).some((key) => key.toLowerCase() === lowered);
|
|
@@ -201,7 +208,7 @@ var init_http = __esm({
|
|
|
201
208
|
allowH2: true
|
|
202
209
|
})
|
|
203
210
|
);
|
|
204
|
-
HttpClient = class {
|
|
211
|
+
HttpClient = class _HttpClient {
|
|
205
212
|
baseUrl;
|
|
206
213
|
headers;
|
|
207
214
|
maxRetries;
|
|
@@ -214,7 +221,9 @@ var init_http = __esm({
|
|
|
214
221
|
this.maxRetries = options.maxRetries ?? MAX_RETRIES;
|
|
215
222
|
this.retryBackoffMs = options.retryBackoffMs ?? RETRY_BACKOFF_MS;
|
|
216
223
|
this.timeoutMs = options.timeoutMs ?? DEFAULT_HTTP_TIMEOUT_MS;
|
|
217
|
-
this.headers = {
|
|
224
|
+
this.headers = {
|
|
225
|
+
"User-Agent": `tensorlake-typescript-sdk/${SDK_VERSION}`
|
|
226
|
+
};
|
|
218
227
|
if (options.apiKey) {
|
|
219
228
|
this.headers["Authorization"] = `Bearer ${options.apiKey}`;
|
|
220
229
|
}
|
|
@@ -243,8 +252,8 @@ var init_http = __esm({
|
|
|
243
252
|
signal: options?.signal
|
|
244
253
|
});
|
|
245
254
|
const text = await response.text();
|
|
246
|
-
|
|
247
|
-
return
|
|
255
|
+
const data = text ? JSON.parse(text) : void 0;
|
|
256
|
+
return withTraceId(data, response.traceId);
|
|
248
257
|
}
|
|
249
258
|
/** Make a request returning raw bytes. */
|
|
250
259
|
async requestBytes(method, path2, options) {
|
|
@@ -258,7 +267,7 @@ var init_http = __esm({
|
|
|
258
267
|
signal: options?.signal
|
|
259
268
|
});
|
|
260
269
|
const buffer = await response.arrayBuffer();
|
|
261
|
-
return new Uint8Array(buffer);
|
|
270
|
+
return withTraceId(new Uint8Array(buffer), response.traceId);
|
|
262
271
|
}
|
|
263
272
|
/** Make a request and return the response body as an SSE stream. */
|
|
264
273
|
async requestStream(method, path2, options) {
|
|
@@ -273,7 +282,7 @@ var init_http = __esm({
|
|
|
273
282
|
"No response body for SSE stream"
|
|
274
283
|
);
|
|
275
284
|
}
|
|
276
|
-
return response.body;
|
|
285
|
+
return withTraceId(response.body, response.traceId);
|
|
277
286
|
}
|
|
278
287
|
/** Make a request and return the raw Response. */
|
|
279
288
|
async requestResponse(method, path2, options) {
|
|
@@ -286,7 +295,7 @@ var init_http = __esm({
|
|
|
286
295
|
headers["Content-Type"] = "application/json";
|
|
287
296
|
}
|
|
288
297
|
const body = hasJsonBody ? JSON.stringify(options?.json) : normalizeRequestBody(options?.body);
|
|
289
|
-
|
|
298
|
+
const { response, traceId } = await this.doFetch(
|
|
290
299
|
method,
|
|
291
300
|
path2,
|
|
292
301
|
body,
|
|
@@ -294,9 +303,18 @@ var init_http = __esm({
|
|
|
294
303
|
options?.signal,
|
|
295
304
|
options?.allowHttpErrors ?? false
|
|
296
305
|
);
|
|
306
|
+
return withTraceId(response, traceId);
|
|
307
|
+
}
|
|
308
|
+
static makeTraceparent() {
|
|
309
|
+
const randomHex = (bytes) => Array.from(crypto.getRandomValues(new Uint8Array(bytes))).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
310
|
+
const traceId = randomHex(16);
|
|
311
|
+
const spanId = randomHex(8);
|
|
312
|
+
return { traceparent: `00-${traceId}-${spanId}-01`, traceId };
|
|
297
313
|
}
|
|
298
314
|
async doFetch(method, path2, body, headers, signal, allowHttpErrors = false) {
|
|
299
315
|
const url = `${this.baseUrl}${path2}`;
|
|
316
|
+
const { traceparent, traceId } = _HttpClient.makeTraceparent();
|
|
317
|
+
headers["traceparent"] = traceparent;
|
|
300
318
|
let lastError;
|
|
301
319
|
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
302
320
|
if (attempt > 0) {
|
|
@@ -317,7 +335,7 @@ var init_http = __esm({
|
|
|
317
335
|
signal: combinedSignal
|
|
318
336
|
});
|
|
319
337
|
clearTimeout(timeoutId);
|
|
320
|
-
if (response.ok) return response;
|
|
338
|
+
if (response.ok) return { response, traceId };
|
|
321
339
|
if (RETRYABLE_STATUS_CODES.has(response.status) && attempt < this.maxRetries) {
|
|
322
340
|
lastError = new RemoteAPIError(
|
|
323
341
|
response.status,
|
|
@@ -326,7 +344,7 @@ var init_http = __esm({
|
|
|
326
344
|
continue;
|
|
327
345
|
}
|
|
328
346
|
if (allowHttpErrors) {
|
|
329
|
-
return response;
|
|
347
|
+
return { response, traceId };
|
|
330
348
|
}
|
|
331
349
|
const errorBody = await response.text().catch(() => "");
|
|
332
350
|
throwMappedError(response.status, errorBody, path2);
|
|
@@ -396,20 +414,20 @@ var SandboxStatus, SnapshotStatus, ProcessStatus, StdinMode, OutputMode, Contain
|
|
|
396
414
|
var init_models = __esm({
|
|
397
415
|
"src/models.ts"() {
|
|
398
416
|
"use strict";
|
|
399
|
-
SandboxStatus = /* @__PURE__ */ ((
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
return
|
|
417
|
+
SandboxStatus = /* @__PURE__ */ ((SandboxStatus3) => {
|
|
418
|
+
SandboxStatus3["PENDING"] = "pending";
|
|
419
|
+
SandboxStatus3["RUNNING"] = "running";
|
|
420
|
+
SandboxStatus3["SNAPSHOTTING"] = "snapshotting";
|
|
421
|
+
SandboxStatus3["SUSPENDING"] = "suspending";
|
|
422
|
+
SandboxStatus3["SUSPENDED"] = "suspended";
|
|
423
|
+
SandboxStatus3["TERMINATED"] = "terminated";
|
|
424
|
+
return SandboxStatus3;
|
|
407
425
|
})(SandboxStatus || {});
|
|
408
|
-
SnapshotStatus = /* @__PURE__ */ ((
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
return
|
|
426
|
+
SnapshotStatus = /* @__PURE__ */ ((SnapshotStatus3) => {
|
|
427
|
+
SnapshotStatus3["IN_PROGRESS"] = "in_progress";
|
|
428
|
+
SnapshotStatus3["COMPLETED"] = "completed";
|
|
429
|
+
SnapshotStatus3["FAILED"] = "failed";
|
|
430
|
+
return SnapshotStatus3;
|
|
413
431
|
})(SnapshotStatus || {});
|
|
414
432
|
ProcessStatus = /* @__PURE__ */ ((ProcessStatus2) => {
|
|
415
433
|
ProcessStatus2["RUNNING"] = "running";
|
|
@@ -3158,6 +3176,7 @@ var init_sandbox = __esm({
|
|
|
3158
3176
|
};
|
|
3159
3177
|
Sandbox = class {
|
|
3160
3178
|
sandboxId;
|
|
3179
|
+
traceId = null;
|
|
3161
3180
|
http;
|
|
3162
3181
|
baseUrl;
|
|
3163
3182
|
wsHeaders;
|
|
@@ -3195,9 +3214,126 @@ var init_sandbox = __esm({
|
|
|
3195
3214
|
this.ownsSandbox = true;
|
|
3196
3215
|
this.lifecycleClient = client;
|
|
3197
3216
|
}
|
|
3217
|
+
// --- Static factory methods ---
|
|
3218
|
+
/**
|
|
3219
|
+
* Create a new sandbox and return a connected, running handle.
|
|
3220
|
+
*
|
|
3221
|
+
* Covers both fresh sandbox creation and restore-from-snapshot (set
|
|
3222
|
+
* `snapshotId`). Blocks until the sandbox is `Running`.
|
|
3223
|
+
*/
|
|
3224
|
+
static async create(options) {
|
|
3225
|
+
const { SandboxClient: SandboxClient2 } = await Promise.resolve().then(() => (init_client(), client_exports));
|
|
3226
|
+
const client = new SandboxClient2(
|
|
3227
|
+
options,
|
|
3228
|
+
/* _internal */
|
|
3229
|
+
true
|
|
3230
|
+
);
|
|
3231
|
+
const sandbox = await client.createAndConnect(options);
|
|
3232
|
+
sandbox.lifecycleClient = client;
|
|
3233
|
+
return sandbox;
|
|
3234
|
+
}
|
|
3235
|
+
/**
|
|
3236
|
+
* Attach to an existing sandbox and return a connected handle.
|
|
3237
|
+
*
|
|
3238
|
+
* Verifies the sandbox exists via a server GET call, then returns a handle
|
|
3239
|
+
* in whatever state the sandbox is in. Does **not** auto-resume a suspended
|
|
3240
|
+
* sandbox — call `sandbox.resume()` explicitly.
|
|
3241
|
+
*/
|
|
3242
|
+
static async connect(options) {
|
|
3243
|
+
const { SandboxClient: SandboxClient2 } = await Promise.resolve().then(() => (init_client(), client_exports));
|
|
3244
|
+
const client = new SandboxClient2(
|
|
3245
|
+
options,
|
|
3246
|
+
/* _internal */
|
|
3247
|
+
true
|
|
3248
|
+
);
|
|
3249
|
+
await client.get(options.sandboxId);
|
|
3250
|
+
const sandbox = client.connect(options.sandboxId, options.proxyUrl, options.routingHint);
|
|
3251
|
+
sandbox.lifecycleClient = client;
|
|
3252
|
+
return sandbox;
|
|
3253
|
+
}
|
|
3254
|
+
// --- Static snapshot management ---
|
|
3255
|
+
/** Get information about a snapshot by ID. No sandbox handle needed. */
|
|
3256
|
+
static async getSnapshot(snapshotId, options) {
|
|
3257
|
+
const { SandboxClient: SandboxClient2 } = await Promise.resolve().then(() => (init_client(), client_exports));
|
|
3258
|
+
const client = new SandboxClient2(
|
|
3259
|
+
options,
|
|
3260
|
+
/* _internal */
|
|
3261
|
+
true
|
|
3262
|
+
);
|
|
3263
|
+
return client.getSnapshot(snapshotId);
|
|
3264
|
+
}
|
|
3265
|
+
/** Delete a snapshot by ID. No sandbox handle needed. */
|
|
3266
|
+
static async deleteSnapshot(snapshotId, options) {
|
|
3267
|
+
const { SandboxClient: SandboxClient2 } = await Promise.resolve().then(() => (init_client(), client_exports));
|
|
3268
|
+
const client = new SandboxClient2(
|
|
3269
|
+
options,
|
|
3270
|
+
/* _internal */
|
|
3271
|
+
true
|
|
3272
|
+
);
|
|
3273
|
+
await client.deleteSnapshot(snapshotId);
|
|
3274
|
+
}
|
|
3275
|
+
// --- Instance lifecycle methods ---
|
|
3276
|
+
requireLifecycleClient(operation) {
|
|
3277
|
+
if (!this.lifecycleClient) {
|
|
3278
|
+
throw new SandboxError(
|
|
3279
|
+
`Cannot ${operation}: no lifecycle client available. Use Sandbox.create() or Sandbox.connect() to get a lifecycle-aware handle.`
|
|
3280
|
+
);
|
|
3281
|
+
}
|
|
3282
|
+
return this.lifecycleClient;
|
|
3283
|
+
}
|
|
3284
|
+
/**
|
|
3285
|
+
* Suspend this sandbox.
|
|
3286
|
+
*
|
|
3287
|
+
* By default blocks until the sandbox is fully `Suspended`. Pass
|
|
3288
|
+
* `{ wait: false }` for fire-and-return.
|
|
3289
|
+
*/
|
|
3290
|
+
async suspend(options) {
|
|
3291
|
+
const client = this.requireLifecycleClient("suspend");
|
|
3292
|
+
await client.suspend(this.sandboxId, options);
|
|
3293
|
+
}
|
|
3294
|
+
/**
|
|
3295
|
+
* Resume this sandbox.
|
|
3296
|
+
*
|
|
3297
|
+
* By default blocks until the sandbox is `Running` and routable. Pass
|
|
3298
|
+
* `{ wait: false }` for fire-and-return.
|
|
3299
|
+
*/
|
|
3300
|
+
async resume(options) {
|
|
3301
|
+
const client = this.requireLifecycleClient("resume");
|
|
3302
|
+
await client.resume(this.sandboxId, options);
|
|
3303
|
+
}
|
|
3304
|
+
/**
|
|
3305
|
+
* Create a snapshot of this sandbox's filesystem and wait for it to
|
|
3306
|
+
* be committed.
|
|
3307
|
+
*
|
|
3308
|
+
* By default blocks until the snapshot artifact is ready and returns
|
|
3309
|
+
* the completed `SnapshotInfo`. Pass `{ wait: false }` to fire-and-return
|
|
3310
|
+
* (returns `undefined`).
|
|
3311
|
+
*/
|
|
3312
|
+
async checkpoint(options) {
|
|
3313
|
+
const client = this.requireLifecycleClient("checkpoint");
|
|
3314
|
+
if (options?.wait === false) {
|
|
3315
|
+
await client.snapshot(this.sandboxId, { contentMode: options.contentMode });
|
|
3316
|
+
return void 0;
|
|
3317
|
+
}
|
|
3318
|
+
return client.snapshotAndWait(this.sandboxId, {
|
|
3319
|
+
timeout: options?.timeout,
|
|
3320
|
+
pollInterval: options?.pollInterval,
|
|
3321
|
+
contentMode: options?.contentMode
|
|
3322
|
+
});
|
|
3323
|
+
}
|
|
3324
|
+
/**
|
|
3325
|
+
* List snapshots taken from this sandbox.
|
|
3326
|
+
*/
|
|
3327
|
+
async listSnapshots() {
|
|
3328
|
+
const client = this.requireLifecycleClient("listSnapshots");
|
|
3329
|
+
const all = await client.listSnapshots();
|
|
3330
|
+
return all.filter((s) => s.sandboxId === this.sandboxId);
|
|
3331
|
+
}
|
|
3332
|
+
/** Close the HTTP client. The sandbox keeps running. */
|
|
3198
3333
|
close() {
|
|
3199
3334
|
this.http.close();
|
|
3200
3335
|
}
|
|
3336
|
+
/** Terminate the sandbox and release all resources. */
|
|
3201
3337
|
async terminate() {
|
|
3202
3338
|
const client = this.lifecycleClient;
|
|
3203
3339
|
this.ownsSandbox = false;
|
|
@@ -3250,6 +3386,14 @@ var init_sandbox = __esm({
|
|
|
3250
3386
|
};
|
|
3251
3387
|
}
|
|
3252
3388
|
// --- Process management ---
|
|
3389
|
+
/**
|
|
3390
|
+
* Start a process in the sandbox without waiting for it to exit.
|
|
3391
|
+
*
|
|
3392
|
+
* Returns a `ProcessInfo` with the assigned `pid`. Use `getProcess()` to
|
|
3393
|
+
* poll status, or `followStdout()` / `followOutput()` to stream output
|
|
3394
|
+
* until the process exits. Use `run()` instead to block until completion
|
|
3395
|
+
* and get combined output in one call.
|
|
3396
|
+
*/
|
|
3253
3397
|
async startProcess(command, options) {
|
|
3254
3398
|
const payload = { command };
|
|
3255
3399
|
if (options?.args != null) payload.args = options.args;
|
|
@@ -3271,6 +3415,7 @@ var init_sandbox = __esm({
|
|
|
3271
3415
|
);
|
|
3272
3416
|
return fromSnakeKeys(raw);
|
|
3273
3417
|
}
|
|
3418
|
+
/** List all processes (running and exited) tracked by the sandbox daemon. */
|
|
3274
3419
|
async listProcesses() {
|
|
3275
3420
|
const raw = await this.http.requestJson(
|
|
3276
3421
|
"GET",
|
|
@@ -3278,6 +3423,7 @@ var init_sandbox = __esm({
|
|
|
3278
3423
|
);
|
|
3279
3424
|
return (raw.processes ?? []).map((p) => fromSnakeKeys(p));
|
|
3280
3425
|
}
|
|
3426
|
+
/** Get current status and metadata for a process by PID. */
|
|
3281
3427
|
async getProcess(pid) {
|
|
3282
3428
|
const raw = await this.http.requestJson(
|
|
3283
3429
|
"GET",
|
|
@@ -3285,9 +3431,11 @@ var init_sandbox = __esm({
|
|
|
3285
3431
|
);
|
|
3286
3432
|
return fromSnakeKeys(raw);
|
|
3287
3433
|
}
|
|
3434
|
+
/** Send SIGKILL to a process. */
|
|
3288
3435
|
async killProcess(pid) {
|
|
3289
3436
|
await this.http.requestJson("DELETE", `/api/v1/processes/${pid}`);
|
|
3290
3437
|
}
|
|
3438
|
+
/** Send an arbitrary signal to a process (e.g. `15` for SIGTERM, `9` for SIGKILL). */
|
|
3291
3439
|
async sendSignal(pid, signal) {
|
|
3292
3440
|
const raw = await this.http.requestJson(
|
|
3293
3441
|
"POST",
|
|
@@ -3297,15 +3445,18 @@ var init_sandbox = __esm({
|
|
|
3297
3445
|
return fromSnakeKeys(raw);
|
|
3298
3446
|
}
|
|
3299
3447
|
// --- Process I/O ---
|
|
3448
|
+
/** Write bytes to a process's stdin. The process must have been started with `stdinMode: StdinMode.PIPE`. */
|
|
3300
3449
|
async writeStdin(pid, data) {
|
|
3301
3450
|
await this.http.requestBytes("POST", `/api/v1/processes/${pid}/stdin`, {
|
|
3302
3451
|
body: data,
|
|
3303
3452
|
contentType: "application/octet-stream"
|
|
3304
3453
|
});
|
|
3305
3454
|
}
|
|
3455
|
+
/** Close a process's stdin pipe, signalling EOF to the process. */
|
|
3306
3456
|
async closeStdin(pid) {
|
|
3307
3457
|
await this.http.requestJson("POST", `/api/v1/processes/${pid}/stdin/close`);
|
|
3308
3458
|
}
|
|
3459
|
+
/** Return all captured stdout lines produced so far by a process. */
|
|
3309
3460
|
async getStdout(pid) {
|
|
3310
3461
|
const raw = await this.http.requestJson(
|
|
3311
3462
|
"GET",
|
|
@@ -3313,6 +3464,7 @@ var init_sandbox = __esm({
|
|
|
3313
3464
|
);
|
|
3314
3465
|
return fromSnakeKeys(raw);
|
|
3315
3466
|
}
|
|
3467
|
+
/** Return all captured stderr lines produced so far by a process. */
|
|
3316
3468
|
async getStderr(pid) {
|
|
3317
3469
|
const raw = await this.http.requestJson(
|
|
3318
3470
|
"GET",
|
|
@@ -3320,6 +3472,7 @@ var init_sandbox = __esm({
|
|
|
3320
3472
|
);
|
|
3321
3473
|
return fromSnakeKeys(raw);
|
|
3322
3474
|
}
|
|
3475
|
+
/** Return all captured stdout+stderr lines produced so far by a process. */
|
|
3323
3476
|
async getOutput(pid) {
|
|
3324
3477
|
const raw = await this.http.requestJson(
|
|
3325
3478
|
"GET",
|
|
@@ -3328,6 +3481,7 @@ var init_sandbox = __esm({
|
|
|
3328
3481
|
return fromSnakeKeys(raw);
|
|
3329
3482
|
}
|
|
3330
3483
|
// --- Streaming (SSE) ---
|
|
3484
|
+
/** Stream stdout events from a process until it exits. Yields one `OutputEvent` per line. */
|
|
3331
3485
|
async *followStdout(pid, options) {
|
|
3332
3486
|
const stream = await this.http.requestStream(
|
|
3333
3487
|
"GET",
|
|
@@ -3341,6 +3495,7 @@ var init_sandbox = __esm({
|
|
|
3341
3495
|
yield fromSnakeKeys(raw);
|
|
3342
3496
|
}
|
|
3343
3497
|
}
|
|
3498
|
+
/** Stream stderr events from a process until it exits. Yields one `OutputEvent` per line. */
|
|
3344
3499
|
async *followStderr(pid, options) {
|
|
3345
3500
|
const stream = await this.http.requestStream(
|
|
3346
3501
|
"GET",
|
|
@@ -3354,6 +3509,7 @@ var init_sandbox = __esm({
|
|
|
3354
3509
|
yield fromSnakeKeys(raw);
|
|
3355
3510
|
}
|
|
3356
3511
|
}
|
|
3512
|
+
/** Stream combined stdout+stderr events from a process until it exits. Yields one `OutputEvent` per line. */
|
|
3357
3513
|
async *followOutput(pid, options) {
|
|
3358
3514
|
const stream = await this.http.requestStream(
|
|
3359
3515
|
"GET",
|
|
@@ -3368,12 +3524,14 @@ var init_sandbox = __esm({
|
|
|
3368
3524
|
}
|
|
3369
3525
|
}
|
|
3370
3526
|
// --- File operations ---
|
|
3527
|
+
/** Read a file from the sandbox and return its raw bytes. */
|
|
3371
3528
|
async readFile(path2) {
|
|
3372
3529
|
return this.http.requestBytes(
|
|
3373
3530
|
"GET",
|
|
3374
3531
|
`/api/v1/files?path=${encodeURIComponent(path2)}`
|
|
3375
3532
|
);
|
|
3376
3533
|
}
|
|
3534
|
+
/** Write raw bytes to a file in the sandbox, creating it if it does not exist. */
|
|
3377
3535
|
async writeFile(path2, content) {
|
|
3378
3536
|
await this.http.requestBytes(
|
|
3379
3537
|
"PUT",
|
|
@@ -3381,12 +3539,14 @@ var init_sandbox = __esm({
|
|
|
3381
3539
|
{ body: content, contentType: "application/octet-stream" }
|
|
3382
3540
|
);
|
|
3383
3541
|
}
|
|
3542
|
+
/** Delete a file from the sandbox. */
|
|
3384
3543
|
async deleteFile(path2) {
|
|
3385
3544
|
await this.http.requestJson(
|
|
3386
3545
|
"DELETE",
|
|
3387
3546
|
`/api/v1/files?path=${encodeURIComponent(path2)}`
|
|
3388
3547
|
);
|
|
3389
3548
|
}
|
|
3549
|
+
/** List the contents of a directory in the sandbox. */
|
|
3390
3550
|
async listDirectory(path2) {
|
|
3391
3551
|
const raw = await this.http.requestJson(
|
|
3392
3552
|
"GET",
|
|
@@ -3395,6 +3555,7 @@ var init_sandbox = __esm({
|
|
|
3395
3555
|
return fromSnakeKeys(raw);
|
|
3396
3556
|
}
|
|
3397
3557
|
// --- PTY ---
|
|
3558
|
+
/** Create an interactive PTY session. Returns a `sessionId` and `token` for WebSocket connection via `connectPty()`. */
|
|
3398
3559
|
async createPtySession(options) {
|
|
3399
3560
|
const payload = {
|
|
3400
3561
|
command: options.command,
|
|
@@ -3411,6 +3572,7 @@ var init_sandbox = __esm({
|
|
|
3411
3572
|
);
|
|
3412
3573
|
return fromSnakeKeys(raw);
|
|
3413
3574
|
}
|
|
3575
|
+
/** Create a PTY session and connect to it immediately. Cleans up the session if the WebSocket connection fails. */
|
|
3414
3576
|
async createPty(options) {
|
|
3415
3577
|
const { onData, onExit, ...createOptions } = options;
|
|
3416
3578
|
const session = await this.createPtySession(createOptions);
|
|
@@ -3424,6 +3586,7 @@ var init_sandbox = __esm({
|
|
|
3424
3586
|
throw error;
|
|
3425
3587
|
}
|
|
3426
3588
|
}
|
|
3589
|
+
/** Attach to an existing PTY session by ID and token and return a connected `Pty` handle. */
|
|
3427
3590
|
async connectPty(sessionId, token, options) {
|
|
3428
3591
|
const wsUrl = new URL(this.ptyWsUrl(sessionId, token));
|
|
3429
3592
|
const authToken = wsUrl.searchParams.get("token") ?? token;
|
|
@@ -3448,6 +3611,7 @@ var init_sandbox = __esm({
|
|
|
3448
3611
|
await pty.connect();
|
|
3449
3612
|
return pty;
|
|
3450
3613
|
}
|
|
3614
|
+
/** Open a TCP tunnel to a port inside the sandbox and return the local listener. */
|
|
3451
3615
|
async createTunnel(remotePort, options) {
|
|
3452
3616
|
return TcpTunnel.listen({
|
|
3453
3617
|
baseUrl: this.baseUrl,
|
|
@@ -3458,6 +3622,7 @@ var init_sandbox = __esm({
|
|
|
3458
3622
|
connectTimeout: options?.connectTimeout
|
|
3459
3623
|
});
|
|
3460
3624
|
}
|
|
3625
|
+
/** Connect to a sandbox VNC session for programmatic desktop control. */
|
|
3461
3626
|
async connectDesktop(options) {
|
|
3462
3627
|
return Desktop.connect({
|
|
3463
3628
|
baseUrl: this.baseUrl,
|
|
@@ -3480,6 +3645,7 @@ var init_sandbox = __esm({
|
|
|
3480
3645
|
return `${wsBase}/api/v1/pty/${sessionId}/ws?token=${token}`;
|
|
3481
3646
|
}
|
|
3482
3647
|
// --- Health ---
|
|
3648
|
+
/** Check the sandbox daemon health. */
|
|
3483
3649
|
async health() {
|
|
3484
3650
|
const raw = await this.http.requestJson(
|
|
3485
3651
|
"GET",
|
|
@@ -3487,6 +3653,7 @@ var init_sandbox = __esm({
|
|
|
3487
3653
|
);
|
|
3488
3654
|
return fromSnakeKeys(raw);
|
|
3489
3655
|
}
|
|
3656
|
+
/** Get sandbox daemon info (version, uptime, process counts). */
|
|
3490
3657
|
async info() {
|
|
3491
3658
|
const raw = await this.http.requestJson(
|
|
3492
3659
|
"GET",
|
|
@@ -3499,6 +3666,10 @@ var init_sandbox = __esm({
|
|
|
3499
3666
|
});
|
|
3500
3667
|
|
|
3501
3668
|
// src/client.ts
|
|
3669
|
+
var client_exports = {};
|
|
3670
|
+
__export(client_exports, {
|
|
3671
|
+
SandboxClient: () => SandboxClient
|
|
3672
|
+
});
|
|
3502
3673
|
function sleep2(ms) {
|
|
3503
3674
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3504
3675
|
}
|
|
@@ -3535,7 +3706,13 @@ var init_client = __esm({
|
|
|
3535
3706
|
projectId;
|
|
3536
3707
|
namespace;
|
|
3537
3708
|
local;
|
|
3538
|
-
|
|
3709
|
+
/** @internal Pass `true` to suppress the deprecation warning when used by `Sandbox.create()` / `Sandbox.connect()`. */
|
|
3710
|
+
constructor(options, _internal = false) {
|
|
3711
|
+
if (!_internal) {
|
|
3712
|
+
console.warn(
|
|
3713
|
+
"[tensorlake] SandboxClient is deprecated; use Sandbox.create() / Sandbox.connect() instead."
|
|
3714
|
+
);
|
|
3715
|
+
}
|
|
3539
3716
|
this.apiUrl = options?.apiUrl ?? API_URL;
|
|
3540
3717
|
this.apiKey = options?.apiKey ?? API_KEY;
|
|
3541
3718
|
this.organizationId = options?.organizationId;
|
|
@@ -3575,6 +3752,7 @@ var init_client = __esm({
|
|
|
3575
3752
|
return lifecyclePath(subpath, this.local, this.namespace);
|
|
3576
3753
|
}
|
|
3577
3754
|
// --- Sandbox CRUD ---
|
|
3755
|
+
/** Create a new sandbox. Returns immediately; the sandbox may still be starting. Use `createAndConnect()` for a blocking, ready-to-use handle. */
|
|
3578
3756
|
async create(options) {
|
|
3579
3757
|
const body = {
|
|
3580
3758
|
resources: {
|
|
@@ -3601,8 +3779,10 @@ var init_client = __esm({
|
|
|
3601
3779
|
this.path("sandboxes"),
|
|
3602
3780
|
{ body }
|
|
3603
3781
|
);
|
|
3604
|
-
|
|
3782
|
+
const result = fromSnakeKeys(raw, "sandboxId");
|
|
3783
|
+
return Object.assign(result, { traceId: raw.traceId });
|
|
3605
3784
|
}
|
|
3785
|
+
/** Get current state and metadata for a sandbox by ID. */
|
|
3606
3786
|
async get(sandboxId) {
|
|
3607
3787
|
const raw = await this.http.requestJson(
|
|
3608
3788
|
"GET",
|
|
@@ -3610,6 +3790,7 @@ var init_client = __esm({
|
|
|
3610
3790
|
);
|
|
3611
3791
|
return fromSnakeKeys(raw, "sandboxId");
|
|
3612
3792
|
}
|
|
3793
|
+
/** List all sandboxes in the namespace. */
|
|
3613
3794
|
async list() {
|
|
3614
3795
|
const raw = await this.http.requestJson(
|
|
3615
3796
|
"GET",
|
|
@@ -3619,6 +3800,7 @@ var init_client = __esm({
|
|
|
3619
3800
|
(s) => fromSnakeKeys(s, "sandboxId")
|
|
3620
3801
|
);
|
|
3621
3802
|
}
|
|
3803
|
+
/** Update sandbox properties such as name, exposed ports, and proxy auth settings. */
|
|
3622
3804
|
async update(sandboxId, options) {
|
|
3623
3805
|
const body = {};
|
|
3624
3806
|
if (options.name != null) body.name = options.name;
|
|
@@ -3638,6 +3820,7 @@ var init_client = __esm({
|
|
|
3638
3820
|
);
|
|
3639
3821
|
return fromSnakeKeys(raw, "sandboxId");
|
|
3640
3822
|
}
|
|
3823
|
+
/** Get the current proxy port settings for a sandbox. */
|
|
3641
3824
|
async getPortAccess(sandboxId) {
|
|
3642
3825
|
const info = await this.get(sandboxId);
|
|
3643
3826
|
return {
|
|
@@ -3646,6 +3829,7 @@ var init_client = __esm({
|
|
|
3646
3829
|
sandboxUrl: info.sandboxUrl
|
|
3647
3830
|
};
|
|
3648
3831
|
}
|
|
3832
|
+
/** Add one or more user ports to the sandbox proxy allowlist. */
|
|
3649
3833
|
async exposePorts(sandboxId, ports, options) {
|
|
3650
3834
|
const requestedPorts = normalizeUserPorts(ports);
|
|
3651
3835
|
const current = await this.getPortAccess(sandboxId);
|
|
@@ -3658,6 +3842,7 @@ var init_client = __esm({
|
|
|
3658
3842
|
exposedPorts: desiredPorts
|
|
3659
3843
|
});
|
|
3660
3844
|
}
|
|
3845
|
+
/** Remove one or more user ports from the sandbox proxy allowlist. */
|
|
3661
3846
|
async unexposePorts(sandboxId, ports) {
|
|
3662
3847
|
const requestedPorts = normalizeUserPorts(ports);
|
|
3663
3848
|
const current = await this.getPortAccess(sandboxId);
|
|
@@ -3668,32 +3853,98 @@ var init_client = __esm({
|
|
|
3668
3853
|
exposedPorts: desiredPorts
|
|
3669
3854
|
});
|
|
3670
3855
|
}
|
|
3856
|
+
/** Terminate and delete a sandbox. */
|
|
3671
3857
|
async delete(sandboxId) {
|
|
3672
3858
|
await this.http.requestJson(
|
|
3673
3859
|
"DELETE",
|
|
3674
3860
|
this.path(`sandboxes/${sandboxId}`)
|
|
3675
3861
|
);
|
|
3676
3862
|
}
|
|
3677
|
-
|
|
3863
|
+
/**
|
|
3864
|
+
* Suspend a named sandbox, preserving its state for later resume.
|
|
3865
|
+
*
|
|
3866
|
+
* Only sandboxes created with a `name` can be suspended; ephemeral sandboxes
|
|
3867
|
+
* cannot. By default blocks until the sandbox is fully `Suspended`. Pass
|
|
3868
|
+
* `{ wait: false }` to return immediately after the request is sent
|
|
3869
|
+
* (fire-and-return); the server processes the suspend asynchronously.
|
|
3870
|
+
*
|
|
3871
|
+
* @param sandboxId - ID or name of the sandbox.
|
|
3872
|
+
* @param options.wait - If `true` (default), poll until `Suspended`. Pass `false` to fire-and-return.
|
|
3873
|
+
* @param options.timeout - Max seconds to wait when `wait=true` (default 300).
|
|
3874
|
+
* @param options.pollInterval - Seconds between status polls when `wait=true` (default 1).
|
|
3875
|
+
* @throws {SandboxError} If `wait=true` and the sandbox does not reach `Suspended` within `timeout`.
|
|
3876
|
+
*/
|
|
3877
|
+
async suspend(sandboxId, options) {
|
|
3678
3878
|
await this.http.requestResponse(
|
|
3679
3879
|
"POST",
|
|
3680
3880
|
this.path(`sandboxes/${sandboxId}/suspend`)
|
|
3681
3881
|
);
|
|
3882
|
+
if (options?.wait === false) return;
|
|
3883
|
+
const timeout = options?.timeout ?? 300;
|
|
3884
|
+
const pollInterval = options?.pollInterval ?? 1;
|
|
3885
|
+
const deadline = Date.now() + timeout * 1e3;
|
|
3886
|
+
while (Date.now() < deadline) {
|
|
3887
|
+
const info = await this.get(sandboxId);
|
|
3888
|
+
if (info.status === "suspended" /* SUSPENDED */) return;
|
|
3889
|
+
if (info.status === "terminated" /* TERMINATED */) {
|
|
3890
|
+
throw new SandboxError(`Sandbox ${sandboxId} terminated while waiting for suspend`);
|
|
3891
|
+
}
|
|
3892
|
+
await sleep2(pollInterval * 1e3);
|
|
3893
|
+
}
|
|
3894
|
+
throw new SandboxError(`Sandbox ${sandboxId} did not suspend within ${timeout}s`);
|
|
3682
3895
|
}
|
|
3683
|
-
|
|
3896
|
+
/**
|
|
3897
|
+
* Resume a suspended sandbox and bring it back to `Running`.
|
|
3898
|
+
*
|
|
3899
|
+
* By default blocks until the sandbox is `Running` and routable. Pass
|
|
3900
|
+
* `{ wait: false }` to return immediately after the request is sent
|
|
3901
|
+
* (fire-and-return); the server processes the resume asynchronously.
|
|
3902
|
+
*
|
|
3903
|
+
* @param sandboxId - ID or name of the sandbox.
|
|
3904
|
+
* @param options.wait - If `true` (default), poll until `Running`. Pass `false` to fire-and-return.
|
|
3905
|
+
* @param options.timeout - Max seconds to wait when `wait=true` (default 300).
|
|
3906
|
+
* @param options.pollInterval - Seconds between status polls when `wait=true` (default 1).
|
|
3907
|
+
* @throws {SandboxError} If `wait=true` and the sandbox does not reach `Running` within `timeout`.
|
|
3908
|
+
*/
|
|
3909
|
+
async resume(sandboxId, options) {
|
|
3684
3910
|
await this.http.requestResponse(
|
|
3685
3911
|
"POST",
|
|
3686
3912
|
this.path(`sandboxes/${sandboxId}/resume`)
|
|
3687
3913
|
);
|
|
3914
|
+
if (options?.wait === false) return;
|
|
3915
|
+
const timeout = options?.timeout ?? 300;
|
|
3916
|
+
const pollInterval = options?.pollInterval ?? 1;
|
|
3917
|
+
const deadline = Date.now() + timeout * 1e3;
|
|
3918
|
+
while (Date.now() < deadline) {
|
|
3919
|
+
const info = await this.get(sandboxId);
|
|
3920
|
+
if (info.status === "running" /* RUNNING */) return;
|
|
3921
|
+
if (info.status === "terminated" /* TERMINATED */) {
|
|
3922
|
+
throw new SandboxError(`Sandbox ${sandboxId} terminated while waiting for resume`);
|
|
3923
|
+
}
|
|
3924
|
+
await sleep2(pollInterval * 1e3);
|
|
3925
|
+
}
|
|
3926
|
+
throw new SandboxError(`Sandbox ${sandboxId} did not resume within ${timeout}s`);
|
|
3688
3927
|
}
|
|
3928
|
+
/** Claim a warm sandbox from a pool, creating one if no warm containers are available. */
|
|
3689
3929
|
async claim(poolId) {
|
|
3690
3930
|
const raw = await this.http.requestJson(
|
|
3691
3931
|
"POST",
|
|
3692
3932
|
this.path(`sandbox-pools/${poolId}/sandboxes`)
|
|
3693
3933
|
);
|
|
3694
|
-
|
|
3934
|
+
const result = fromSnakeKeys(raw, "sandboxId");
|
|
3935
|
+
return Object.assign(result, { traceId: raw.traceId });
|
|
3695
3936
|
}
|
|
3696
3937
|
// --- Snapshots ---
|
|
3938
|
+
/**
|
|
3939
|
+
* Request a snapshot of a running sandbox's filesystem.
|
|
3940
|
+
*
|
|
3941
|
+
* This call **returns immediately** with a `snapshotId` and `in_progress`
|
|
3942
|
+
* status — the snapshot is created asynchronously. Poll `getSnapshot()` until
|
|
3943
|
+
* `completed` or `failed`, or use `snapshotAndWait()` to block automatically.
|
|
3944
|
+
*
|
|
3945
|
+
* @param options.contentMode - `"filesystem_only"` for cold-boot snapshots (e.g. image builds).
|
|
3946
|
+
* Omit to use the server default (full VM snapshot).
|
|
3947
|
+
*/
|
|
3697
3948
|
async snapshot(sandboxId, options) {
|
|
3698
3949
|
const requestOptions = options?.contentMode != null ? { body: { snapshot_content_mode: options.contentMode } } : void 0;
|
|
3699
3950
|
const raw = await this.http.requestJson(
|
|
@@ -3703,6 +3954,7 @@ var init_client = __esm({
|
|
|
3703
3954
|
);
|
|
3704
3955
|
return fromSnakeKeys(raw, "snapshotId");
|
|
3705
3956
|
}
|
|
3957
|
+
/** Get current status and metadata for a snapshot by ID. */
|
|
3706
3958
|
async getSnapshot(snapshotId) {
|
|
3707
3959
|
const raw = await this.http.requestJson(
|
|
3708
3960
|
"GET",
|
|
@@ -3710,6 +3962,7 @@ var init_client = __esm({
|
|
|
3710
3962
|
);
|
|
3711
3963
|
return fromSnakeKeys(raw, "snapshotId");
|
|
3712
3964
|
}
|
|
3965
|
+
/** List all snapshots in the namespace. */
|
|
3713
3966
|
async listSnapshots() {
|
|
3714
3967
|
const raw = await this.http.requestJson(
|
|
3715
3968
|
"GET",
|
|
@@ -3719,12 +3972,26 @@ var init_client = __esm({
|
|
|
3719
3972
|
(s) => fromSnakeKeys(s, "snapshotId")
|
|
3720
3973
|
);
|
|
3721
3974
|
}
|
|
3975
|
+
/** Delete a snapshot by ID. */
|
|
3722
3976
|
async deleteSnapshot(snapshotId) {
|
|
3723
3977
|
await this.http.requestJson(
|
|
3724
3978
|
"DELETE",
|
|
3725
3979
|
this.path(`snapshots/${snapshotId}`)
|
|
3726
3980
|
);
|
|
3727
3981
|
}
|
|
3982
|
+
/**
|
|
3983
|
+
* Create a snapshot and block until it is committed.
|
|
3984
|
+
*
|
|
3985
|
+
* Combines `snapshot()` with polling `getSnapshot()` until `completed`.
|
|
3986
|
+
* Prefer `sandbox.checkpoint()` on a `Sandbox` handle for the same behavior
|
|
3987
|
+
* without managing the client separately.
|
|
3988
|
+
*
|
|
3989
|
+
* @param sandboxId - ID of the running sandbox to snapshot.
|
|
3990
|
+
* @param options.timeout - Max seconds to wait (default 300).
|
|
3991
|
+
* @param options.pollInterval - Seconds between status polls (default 1).
|
|
3992
|
+
* @param options.contentMode - Content mode passed through to `snapshot()`.
|
|
3993
|
+
* @throws {SandboxError} If the snapshot fails or `timeout` elapses.
|
|
3994
|
+
*/
|
|
3728
3995
|
async snapshotAndWait(sandboxId, options) {
|
|
3729
3996
|
const timeout = options?.timeout ?? 300;
|
|
3730
3997
|
const pollInterval = options?.pollInterval ?? 1;
|
|
@@ -3747,6 +4014,7 @@ var init_client = __esm({
|
|
|
3747
4014
|
);
|
|
3748
4015
|
}
|
|
3749
4016
|
// --- Pools ---
|
|
4017
|
+
/** Create a new sandbox pool with warm pre-booted containers. */
|
|
3750
4018
|
async createPool(options) {
|
|
3751
4019
|
const body = {
|
|
3752
4020
|
image: options.image,
|
|
@@ -3768,6 +4036,7 @@ var init_client = __esm({
|
|
|
3768
4036
|
);
|
|
3769
4037
|
return fromSnakeKeys(raw, "poolId");
|
|
3770
4038
|
}
|
|
4039
|
+
/** Get current state and metadata for a sandbox pool by ID. */
|
|
3771
4040
|
async getPool(poolId) {
|
|
3772
4041
|
const raw = await this.http.requestJson(
|
|
3773
4042
|
"GET",
|
|
@@ -3775,6 +4044,7 @@ var init_client = __esm({
|
|
|
3775
4044
|
);
|
|
3776
4045
|
return fromSnakeKeys(raw, "poolId");
|
|
3777
4046
|
}
|
|
4047
|
+
/** List all sandbox pools in the namespace. */
|
|
3778
4048
|
async listPools() {
|
|
3779
4049
|
const raw = await this.http.requestJson(
|
|
3780
4050
|
"GET",
|
|
@@ -3784,6 +4054,7 @@ var init_client = __esm({
|
|
|
3784
4054
|
(p) => fromSnakeKeys(p, "poolId")
|
|
3785
4055
|
);
|
|
3786
4056
|
}
|
|
4057
|
+
/** Replace the configuration of an existing sandbox pool. */
|
|
3787
4058
|
async updatePool(poolId, options) {
|
|
3788
4059
|
const body = {
|
|
3789
4060
|
image: options.image,
|
|
@@ -3805,6 +4076,7 @@ var init_client = __esm({
|
|
|
3805
4076
|
);
|
|
3806
4077
|
return fromSnakeKeys(raw, "poolId");
|
|
3807
4078
|
}
|
|
4079
|
+
/** Delete a sandbox pool. Fails if the pool has active containers. */
|
|
3808
4080
|
async deletePool(poolId) {
|
|
3809
4081
|
await this.http.requestJson(
|
|
3810
4082
|
"DELETE",
|
|
@@ -3812,6 +4084,7 @@ var init_client = __esm({
|
|
|
3812
4084
|
);
|
|
3813
4085
|
}
|
|
3814
4086
|
// --- Connect ---
|
|
4087
|
+
/** Return a `Sandbox` handle for an existing running sandbox without verifying it exists. */
|
|
3815
4088
|
connect(identifier, proxyUrl, routingHint) {
|
|
3816
4089
|
const resolvedProxy = proxyUrl ?? resolveProxyUrl(this.apiUrl);
|
|
3817
4090
|
return new Sandbox({
|
|
@@ -3823,6 +4096,15 @@ var init_client = __esm({
|
|
|
3823
4096
|
routingHint
|
|
3824
4097
|
});
|
|
3825
4098
|
}
|
|
4099
|
+
/**
|
|
4100
|
+
* Create a sandbox, wait for it to reach `Running`, and return a connected handle.
|
|
4101
|
+
*
|
|
4102
|
+
* Blocks until the sandbox is ready or `startupTimeout` elapses. The returned
|
|
4103
|
+
* `Sandbox` auto-terminates when `terminate()` is called.
|
|
4104
|
+
*
|
|
4105
|
+
* @param options.startupTimeout - Max seconds to wait for `Running` status (default 60).
|
|
4106
|
+
* @throws {SandboxError} If the sandbox terminates during startup or the timeout elapses.
|
|
4107
|
+
*/
|
|
3826
4108
|
async createAndConnect(options) {
|
|
3827
4109
|
const startupTimeout = options?.startupTimeout ?? 60;
|
|
3828
4110
|
let result;
|
|
@@ -3834,6 +4116,7 @@ var init_client = __esm({
|
|
|
3834
4116
|
if (result.status === "running" /* RUNNING */) {
|
|
3835
4117
|
const sandbox = this.connect(result.sandboxId, options?.proxyUrl, result.routingHint);
|
|
3836
4118
|
sandbox._setOwner(this);
|
|
4119
|
+
sandbox.traceId = result.traceId;
|
|
3837
4120
|
return sandbox;
|
|
3838
4121
|
}
|
|
3839
4122
|
const deadline = Date.now() + startupTimeout * 1e3;
|
|
@@ -3842,6 +4125,7 @@ var init_client = __esm({
|
|
|
3842
4125
|
if (info.status === "running" /* RUNNING */) {
|
|
3843
4126
|
const sandbox = this.connect(result.sandboxId, options?.proxyUrl, info.routingHint);
|
|
3844
4127
|
sandbox._setOwner(this);
|
|
4128
|
+
sandbox.traceId = result.traceId;
|
|
3845
4129
|
return sandbox;
|
|
3846
4130
|
}
|
|
3847
4131
|
if (info.status === "terminated" /* TERMINATED */) {
|