tensorlake 0.5.5 → 0.5.7
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 +120 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -22
- package/dist/index.d.ts +34 -22
- package/dist/index.js +120 -35
- package/dist/index.js.map +1 -1
- package/dist/{sandbox-image-BmhjX2bC.d.cts → sandbox-image-BMDaNpZ2.d.cts} +1 -1
- package/dist/{sandbox-image-BmhjX2bC.d.ts → sandbox-image-BMDaNpZ2.d.ts} +1 -1
- package/dist/sandbox-image.cjs +120 -35
- 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 +120 -35
- package/dist/sandbox-image.js.map +1 -1
- package/package.json +1 -1
|
Binary file
|
package/dist/bin/darwin-arm64/tl
CHANGED
|
Binary file
|
|
Binary file
|
package/dist/bin/linux-x64/tl
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/index.cjs
CHANGED
|
@@ -35,7 +35,7 @@ var SDK_VERSION, API_URL, API_KEY, NAMESPACE, SANDBOX_PROXY_URL, DEFAULT_HTTP_TI
|
|
|
35
35
|
var init_defaults = __esm({
|
|
36
36
|
"src/defaults.ts"() {
|
|
37
37
|
"use strict";
|
|
38
|
-
SDK_VERSION = "0.
|
|
38
|
+
SDK_VERSION = "0.5.7";
|
|
39
39
|
API_URL = process.env.TENSORLAKE_API_URL ?? "https://api.tensorlake.ai";
|
|
40
40
|
API_KEY = process.env.TENSORLAKE_API_KEY ?? void 0;
|
|
41
41
|
NAMESPACE = process.env.INDEXIFY_NAMESPACE ?? "default";
|
|
@@ -236,6 +236,9 @@ var init_http = __esm({
|
|
|
236
236
|
if (options.hostHeader) {
|
|
237
237
|
this.headers["Host"] = options.hostHeader;
|
|
238
238
|
}
|
|
239
|
+
if (options.sandboxIdHeader) {
|
|
240
|
+
this.headers["X-Tensorlake-Sandbox-Id"] = options.sandboxIdHeader;
|
|
241
|
+
}
|
|
239
242
|
if (options.routingHint) {
|
|
240
243
|
this.headers["X-Tensorlake-Route-Hint"] = options.routingHint;
|
|
241
244
|
}
|
|
@@ -2947,21 +2950,36 @@ function resolveProxyTarget(proxyUrl, sandboxId) {
|
|
|
2947
2950
|
if (host === "localhost" || host === "127.0.0.1") {
|
|
2948
2951
|
return {
|
|
2949
2952
|
baseUrl: trimTrailingSlashes(proxyUrl),
|
|
2950
|
-
hostHeader: `${sandboxId}.local
|
|
2953
|
+
hostHeader: `${sandboxId}.local`,
|
|
2954
|
+
sandboxIdHeader: void 0
|
|
2951
2955
|
};
|
|
2952
2956
|
}
|
|
2953
2957
|
const port = parsed.port ? `:${parsed.port}` : "";
|
|
2954
2958
|
return {
|
|
2955
|
-
baseUrl: `${parsed.protocol}//${
|
|
2956
|
-
hostHeader: void 0
|
|
2959
|
+
baseUrl: `${parsed.protocol}//${host}${port}`,
|
|
2960
|
+
hostHeader: void 0,
|
|
2961
|
+
sandboxIdHeader: sandboxId
|
|
2957
2962
|
};
|
|
2958
2963
|
} catch {
|
|
2959
2964
|
return {
|
|
2960
2965
|
baseUrl: `${trimTrailingSlashes(proxyUrl)}/${sandboxId}`,
|
|
2961
|
-
hostHeader: void 0
|
|
2966
|
+
hostHeader: void 0,
|
|
2967
|
+
sandboxIdHeader: void 0
|
|
2962
2968
|
};
|
|
2963
2969
|
}
|
|
2964
2970
|
}
|
|
2971
|
+
function resolveSandboxLifecycleUrl(apiUrl) {
|
|
2972
|
+
if (isLocalhost(apiUrl)) return apiUrl;
|
|
2973
|
+
try {
|
|
2974
|
+
const parsed = new URL(apiUrl);
|
|
2975
|
+
if (parsed.hostname.startsWith("api.")) {
|
|
2976
|
+
parsed.hostname = "sandbox." + parsed.hostname.slice(4);
|
|
2977
|
+
return parsed.toString().replace(/\/$/, "");
|
|
2978
|
+
}
|
|
2979
|
+
} catch {
|
|
2980
|
+
}
|
|
2981
|
+
return apiUrl;
|
|
2982
|
+
}
|
|
2965
2983
|
function lifecyclePath(path2, isLocal, namespace) {
|
|
2966
2984
|
if (isLocal) {
|
|
2967
2985
|
return `/v1/namespaces/${namespace}/${path2}`;
|
|
@@ -3188,7 +3206,7 @@ var init_sandbox = __esm({
|
|
|
3188
3206
|
this.sandboxId = options.sandboxId;
|
|
3189
3207
|
this.lifecycleIdentifier = options.sandboxId;
|
|
3190
3208
|
const proxyUrl = options.proxyUrl ?? SANDBOX_PROXY_URL;
|
|
3191
|
-
const { baseUrl, hostHeader } = resolveProxyTarget(proxyUrl, options.sandboxId);
|
|
3209
|
+
const { baseUrl, hostHeader, sandboxIdHeader } = resolveProxyTarget(proxyUrl, options.sandboxId);
|
|
3192
3210
|
this.baseUrl = baseUrl;
|
|
3193
3211
|
this.wsHeaders = {};
|
|
3194
3212
|
if (options.apiKey) {
|
|
@@ -3203,12 +3221,16 @@ var init_sandbox = __esm({
|
|
|
3203
3221
|
if (hostHeader) {
|
|
3204
3222
|
this.wsHeaders.Host = hostHeader;
|
|
3205
3223
|
}
|
|
3224
|
+
if (sandboxIdHeader) {
|
|
3225
|
+
this.wsHeaders["X-Tensorlake-Sandbox-Id"] = sandboxIdHeader;
|
|
3226
|
+
}
|
|
3206
3227
|
this.http = new HttpClient({
|
|
3207
3228
|
baseUrl,
|
|
3208
3229
|
apiKey: options.apiKey,
|
|
3209
3230
|
organizationId: options.organizationId,
|
|
3210
3231
|
projectId: options.projectId,
|
|
3211
3232
|
hostHeader,
|
|
3233
|
+
sandboxIdHeader,
|
|
3212
3234
|
routingHint: options.routingHint
|
|
3213
3235
|
});
|
|
3214
3236
|
}
|
|
@@ -3249,8 +3271,8 @@ var init_sandbox = __esm({
|
|
|
3249
3271
|
/**
|
|
3250
3272
|
* Attach to an existing sandbox and return a connected handle.
|
|
3251
3273
|
*
|
|
3252
|
-
*
|
|
3253
|
-
*
|
|
3274
|
+
* Returns immediately without contacting the server. Call `sandbox.info()`
|
|
3275
|
+
* to fetch the current state on demand. Does **not** auto-resume a suspended
|
|
3254
3276
|
* sandbox — call `sandbox.resume()` explicitly.
|
|
3255
3277
|
*/
|
|
3256
3278
|
static async connect(options) {
|
|
@@ -3260,15 +3282,12 @@ var init_sandbox = __esm({
|
|
|
3260
3282
|
/* _internal */
|
|
3261
3283
|
true
|
|
3262
3284
|
);
|
|
3263
|
-
const info = await client.get(options.sandboxId);
|
|
3264
3285
|
const sandbox = client.connect(
|
|
3265
|
-
|
|
3286
|
+
options.sandboxId,
|
|
3266
3287
|
options.proxyUrl,
|
|
3267
|
-
options.routingHint
|
|
3288
|
+
options.routingHint
|
|
3268
3289
|
);
|
|
3269
3290
|
sandbox.lifecycleClient = client;
|
|
3270
|
-
sandbox._setLifecycleIdentifier(info.sandboxId);
|
|
3271
|
-
sandbox._setName(info.name ?? null);
|
|
3272
3291
|
return sandbox;
|
|
3273
3292
|
}
|
|
3274
3293
|
// --- Static snapshot management ---
|
|
@@ -3292,6 +3311,26 @@ var init_sandbox = __esm({
|
|
|
3292
3311
|
);
|
|
3293
3312
|
await client.deleteSnapshot(snapshotId);
|
|
3294
3313
|
}
|
|
3314
|
+
/** List all sandboxes. No sandbox handle needed. */
|
|
3315
|
+
static async list(options) {
|
|
3316
|
+
const { SandboxClient: SandboxClient2 } = await Promise.resolve().then(() => (init_client(), client_exports));
|
|
3317
|
+
const client = new SandboxClient2(
|
|
3318
|
+
options,
|
|
3319
|
+
/* _internal */
|
|
3320
|
+
true
|
|
3321
|
+
);
|
|
3322
|
+
return client.list();
|
|
3323
|
+
}
|
|
3324
|
+
/** List all snapshots in the project. No sandbox handle needed. */
|
|
3325
|
+
static async listSnapshots(options) {
|
|
3326
|
+
const { SandboxClient: SandboxClient2 } = await Promise.resolve().then(() => (init_client(), client_exports));
|
|
3327
|
+
const client = new SandboxClient2(
|
|
3328
|
+
options,
|
|
3329
|
+
/* _internal */
|
|
3330
|
+
true
|
|
3331
|
+
);
|
|
3332
|
+
return client.listSnapshots();
|
|
3333
|
+
}
|
|
3295
3334
|
// --- Instance lifecycle methods ---
|
|
3296
3335
|
requireLifecycleClient(operation) {
|
|
3297
3336
|
if (!this.lifecycleClient) {
|
|
@@ -3301,6 +3340,14 @@ var init_sandbox = __esm({
|
|
|
3301
3340
|
}
|
|
3302
3341
|
return this.lifecycleClient;
|
|
3303
3342
|
}
|
|
3343
|
+
/** Fetch the current sandbox information from the server on demand. */
|
|
3344
|
+
async info() {
|
|
3345
|
+
const client = this.requireLifecycleClient("info");
|
|
3346
|
+
const info = await client.get(this.lifecycleIdentifier);
|
|
3347
|
+
this._setLifecycleIdentifier(info.sandboxId);
|
|
3348
|
+
this._setName(info.name ?? null);
|
|
3349
|
+
return info;
|
|
3350
|
+
}
|
|
3304
3351
|
/**
|
|
3305
3352
|
* Fetch the current sandbox status from the server.
|
|
3306
3353
|
*
|
|
@@ -3408,6 +3455,7 @@ var init_sandbox = __esm({
|
|
|
3408
3455
|
"/api/v1/processes/run",
|
|
3409
3456
|
{ json: body }
|
|
3410
3457
|
);
|
|
3458
|
+
const traceId = sseStream.traceId;
|
|
3411
3459
|
const stdoutLines = [];
|
|
3412
3460
|
const stderrLines = [];
|
|
3413
3461
|
let exitCode = -1;
|
|
@@ -3426,11 +3474,10 @@ var init_sandbox = __esm({
|
|
|
3426
3474
|
}
|
|
3427
3475
|
}
|
|
3428
3476
|
}
|
|
3429
|
-
return
|
|
3430
|
-
exitCode,
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
};
|
|
3477
|
+
return Object.assign(
|
|
3478
|
+
{ exitCode, stdout: stdoutLines.join("\n"), stderr: stderrLines.join("\n") },
|
|
3479
|
+
{ traceId }
|
|
3480
|
+
);
|
|
3434
3481
|
}
|
|
3435
3482
|
// --- Process management ---
|
|
3436
3483
|
/**
|
|
@@ -3460,7 +3507,7 @@ var init_sandbox = __esm({
|
|
|
3460
3507
|
"/api/v1/processes",
|
|
3461
3508
|
{ body: payload }
|
|
3462
3509
|
);
|
|
3463
|
-
return fromSnakeKeys(raw);
|
|
3510
|
+
return Object.assign(fromSnakeKeys(raw), { traceId: raw.traceId });
|
|
3464
3511
|
}
|
|
3465
3512
|
/** List all processes (running and exited) tracked by the sandbox daemon. */
|
|
3466
3513
|
async listProcesses() {
|
|
@@ -3477,7 +3524,7 @@ var init_sandbox = __esm({
|
|
|
3477
3524
|
"GET",
|
|
3478
3525
|
`/api/v1/processes/${pid}`
|
|
3479
3526
|
);
|
|
3480
|
-
return fromSnakeKeys(raw);
|
|
3527
|
+
return Object.assign(fromSnakeKeys(raw), { traceId: raw.traceId });
|
|
3481
3528
|
}
|
|
3482
3529
|
/** Send SIGKILL to a process. */
|
|
3483
3530
|
async killProcess(pid) {
|
|
@@ -3490,7 +3537,7 @@ var init_sandbox = __esm({
|
|
|
3490
3537
|
`/api/v1/processes/${pid}/signal`,
|
|
3491
3538
|
{ body: { signal } }
|
|
3492
3539
|
);
|
|
3493
|
-
return fromSnakeKeys(raw);
|
|
3540
|
+
return Object.assign(fromSnakeKeys(raw), { traceId: raw.traceId });
|
|
3494
3541
|
}
|
|
3495
3542
|
// --- Process I/O ---
|
|
3496
3543
|
/** Write bytes to a process's stdin. The process must have been started with `stdinMode: StdinMode.PIPE`. */
|
|
@@ -3510,7 +3557,7 @@ var init_sandbox = __esm({
|
|
|
3510
3557
|
"GET",
|
|
3511
3558
|
`/api/v1/processes/${pid}/stdout`
|
|
3512
3559
|
);
|
|
3513
|
-
return fromSnakeKeys(raw);
|
|
3560
|
+
return Object.assign(fromSnakeKeys(raw), { traceId: raw.traceId });
|
|
3514
3561
|
}
|
|
3515
3562
|
/** Return all captured stderr lines produced so far by a process. */
|
|
3516
3563
|
async getStderr(pid) {
|
|
@@ -3518,7 +3565,7 @@ var init_sandbox = __esm({
|
|
|
3518
3565
|
"GET",
|
|
3519
3566
|
`/api/v1/processes/${pid}/stderr`
|
|
3520
3567
|
);
|
|
3521
|
-
return fromSnakeKeys(raw);
|
|
3568
|
+
return Object.assign(fromSnakeKeys(raw), { traceId: raw.traceId });
|
|
3522
3569
|
}
|
|
3523
3570
|
/** Return all captured stdout+stderr lines produced so far by a process. */
|
|
3524
3571
|
async getOutput(pid) {
|
|
@@ -3526,7 +3573,7 @@ var init_sandbox = __esm({
|
|
|
3526
3573
|
"GET",
|
|
3527
3574
|
`/api/v1/processes/${pid}/output`
|
|
3528
3575
|
);
|
|
3529
|
-
return fromSnakeKeys(raw);
|
|
3576
|
+
return Object.assign(fromSnakeKeys(raw), { traceId: raw.traceId });
|
|
3530
3577
|
}
|
|
3531
3578
|
// --- Streaming (SSE) ---
|
|
3532
3579
|
/** Stream stdout events from a process until it exits. Yields one `OutputEvent` per line. */
|
|
@@ -3600,7 +3647,7 @@ var init_sandbox = __esm({
|
|
|
3600
3647
|
"GET",
|
|
3601
3648
|
`/api/v1/files/list?path=${encodeURIComponent(path2)}`
|
|
3602
3649
|
);
|
|
3603
|
-
return fromSnakeKeys(raw);
|
|
3650
|
+
return Object.assign(fromSnakeKeys(raw), { traceId: raw.traceId });
|
|
3604
3651
|
}
|
|
3605
3652
|
// --- PTY ---
|
|
3606
3653
|
/** Create an interactive PTY session. Returns a `sessionId` and `token` for WebSocket connection via `connectPty()`. */
|
|
@@ -3618,7 +3665,7 @@ var init_sandbox = __esm({
|
|
|
3618
3665
|
"/api/v1/pty",
|
|
3619
3666
|
{ body: payload }
|
|
3620
3667
|
);
|
|
3621
|
-
return fromSnakeKeys(raw);
|
|
3668
|
+
return Object.assign(fromSnakeKeys(raw), { traceId: raw.traceId });
|
|
3622
3669
|
}
|
|
3623
3670
|
/** Create a PTY session and connect to it immediately. Cleans up the session if the WebSocket connection fails. */
|
|
3624
3671
|
async createPty(options) {
|
|
@@ -3672,15 +3719,53 @@ var init_sandbox = __esm({
|
|
|
3672
3719
|
}
|
|
3673
3720
|
/** Connect to a sandbox VNC session for programmatic desktop control. */
|
|
3674
3721
|
async connectDesktop(options) {
|
|
3722
|
+
const port = options?.port ?? 5901;
|
|
3723
|
+
const connectTimeout = options?.connectTimeout ?? 10;
|
|
3724
|
+
const startMs = Date.now();
|
|
3725
|
+
const deadlineMs = startMs + connectTimeout * 1e3;
|
|
3726
|
+
await this.waitForPortReady(port, deadlineMs);
|
|
3727
|
+
const remainingSecs = Math.max(0.1, (deadlineMs - Date.now()) / 1e3);
|
|
3675
3728
|
return Desktop.connect({
|
|
3676
3729
|
baseUrl: this.baseUrl,
|
|
3677
3730
|
wsHeaders: this.wsHeaders,
|
|
3678
|
-
port
|
|
3731
|
+
port,
|
|
3679
3732
|
password: options?.password,
|
|
3680
3733
|
shared: options?.shared,
|
|
3681
|
-
connectTimeout:
|
|
3734
|
+
connectTimeout: remainingSecs
|
|
3682
3735
|
});
|
|
3683
3736
|
}
|
|
3737
|
+
/**
|
|
3738
|
+
* Poll the in-sandbox daemon until `127.0.0.1:port` accepts a TCP connection.
|
|
3739
|
+
* Uses `bash`'s `/dev/tcp` builtin via `processes/run` — no extra deps in
|
|
3740
|
+
* the sandbox image. `bash` is present on every image we ship.
|
|
3741
|
+
*/
|
|
3742
|
+
async waitForPortReady(port, deadlineMs) {
|
|
3743
|
+
const probeIntervalMs = 250;
|
|
3744
|
+
const probeProcessTimeoutSecs = 2;
|
|
3745
|
+
let lastError;
|
|
3746
|
+
while (Date.now() < deadlineMs) {
|
|
3747
|
+
try {
|
|
3748
|
+
const result = await this.run("/bin/bash", {
|
|
3749
|
+
args: ["-c", `exec 3<>/dev/tcp/127.0.0.1/${port}`],
|
|
3750
|
+
timeout: probeProcessTimeoutSecs
|
|
3751
|
+
});
|
|
3752
|
+
if (result.exitCode === 0) {
|
|
3753
|
+
return;
|
|
3754
|
+
}
|
|
3755
|
+
} catch (error) {
|
|
3756
|
+
lastError = error;
|
|
3757
|
+
}
|
|
3758
|
+
const remainingMs = deadlineMs - Date.now();
|
|
3759
|
+
if (remainingMs <= 0) break;
|
|
3760
|
+
await new Promise(
|
|
3761
|
+
(resolve) => setTimeout(resolve, Math.min(probeIntervalMs, remainingMs))
|
|
3762
|
+
);
|
|
3763
|
+
}
|
|
3764
|
+
const detail = lastError instanceof Error ? `: ${lastError.message}` : "";
|
|
3765
|
+
throw new SandboxError(
|
|
3766
|
+
`port ${port} did not become reachable inside sandbox within the connect timeout${detail}`
|
|
3767
|
+
);
|
|
3768
|
+
}
|
|
3684
3769
|
ptyWsUrl(sessionId, token) {
|
|
3685
3770
|
let wsBase;
|
|
3686
3771
|
if (this.baseUrl.startsWith("https://")) {
|
|
@@ -3699,15 +3784,15 @@ var init_sandbox = __esm({
|
|
|
3699
3784
|
"GET",
|
|
3700
3785
|
"/api/v1/health"
|
|
3701
3786
|
);
|
|
3702
|
-
return fromSnakeKeys(raw);
|
|
3787
|
+
return Object.assign(fromSnakeKeys(raw), { traceId: raw.traceId });
|
|
3703
3788
|
}
|
|
3704
3789
|
/** Get sandbox daemon info (version, uptime, process counts). */
|
|
3705
|
-
async
|
|
3790
|
+
async daemonInfo() {
|
|
3706
3791
|
const raw = await this.http.requestJson(
|
|
3707
3792
|
"GET",
|
|
3708
3793
|
"/api/v1/info"
|
|
3709
3794
|
);
|
|
3710
|
-
return fromSnakeKeys(raw);
|
|
3795
|
+
return Object.assign(fromSnakeKeys(raw), { traceId: raw.traceId });
|
|
3711
3796
|
}
|
|
3712
3797
|
};
|
|
3713
3798
|
}
|
|
@@ -3800,7 +3885,7 @@ var init_client = __esm({
|
|
|
3800
3885
|
this.namespace = options?.namespace ?? NAMESPACE;
|
|
3801
3886
|
this.local = isLocalhost(this.apiUrl);
|
|
3802
3887
|
this.http = new HttpClient({
|
|
3803
|
-
baseUrl: this.apiUrl,
|
|
3888
|
+
baseUrl: resolveSandboxLifecycleUrl(this.apiUrl),
|
|
3804
3889
|
apiKey: this.apiKey,
|
|
3805
3890
|
organizationId: this.organizationId,
|
|
3806
3891
|
projectId: this.projectId,
|
|
@@ -3868,7 +3953,7 @@ var init_client = __esm({
|
|
|
3868
3953
|
"GET",
|
|
3869
3954
|
this.path(`sandboxes/${sandboxId}`)
|
|
3870
3955
|
);
|
|
3871
|
-
return fromSnakeKeys(raw, "sandboxId");
|
|
3956
|
+
return Object.assign(fromSnakeKeys(raw, "sandboxId"), { traceId: raw.traceId });
|
|
3872
3957
|
}
|
|
3873
3958
|
/** List all sandboxes in the namespace. */
|
|
3874
3959
|
async list() {
|
|
@@ -3899,7 +3984,7 @@ var init_client = __esm({
|
|
|
3899
3984
|
this.path(`sandboxes/${sandboxId}`),
|
|
3900
3985
|
{ body }
|
|
3901
3986
|
);
|
|
3902
|
-
return fromSnakeKeys(raw, "sandboxId");
|
|
3987
|
+
return Object.assign(fromSnakeKeys(raw, "sandboxId"), { traceId: raw.traceId });
|
|
3903
3988
|
}
|
|
3904
3989
|
/** Get the current proxy port settings for a sandbox. */
|
|
3905
3990
|
async getPortAccess(sandboxId) {
|
|
@@ -4041,7 +4126,7 @@ var init_client = __esm({
|
|
|
4041
4126
|
"GET",
|
|
4042
4127
|
this.path(`snapshots/${snapshotId}`)
|
|
4043
4128
|
);
|
|
4044
|
-
return fromSnakeKeys(raw, "snapshotId");
|
|
4129
|
+
return Object.assign(fromSnakeKeys(raw, "snapshotId"), { traceId: raw.traceId });
|
|
4045
4130
|
}
|
|
4046
4131
|
/** List all snapshots in the namespace. */
|
|
4047
4132
|
async listSnapshots() {
|