tensorlake 0.5.29 → 0.5.31
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 +262 -76
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +49 -10
- package/dist/index.d.ts +49 -10
- package/dist/index.js +260 -75
- package/dist/index.js.map +1 -1
- package/dist/native/darwin-arm64/tensorlake-node.node +0 -0
- package/dist/native/linux-x64/tensorlake-node.node +0 -0
- package/dist/native/win32-x64/tensorlake-node.node +0 -0
- 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.5.
|
|
38
|
+
SDK_VERSION = "0.5.31";
|
|
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";
|
|
@@ -195,13 +195,14 @@ function anySignal(signals) {
|
|
|
195
195
|
function sleep(ms) {
|
|
196
196
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
197
197
|
}
|
|
198
|
-
var import_undici, HttpClient;
|
|
198
|
+
var import_undici, REQUEST_TIMEOUT_HEADER, HttpClient;
|
|
199
199
|
var init_http = __esm({
|
|
200
200
|
"src/http.ts"() {
|
|
201
201
|
"use strict";
|
|
202
202
|
import_undici = require("undici");
|
|
203
203
|
init_defaults();
|
|
204
204
|
init_errors();
|
|
205
|
+
REQUEST_TIMEOUT_HEADER = "X-Tensorlake-Request-Timeout-Ms";
|
|
205
206
|
(0, import_undici.setGlobalDispatcher)(
|
|
206
207
|
new import_undici.Agent({
|
|
207
208
|
keepAliveTimeout: 6e4,
|
|
@@ -220,10 +221,13 @@ var init_http = __esm({
|
|
|
220
221
|
this.baseUrl = url.endsWith("/") ? url.slice(0, -1) : url;
|
|
221
222
|
this.maxRetries = options.maxRetries ?? MAX_RETRIES;
|
|
222
223
|
this.retryBackoffMs = options.retryBackoffMs ?? RETRY_BACKOFF_MS;
|
|
223
|
-
this.timeoutMs = options.timeoutMs
|
|
224
|
+
this.timeoutMs = options.timeoutMs === void 0 ? DEFAULT_HTTP_TIMEOUT_MS : options.timeoutMs;
|
|
224
225
|
this.headers = {
|
|
225
226
|
"User-Agent": `tensorlake-typescript-sdk/${SDK_VERSION}`
|
|
226
227
|
};
|
|
228
|
+
if (this.timeoutMs != null) {
|
|
229
|
+
this.headers[REQUEST_TIMEOUT_HEADER] = String(this.timeoutMs);
|
|
230
|
+
}
|
|
227
231
|
if (options.apiKey) {
|
|
228
232
|
this.headers["Authorization"] = `Bearer ${options.apiKey}`;
|
|
229
233
|
}
|
|
@@ -252,7 +256,10 @@ var init_http = __esm({
|
|
|
252
256
|
const response = await this.requestResponse(method, path2, {
|
|
253
257
|
json: options?.body,
|
|
254
258
|
headers: options?.headers,
|
|
255
|
-
signal: options?.signal
|
|
259
|
+
signal: options?.signal,
|
|
260
|
+
retryableStatusCodes: options?.retryableStatusCodes,
|
|
261
|
+
allowedErrorStatusCodes: options?.allowedErrorStatusCodes,
|
|
262
|
+
allowHttpErrors: options?.allowHttpErrors
|
|
256
263
|
});
|
|
257
264
|
const text = await response.text();
|
|
258
265
|
const data = text ? JSON.parse(text) : void 0;
|
|
@@ -304,7 +311,9 @@ var init_http = __esm({
|
|
|
304
311
|
body,
|
|
305
312
|
headers,
|
|
306
313
|
options?.signal,
|
|
307
|
-
options?.allowHttpErrors ?? false
|
|
314
|
+
options?.allowHttpErrors ?? false,
|
|
315
|
+
options?.retryableStatusCodes ?? RETRYABLE_STATUS_CODES,
|
|
316
|
+
options?.allowedErrorStatusCodes ?? /* @__PURE__ */ new Set()
|
|
308
317
|
);
|
|
309
318
|
return withTraceId(response, traceId);
|
|
310
319
|
}
|
|
@@ -314,7 +323,7 @@ var init_http = __esm({
|
|
|
314
323
|
const spanId = randomHex(8);
|
|
315
324
|
return { traceparent: `00-${traceId}-${spanId}-01`, traceId };
|
|
316
325
|
}
|
|
317
|
-
async doFetch(method, path2, body, headers, signal, allowHttpErrors = false) {
|
|
326
|
+
async doFetch(method, path2, body, headers, signal, allowHttpErrors = false, retryableStatusCodes = RETRYABLE_STATUS_CODES, allowedErrorStatusCodes = /* @__PURE__ */ new Set()) {
|
|
318
327
|
const url = `${this.baseUrl}${path2}`;
|
|
319
328
|
const { traceparent, traceId } = _HttpClient.makeTraceparent();
|
|
320
329
|
headers["traceparent"] = traceparent;
|
|
@@ -325,10 +334,7 @@ var init_http = __esm({
|
|
|
325
334
|
await sleep(delay);
|
|
326
335
|
}
|
|
327
336
|
this.abortController = new AbortController();
|
|
328
|
-
const timeoutId = setTimeout(
|
|
329
|
-
() => this.abortController?.abort(),
|
|
330
|
-
this.timeoutMs
|
|
331
|
-
);
|
|
337
|
+
const timeoutId = this.timeoutMs == null ? null : setTimeout(() => this.abortController?.abort(), this.timeoutMs);
|
|
332
338
|
const combinedSignal = signal ? anySignal([signal, this.abortController.signal]) : this.abortController.signal;
|
|
333
339
|
try {
|
|
334
340
|
const response = await (0, import_undici.fetch)(url, {
|
|
@@ -337,22 +343,22 @@ var init_http = __esm({
|
|
|
337
343
|
body,
|
|
338
344
|
signal: combinedSignal
|
|
339
345
|
});
|
|
340
|
-
clearTimeout(timeoutId);
|
|
346
|
+
if (timeoutId != null) clearTimeout(timeoutId);
|
|
341
347
|
if (response.ok) return { response, traceId };
|
|
342
|
-
if (
|
|
348
|
+
if (retryableStatusCodes.has(response.status) && attempt < this.maxRetries) {
|
|
343
349
|
lastError = new RemoteAPIError(
|
|
344
350
|
response.status,
|
|
345
351
|
await response.text().catch(() => "")
|
|
346
352
|
);
|
|
347
353
|
continue;
|
|
348
354
|
}
|
|
349
|
-
if (allowHttpErrors) {
|
|
355
|
+
if (allowHttpErrors || allowedErrorStatusCodes.has(response.status)) {
|
|
350
356
|
return { response, traceId };
|
|
351
357
|
}
|
|
352
358
|
const errorBody = await response.text().catch(() => "");
|
|
353
359
|
throwMappedError(response.status, errorBody, path2);
|
|
354
360
|
} catch (err) {
|
|
355
|
-
clearTimeout(timeoutId);
|
|
361
|
+
if (timeoutId != null) clearTimeout(timeoutId);
|
|
356
362
|
if (err instanceof RemoteAPIError || err instanceof SandboxNotFoundError || err instanceof PoolNotFoundError || err instanceof PoolInUseError) {
|
|
357
363
|
throw err;
|
|
358
364
|
}
|
|
@@ -424,6 +430,7 @@ var init_models = __esm({
|
|
|
424
430
|
SandboxStatus3["SUSPENDING"] = "suspending";
|
|
425
431
|
SandboxStatus3["SUSPENDED"] = "suspended";
|
|
426
432
|
SandboxStatus3["TERMINATED"] = "terminated";
|
|
433
|
+
SandboxStatus3["TIMEOUT"] = "timeout";
|
|
427
434
|
return SandboxStatus3;
|
|
428
435
|
})(SandboxStatus || {});
|
|
429
436
|
SnapshotStatus = /* @__PURE__ */ ((SnapshotStatus2) => {
|
|
@@ -2969,6 +2976,14 @@ function resolveProxyTarget(proxyUrl, sandboxId) {
|
|
|
2969
2976
|
};
|
|
2970
2977
|
}
|
|
2971
2978
|
}
|
|
2979
|
+
function sandboxUrlFromIngressEndpoint(ingressEndpoint, sandboxId, port = 9501) {
|
|
2980
|
+
const parsed = new URL(ingressEndpoint);
|
|
2981
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
2982
|
+
throw new Error("ingressEndpoint must be an absolute http(s) URL");
|
|
2983
|
+
}
|
|
2984
|
+
const label = port === 9501 ? sandboxId : `${port}-${sandboxId}`;
|
|
2985
|
+
return `${parsed.protocol}//${label}.${parsed.host}`;
|
|
2986
|
+
}
|
|
2972
2987
|
function resolveSandboxLifecycleUrl(apiUrl) {
|
|
2973
2988
|
if (isLocalhost(apiUrl)) return apiUrl;
|
|
2974
2989
|
try {
|
|
@@ -3027,7 +3042,13 @@ function sendPtyFrame(socket, frame) {
|
|
|
3027
3042
|
socket.send(frame, (error) => error ? reject(error) : resolve());
|
|
3028
3043
|
});
|
|
3029
3044
|
}
|
|
3030
|
-
|
|
3045
|
+
function secondsToMillis3(seconds) {
|
|
3046
|
+
if (!Number.isFinite(seconds) || seconds <= 0) {
|
|
3047
|
+
throw new SandboxError("requestTimeout must be a positive number of seconds");
|
|
3048
|
+
}
|
|
3049
|
+
return Math.ceil(seconds * 1e3);
|
|
3050
|
+
}
|
|
3051
|
+
var import_ws2, DEFAULT_PROCESS_USER, SandboxProxyConnection, PTY_OP_DATA, PTY_OP_RESIZE, PTY_OP_READY, PTY_OP_EXIT, Pty, Sandbox;
|
|
3031
3052
|
var init_sandbox = __esm({
|
|
3032
3053
|
"src/sandbox.ts"() {
|
|
3033
3054
|
"use strict";
|
|
@@ -3041,6 +3062,99 @@ var init_sandbox = __esm({
|
|
|
3041
3062
|
init_url();
|
|
3042
3063
|
import_ws2 = __toESM(require("ws"), 1);
|
|
3043
3064
|
DEFAULT_PROCESS_USER = "tl-user";
|
|
3065
|
+
SandboxProxyConnection = class {
|
|
3066
|
+
constructor(sandbox, options) {
|
|
3067
|
+
this.sandbox = sandbox;
|
|
3068
|
+
this.options = options;
|
|
3069
|
+
this.routingHint = options.routingHint;
|
|
3070
|
+
this.http = this.configureProxy(
|
|
3071
|
+
options.proxyUrl ?? SANDBOX_PROXY_URL,
|
|
3072
|
+
options.sandboxId,
|
|
3073
|
+
options.routingHint
|
|
3074
|
+
);
|
|
3075
|
+
this.resolveProxyInfo = options.resolveProxyInfo;
|
|
3076
|
+
}
|
|
3077
|
+
baseUrl = "";
|
|
3078
|
+
wsHeaders = {};
|
|
3079
|
+
http;
|
|
3080
|
+
resolveProxyInfo;
|
|
3081
|
+
resolvePromise = null;
|
|
3082
|
+
routingHint;
|
|
3083
|
+
async ensureResolved() {
|
|
3084
|
+
if (this.resolveProxyInfo == null) {
|
|
3085
|
+
return;
|
|
3086
|
+
}
|
|
3087
|
+
if (this.resolvePromise != null) {
|
|
3088
|
+
return this.resolvePromise;
|
|
3089
|
+
}
|
|
3090
|
+
this.resolvePromise = this.resolveProxyInfo(this.sandbox._getLifecycleIdentifier()).then((info) => {
|
|
3091
|
+
this.resolveProxyInfo = void 0;
|
|
3092
|
+
this.sandbox.traceId = info.traceId;
|
|
3093
|
+
this.sandbox._setLifecycleIdentifier(info.sandboxId);
|
|
3094
|
+
this.sandbox._setName(info.name ?? null);
|
|
3095
|
+
this.routingHint = this.routingHint ?? info.routingHint;
|
|
3096
|
+
const proxyUrl = info.ingressEndpoint ?? this.options.proxyUrl ?? SANDBOX_PROXY_URL;
|
|
3097
|
+
const nextHttp = this.configureProxy(proxyUrl, info.sandboxId, this.routingHint);
|
|
3098
|
+
this.http.close();
|
|
3099
|
+
this.http = nextHttp;
|
|
3100
|
+
}).finally(() => {
|
|
3101
|
+
this.resolvePromise = null;
|
|
3102
|
+
});
|
|
3103
|
+
return this.resolvePromise;
|
|
3104
|
+
}
|
|
3105
|
+
async requestJson(method, path2, options) {
|
|
3106
|
+
await this.ensureResolved();
|
|
3107
|
+
return this.http.requestJson(method, path2, options);
|
|
3108
|
+
}
|
|
3109
|
+
async requestBytes(method, path2, options) {
|
|
3110
|
+
await this.ensureResolved();
|
|
3111
|
+
return this.http.requestBytes(method, path2, options);
|
|
3112
|
+
}
|
|
3113
|
+
async requestStream(method, path2, options) {
|
|
3114
|
+
await this.ensureResolved();
|
|
3115
|
+
return this.http.requestStream(method, path2, options);
|
|
3116
|
+
}
|
|
3117
|
+
async requestResponse(method, path2, options) {
|
|
3118
|
+
await this.ensureResolved();
|
|
3119
|
+
return this.http.requestResponse(method, path2, options);
|
|
3120
|
+
}
|
|
3121
|
+
close() {
|
|
3122
|
+
this.http.close();
|
|
3123
|
+
}
|
|
3124
|
+
configureProxy(proxyUrl, sandboxId, routingHint) {
|
|
3125
|
+
const { baseUrl, hostHeader, sandboxIdHeader } = resolveProxyTarget(
|
|
3126
|
+
proxyUrl,
|
|
3127
|
+
sandboxId
|
|
3128
|
+
);
|
|
3129
|
+
this.baseUrl = baseUrl;
|
|
3130
|
+
this.wsHeaders = {};
|
|
3131
|
+
if (this.options.apiKey) {
|
|
3132
|
+
this.wsHeaders.Authorization = `Bearer ${this.options.apiKey}`;
|
|
3133
|
+
}
|
|
3134
|
+
if (this.options.organizationId) {
|
|
3135
|
+
this.wsHeaders["X-Forwarded-Organization-Id"] = this.options.organizationId;
|
|
3136
|
+
}
|
|
3137
|
+
if (this.options.projectId) {
|
|
3138
|
+
this.wsHeaders["X-Forwarded-Project-Id"] = this.options.projectId;
|
|
3139
|
+
}
|
|
3140
|
+
if (hostHeader) {
|
|
3141
|
+
this.wsHeaders.Host = hostHeader;
|
|
3142
|
+
}
|
|
3143
|
+
if (sandboxIdHeader) {
|
|
3144
|
+
this.wsHeaders["X-Tensorlake-Sandbox-Id"] = sandboxIdHeader;
|
|
3145
|
+
}
|
|
3146
|
+
return new HttpClient({
|
|
3147
|
+
baseUrl,
|
|
3148
|
+
apiKey: this.options.apiKey,
|
|
3149
|
+
organizationId: this.options.organizationId,
|
|
3150
|
+
projectId: this.options.projectId,
|
|
3151
|
+
hostHeader,
|
|
3152
|
+
sandboxIdHeader,
|
|
3153
|
+
routingHint,
|
|
3154
|
+
timeoutMs: this.options.requestTimeout != null ? secondsToMillis3(this.options.requestTimeout) : this.options.timeoutMs ?? null
|
|
3155
|
+
});
|
|
3156
|
+
}
|
|
3157
|
+
};
|
|
3044
3158
|
PTY_OP_DATA = 0;
|
|
3045
3159
|
PTY_OP_RESIZE = 1;
|
|
3046
3160
|
PTY_OP_READY = 2;
|
|
@@ -3206,9 +3320,8 @@ var init_sandbox = __esm({
|
|
|
3206
3320
|
Sandbox = class {
|
|
3207
3321
|
sandboxId;
|
|
3208
3322
|
traceId = null;
|
|
3323
|
+
proxy;
|
|
3209
3324
|
http;
|
|
3210
|
-
baseUrl;
|
|
3211
|
-
wsHeaders;
|
|
3212
3325
|
ownsSandbox = false;
|
|
3213
3326
|
lifecycleClient = null;
|
|
3214
3327
|
lifecycleIdentifier;
|
|
@@ -3216,34 +3329,14 @@ var init_sandbox = __esm({
|
|
|
3216
3329
|
constructor(options) {
|
|
3217
3330
|
this.sandboxId = options.sandboxId;
|
|
3218
3331
|
this.lifecycleIdentifier = options.sandboxId;
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
this.wsHeaders["X-Forwarded-Organization-Id"] = options.organizationId;
|
|
3228
|
-
}
|
|
3229
|
-
if (options.projectId) {
|
|
3230
|
-
this.wsHeaders["X-Forwarded-Project-Id"] = options.projectId;
|
|
3231
|
-
}
|
|
3232
|
-
if (hostHeader) {
|
|
3233
|
-
this.wsHeaders.Host = hostHeader;
|
|
3234
|
-
}
|
|
3235
|
-
if (sandboxIdHeader) {
|
|
3236
|
-
this.wsHeaders["X-Tensorlake-Sandbox-Id"] = sandboxIdHeader;
|
|
3237
|
-
}
|
|
3238
|
-
this.http = new HttpClient({
|
|
3239
|
-
baseUrl,
|
|
3240
|
-
apiKey: options.apiKey,
|
|
3241
|
-
organizationId: options.organizationId,
|
|
3242
|
-
projectId: options.projectId,
|
|
3243
|
-
hostHeader,
|
|
3244
|
-
sandboxIdHeader,
|
|
3245
|
-
routingHint: options.routingHint
|
|
3246
|
-
});
|
|
3332
|
+
this.proxy = new SandboxProxyConnection(this, options);
|
|
3333
|
+
this.http = this.proxy;
|
|
3334
|
+
}
|
|
3335
|
+
get baseUrl() {
|
|
3336
|
+
return this.proxy.baseUrl;
|
|
3337
|
+
}
|
|
3338
|
+
get wsHeaders() {
|
|
3339
|
+
return this.proxy.wsHeaders;
|
|
3247
3340
|
}
|
|
3248
3341
|
get name() {
|
|
3249
3342
|
return this.sandboxName;
|
|
@@ -3256,6 +3349,10 @@ var init_sandbox = __esm({
|
|
|
3256
3349
|
_setLifecycleIdentifier(identifier) {
|
|
3257
3350
|
this.lifecycleIdentifier = identifier;
|
|
3258
3351
|
}
|
|
3352
|
+
/** @internal Used by the lazy proxy resolver. */
|
|
3353
|
+
_getLifecycleIdentifier() {
|
|
3354
|
+
return this.lifecycleIdentifier;
|
|
3355
|
+
}
|
|
3259
3356
|
/** @internal Used by SandboxClient.createAndConnect to set ownership. */
|
|
3260
3357
|
_setOwner(client) {
|
|
3261
3358
|
this.ownsSandbox = true;
|
|
@@ -3275,16 +3372,14 @@ var init_sandbox = __esm({
|
|
|
3275
3372
|
/* _internal */
|
|
3276
3373
|
true
|
|
3277
3374
|
);
|
|
3278
|
-
|
|
3279
|
-
sandbox.lifecycleClient = client;
|
|
3280
|
-
return sandbox;
|
|
3375
|
+
return client.createAndConnect(options);
|
|
3281
3376
|
}
|
|
3282
3377
|
/**
|
|
3283
3378
|
* Attach to an existing sandbox and return a connected handle.
|
|
3284
3379
|
*
|
|
3285
|
-
*
|
|
3286
|
-
*
|
|
3287
|
-
* sandbox — call `sandbox.resume()` explicitly.
|
|
3380
|
+
* When `proxyUrl` is omitted, resolves the sandbox first so the handle uses
|
|
3381
|
+
* the correct cloud/region ingress endpoint. Does **not** auto-resume a
|
|
3382
|
+
* suspended sandbox — call `sandbox.resume()` explicitly.
|
|
3288
3383
|
*/
|
|
3289
3384
|
static async connect(options) {
|
|
3290
3385
|
const { SandboxClient: SandboxClient2 } = await Promise.resolve().then(() => (init_client(), client_exports));
|
|
@@ -3296,7 +3391,8 @@ var init_sandbox = __esm({
|
|
|
3296
3391
|
const sandbox = client.connect(
|
|
3297
3392
|
options.sandboxId,
|
|
3298
3393
|
options.proxyUrl,
|
|
3299
|
-
options.routingHint
|
|
3394
|
+
options.routingHint,
|
|
3395
|
+
options.requestTimeout
|
|
3300
3396
|
);
|
|
3301
3397
|
sandbox.lifecycleClient = client;
|
|
3302
3398
|
return sandbox;
|
|
@@ -3698,6 +3794,7 @@ var init_sandbox = __esm({
|
|
|
3698
3794
|
}
|
|
3699
3795
|
/** Attach to an existing PTY session by ID and token and return a connected `Pty` handle. */
|
|
3700
3796
|
async connectPty(sessionId, token, options) {
|
|
3797
|
+
await this.proxy.ensureResolved();
|
|
3701
3798
|
const wsUrl = new URL(this.ptyWsUrl(sessionId, token));
|
|
3702
3799
|
const authToken = wsUrl.searchParams.get("token") ?? token;
|
|
3703
3800
|
const pty = new Pty({
|
|
@@ -3723,6 +3820,7 @@ var init_sandbox = __esm({
|
|
|
3723
3820
|
}
|
|
3724
3821
|
/** Open a TCP tunnel to a port inside the sandbox and return the local listener. */
|
|
3725
3822
|
async createTunnel(remotePort, options) {
|
|
3823
|
+
await this.proxy.ensureResolved();
|
|
3726
3824
|
return TcpTunnel.listen({
|
|
3727
3825
|
baseUrl: this.baseUrl,
|
|
3728
3826
|
wsHeaders: this.wsHeaders,
|
|
@@ -3734,6 +3832,7 @@ var init_sandbox = __esm({
|
|
|
3734
3832
|
}
|
|
3735
3833
|
/** Connect to a sandbox VNC session for programmatic desktop control. */
|
|
3736
3834
|
async connectDesktop(options) {
|
|
3835
|
+
await this.proxy.ensureResolved();
|
|
3737
3836
|
const port = options?.port ?? 5901;
|
|
3738
3837
|
const connectTimeout = options?.connectTimeout ?? 10;
|
|
3739
3838
|
const startMs = Date.now();
|
|
@@ -3818,6 +3917,27 @@ var client_exports = {};
|
|
|
3818
3917
|
__export(client_exports, {
|
|
3819
3918
|
SandboxClient: () => SandboxClient
|
|
3820
3919
|
});
|
|
3920
|
+
function resolveRequestTimeoutMs(options) {
|
|
3921
|
+
if (options?.requestTimeout != null) {
|
|
3922
|
+
return secondsToMillis4(options.requestTimeout);
|
|
3923
|
+
}
|
|
3924
|
+
if (options?.timeoutMs != null) {
|
|
3925
|
+
validateTimeoutMs(options.timeoutMs);
|
|
3926
|
+
return options.timeoutMs;
|
|
3927
|
+
}
|
|
3928
|
+
return DEFAULT_HTTP_TIMEOUT_MS;
|
|
3929
|
+
}
|
|
3930
|
+
function secondsToMillis4(seconds) {
|
|
3931
|
+
if (!Number.isFinite(seconds) || seconds <= 0) {
|
|
3932
|
+
throw new SandboxError("requestTimeout must be a positive number of seconds");
|
|
3933
|
+
}
|
|
3934
|
+
return Math.ceil(seconds * 1e3);
|
|
3935
|
+
}
|
|
3936
|
+
function validateTimeoutMs(timeoutMs) {
|
|
3937
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
3938
|
+
throw new SandboxError("timeoutMs must be a positive number of milliseconds");
|
|
3939
|
+
}
|
|
3940
|
+
}
|
|
3821
3941
|
function sleep2(ms) {
|
|
3822
3942
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3823
3943
|
}
|
|
@@ -3874,7 +3994,7 @@ function validateUserPort(port) {
|
|
|
3874
3994
|
function dedupeAndSortPorts(ports) {
|
|
3875
3995
|
return [...new Set(ports)].sort((a, b) => a - b);
|
|
3876
3996
|
}
|
|
3877
|
-
var SandboxClient, RESERVED_SANDBOX_MANAGEMENT_PORT;
|
|
3997
|
+
var CREATE_SANDBOX_RETRYABLE_STATUS_CODES, CREATE_SANDBOX_ALLOWED_ERROR_STATUS_CODES, SandboxClient, RESERVED_SANDBOX_MANAGEMENT_PORT;
|
|
3878
3998
|
var init_client = __esm({
|
|
3879
3999
|
"src/client.ts"() {
|
|
3880
4000
|
"use strict";
|
|
@@ -3884,6 +4004,8 @@ var init_client = __esm({
|
|
|
3884
4004
|
init_models();
|
|
3885
4005
|
init_sandbox();
|
|
3886
4006
|
init_url();
|
|
4007
|
+
CREATE_SANDBOX_RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([502, 503]);
|
|
4008
|
+
CREATE_SANDBOX_ALLOWED_ERROR_STATUS_CODES = /* @__PURE__ */ new Set([504]);
|
|
3887
4009
|
SandboxClient = class _SandboxClient {
|
|
3888
4010
|
http;
|
|
3889
4011
|
apiUrl;
|
|
@@ -3892,6 +4014,9 @@ var init_client = __esm({
|
|
|
3892
4014
|
projectId;
|
|
3893
4015
|
namespace;
|
|
3894
4016
|
local;
|
|
4017
|
+
maxRetries;
|
|
4018
|
+
retryBackoffMs;
|
|
4019
|
+
requestTimeoutMs;
|
|
3895
4020
|
/** @internal Pass `true` to suppress the deprecation warning when used by `Sandbox.create()` / `Sandbox.connect()`. */
|
|
3896
4021
|
constructor(options, _internal = false) {
|
|
3897
4022
|
if (!_internal) {
|
|
@@ -3905,13 +4030,17 @@ var init_client = __esm({
|
|
|
3905
4030
|
this.projectId = options?.projectId;
|
|
3906
4031
|
this.namespace = options?.namespace ?? NAMESPACE;
|
|
3907
4032
|
this.local = isLocalhost(this.apiUrl);
|
|
4033
|
+
this.maxRetries = options?.maxRetries ?? MAX_RETRIES;
|
|
4034
|
+
this.retryBackoffMs = options?.retryBackoffMs ?? RETRY_BACKOFF_MS;
|
|
4035
|
+
this.requestTimeoutMs = resolveRequestTimeoutMs(options);
|
|
3908
4036
|
this.http = new HttpClient({
|
|
3909
4037
|
baseUrl: resolveSandboxLifecycleUrl(this.apiUrl),
|
|
3910
4038
|
apiKey: this.apiKey,
|
|
3911
4039
|
organizationId: this.organizationId,
|
|
3912
4040
|
projectId: this.projectId,
|
|
3913
|
-
maxRetries:
|
|
3914
|
-
retryBackoffMs:
|
|
4041
|
+
maxRetries: this.maxRetries,
|
|
4042
|
+
retryBackoffMs: this.retryBackoffMs,
|
|
4043
|
+
timeoutMs: this.requestTimeoutMs
|
|
3915
4044
|
});
|
|
3916
4045
|
}
|
|
3917
4046
|
/** Create a client for the TensorLake cloud platform. */
|
|
@@ -3920,19 +4049,46 @@ var init_client = __esm({
|
|
|
3920
4049
|
apiUrl: options?.apiUrl ?? "https://api.tensorlake.ai",
|
|
3921
4050
|
apiKey: options?.apiKey,
|
|
3922
4051
|
organizationId: options?.organizationId,
|
|
3923
|
-
projectId: options?.projectId
|
|
4052
|
+
projectId: options?.projectId,
|
|
4053
|
+
requestTimeout: options?.requestTimeout,
|
|
4054
|
+
timeoutMs: options?.timeoutMs
|
|
3924
4055
|
});
|
|
3925
4056
|
}
|
|
3926
4057
|
/** Create a client for a local Indexify server. */
|
|
3927
4058
|
static forLocalhost(options) {
|
|
3928
4059
|
return new _SandboxClient({
|
|
3929
4060
|
apiUrl: options?.apiUrl ?? "http://localhost:8900",
|
|
3930
|
-
namespace: options?.namespace ?? "default"
|
|
4061
|
+
namespace: options?.namespace ?? "default",
|
|
4062
|
+
requestTimeout: options?.requestTimeout,
|
|
4063
|
+
timeoutMs: options?.timeoutMs
|
|
3931
4064
|
});
|
|
3932
4065
|
}
|
|
3933
4066
|
close() {
|
|
3934
4067
|
this.http.close();
|
|
3935
4068
|
}
|
|
4069
|
+
withRequestTimeout(requestTimeout) {
|
|
4070
|
+
if (requestTimeout == null) {
|
|
4071
|
+
return this;
|
|
4072
|
+
}
|
|
4073
|
+
const timeoutMs = secondsToMillis4(requestTimeout);
|
|
4074
|
+
if (timeoutMs === this.requestTimeoutMs) {
|
|
4075
|
+
return this;
|
|
4076
|
+
}
|
|
4077
|
+
return new _SandboxClient(
|
|
4078
|
+
{
|
|
4079
|
+
apiUrl: this.apiUrl,
|
|
4080
|
+
apiKey: this.apiKey,
|
|
4081
|
+
organizationId: this.organizationId,
|
|
4082
|
+
projectId: this.projectId,
|
|
4083
|
+
namespace: this.namespace,
|
|
4084
|
+
maxRetries: this.maxRetries,
|
|
4085
|
+
retryBackoffMs: this.retryBackoffMs,
|
|
4086
|
+
timeoutMs
|
|
4087
|
+
},
|
|
4088
|
+
/* _internal */
|
|
4089
|
+
true
|
|
4090
|
+
);
|
|
4091
|
+
}
|
|
3936
4092
|
// --- Path helper ---
|
|
3937
4093
|
path(subpath) {
|
|
3938
4094
|
return lifecyclePath(subpath, this.local, this.namespace);
|
|
@@ -3963,7 +4119,11 @@ var init_client = __esm({
|
|
|
3963
4119
|
const raw = await this.http.requestJson(
|
|
3964
4120
|
"POST",
|
|
3965
4121
|
this.path("sandboxes"),
|
|
3966
|
-
{
|
|
4122
|
+
{
|
|
4123
|
+
body,
|
|
4124
|
+
retryableStatusCodes: CREATE_SANDBOX_RETRYABLE_STATUS_CODES,
|
|
4125
|
+
allowedErrorStatusCodes: CREATE_SANDBOX_ALLOWED_ERROR_STATUS_CODES
|
|
4126
|
+
}
|
|
3967
4127
|
);
|
|
3968
4128
|
const result = fromSnakeKeys(raw, "sandboxId");
|
|
3969
4129
|
return Object.assign(result, { traceId: raw.traceId });
|
|
@@ -4053,6 +4213,7 @@ var init_client = __esm({
|
|
|
4053
4213
|
return {
|
|
4054
4214
|
allowUnauthenticatedAccess: info.allowUnauthenticatedAccess ?? false,
|
|
4055
4215
|
exposedPorts: dedupeAndSortPorts(info.exposedPorts ?? []),
|
|
4216
|
+
ingressEndpoint: info.ingressEndpoint,
|
|
4056
4217
|
sandboxUrl: info.sandboxUrl
|
|
4057
4218
|
};
|
|
4058
4219
|
}
|
|
@@ -4156,7 +4317,11 @@ var init_client = __esm({
|
|
|
4156
4317
|
async claim(poolId) {
|
|
4157
4318
|
const raw = await this.http.requestJson(
|
|
4158
4319
|
"POST",
|
|
4159
|
-
this.path(`sandbox-pools/${poolId}/sandboxes`)
|
|
4320
|
+
this.path(`sandbox-pools/${poolId}/sandboxes`),
|
|
4321
|
+
{
|
|
4322
|
+
retryableStatusCodes: CREATE_SANDBOX_RETRYABLE_STATUS_CODES,
|
|
4323
|
+
allowedErrorStatusCodes: CREATE_SANDBOX_ALLOWED_ERROR_STATUS_CODES
|
|
4324
|
+
}
|
|
4160
4325
|
);
|
|
4161
4326
|
const result = fromSnakeKeys(raw, "sandboxId");
|
|
4162
4327
|
return Object.assign(result, { traceId: raw.traceId });
|
|
@@ -4318,7 +4483,7 @@ var init_client = __esm({
|
|
|
4318
4483
|
}
|
|
4319
4484
|
// --- Connect ---
|
|
4320
4485
|
/** Return a `Sandbox` handle for an existing running sandbox without verifying it exists. */
|
|
4321
|
-
connect(identifier, proxyUrl, routingHint) {
|
|
4486
|
+
connect(identifier, proxyUrl, routingHint, requestTimeout) {
|
|
4322
4487
|
const resolvedProxy = proxyUrl ?? resolveProxyUrl(this.apiUrl);
|
|
4323
4488
|
return new Sandbox({
|
|
4324
4489
|
sandboxId: identifier,
|
|
@@ -4326,32 +4491,41 @@ var init_client = __esm({
|
|
|
4326
4491
|
apiKey: this.apiKey,
|
|
4327
4492
|
organizationId: this.organizationId,
|
|
4328
4493
|
projectId: this.projectId,
|
|
4329
|
-
routingHint
|
|
4494
|
+
routingHint,
|
|
4495
|
+
resolveProxyInfo: proxyUrl == null ? async (currentIdentifier) => this.get(currentIdentifier) : void 0,
|
|
4496
|
+
requestTimeout
|
|
4330
4497
|
});
|
|
4331
4498
|
}
|
|
4332
4499
|
/**
|
|
4333
4500
|
* Create a sandbox, wait for it to reach `Running`, and return a connected handle.
|
|
4334
4501
|
*
|
|
4335
|
-
* Blocks until the sandbox is ready or `
|
|
4502
|
+
* Blocks until the sandbox is ready or `requestTimeout` elapses. The returned
|
|
4336
4503
|
* `Sandbox` auto-terminates when `terminate()` is called.
|
|
4337
4504
|
*
|
|
4338
|
-
* @param options.
|
|
4505
|
+
* @param options.requestTimeout - Max seconds to wait for `Running` status (default: client requestTimeout).
|
|
4506
|
+
* @param options.startupTimeout - Deprecated alias for `requestTimeout`.
|
|
4339
4507
|
* @throws {SandboxError} If the sandbox terminates during startup or the timeout elapses.
|
|
4340
4508
|
*/
|
|
4341
4509
|
async createAndConnect(options) {
|
|
4342
|
-
const
|
|
4343
|
-
const
|
|
4510
|
+
const requestTimeout = options?.requestTimeout ?? options?.startupTimeout ?? this.requestTimeoutMs / 1e3;
|
|
4511
|
+
const requestClient = this.withRequestTimeout(requestTimeout);
|
|
4512
|
+
const result = options?.poolId != null ? await requestClient.claim(options.poolId) : await requestClient.create(options);
|
|
4344
4513
|
const requestedName = options?.poolId != null ? null : options?.name ?? null;
|
|
4345
|
-
const finishConnect = (routingHint, name) => {
|
|
4346
|
-
const sandbox =
|
|
4347
|
-
|
|
4514
|
+
const finishConnect = (routingHint, name, ingressEndpoint) => {
|
|
4515
|
+
const sandbox = requestClient.connect(
|
|
4516
|
+
result.sandboxId,
|
|
4517
|
+
options?.proxyUrl ?? ingressEndpoint,
|
|
4518
|
+
routingHint,
|
|
4519
|
+
requestTimeout
|
|
4520
|
+
);
|
|
4521
|
+
sandbox._setOwner(requestClient);
|
|
4348
4522
|
sandbox.traceId = result.traceId;
|
|
4349
4523
|
sandbox._setLifecycleIdentifier(result.sandboxId);
|
|
4350
4524
|
sandbox._setName(name ?? requestedName);
|
|
4351
4525
|
return sandbox;
|
|
4352
4526
|
};
|
|
4353
4527
|
if (result.status === "running" /* RUNNING */) {
|
|
4354
|
-
return finishConnect(result.routingHint, result.name);
|
|
4528
|
+
return finishConnect(result.routingHint, result.name, result.ingressEndpoint);
|
|
4355
4529
|
}
|
|
4356
4530
|
if (result.status === "suspended" /* SUSPENDED */ || result.status === "terminated" /* TERMINATED */) {
|
|
4357
4531
|
throw new SandboxError(
|
|
@@ -4361,11 +4535,20 @@ var init_client = __esm({
|
|
|
4361
4535
|
})
|
|
4362
4536
|
);
|
|
4363
4537
|
}
|
|
4364
|
-
|
|
4538
|
+
if (result.status === "timeout" /* TIMEOUT */) {
|
|
4539
|
+
try {
|
|
4540
|
+
await requestClient.delete(result.sandboxId);
|
|
4541
|
+
} catch {
|
|
4542
|
+
}
|
|
4543
|
+
throw new SandboxError(
|
|
4544
|
+
`Sandbox ${result.sandboxId} did not start within ${requestTimeout}s`
|
|
4545
|
+
);
|
|
4546
|
+
}
|
|
4547
|
+
const deadline = Date.now() + secondsToMillis4(requestTimeout);
|
|
4365
4548
|
while (Date.now() < deadline) {
|
|
4366
|
-
const info = await
|
|
4549
|
+
const info = await requestClient.get(result.sandboxId);
|
|
4367
4550
|
if (info.status === "running" /* RUNNING */) {
|
|
4368
|
-
return finishConnect(info.routingHint, info.name);
|
|
4551
|
+
return finishConnect(info.routingHint, info.name, info.ingressEndpoint);
|
|
4369
4552
|
}
|
|
4370
4553
|
if (info.status === "suspended" /* SUSPENDED */ || info.status === "terminated" /* TERMINATED */) {
|
|
4371
4554
|
throw new SandboxError(
|
|
@@ -4378,11 +4561,11 @@ var init_client = __esm({
|
|
|
4378
4561
|
await sleep2(500);
|
|
4379
4562
|
}
|
|
4380
4563
|
try {
|
|
4381
|
-
await
|
|
4564
|
+
await requestClient.delete(result.sandboxId);
|
|
4382
4565
|
} catch {
|
|
4383
4566
|
}
|
|
4384
4567
|
throw new SandboxError(
|
|
4385
|
-
`Sandbox ${result.sandboxId} did not start within ${
|
|
4568
|
+
`Sandbox ${result.sandboxId} did not start within ${requestTimeout}s`
|
|
4386
4569
|
);
|
|
4387
4570
|
}
|
|
4388
4571
|
};
|
|
@@ -4772,7 +4955,8 @@ __export(index_exports, {
|
|
|
4772
4955
|
StdinMode: () => StdinMode,
|
|
4773
4956
|
TcpTunnel: () => TcpTunnel,
|
|
4774
4957
|
createSandboxImage: () => createSandboxImage,
|
|
4775
|
-
dockerfileContent: () => dockerfileContent
|
|
4958
|
+
dockerfileContent: () => dockerfileContent,
|
|
4959
|
+
sandboxUrlFromIngressEndpoint: () => sandboxUrlFromIngressEndpoint
|
|
4776
4960
|
});
|
|
4777
4961
|
module.exports = __toCommonJS(index_exports);
|
|
4778
4962
|
init_client();
|
|
@@ -5165,6 +5349,7 @@ var APIClient = class {
|
|
|
5165
5349
|
// src/index.ts
|
|
5166
5350
|
init_sandbox_image();
|
|
5167
5351
|
init_image();
|
|
5352
|
+
init_url();
|
|
5168
5353
|
init_errors();
|
|
5169
5354
|
init_models();
|
|
5170
5355
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -5195,6 +5380,7 @@ init_models();
|
|
|
5195
5380
|
StdinMode,
|
|
5196
5381
|
TcpTunnel,
|
|
5197
5382
|
createSandboxImage,
|
|
5198
|
-
dockerfileContent
|
|
5383
|
+
dockerfileContent,
|
|
5384
|
+
sandboxUrlFromIngressEndpoint
|
|
5199
5385
|
});
|
|
5200
5386
|
//# sourceMappingURL=index.cjs.map
|