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
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ var SDK_VERSION, API_URL, API_KEY, NAMESPACE, SANDBOX_PROXY_URL, DEFAULT_HTTP_TI
|
|
|
19
19
|
var init_defaults = __esm({
|
|
20
20
|
"src/defaults.ts"() {
|
|
21
21
|
"use strict";
|
|
22
|
-
SDK_VERSION = "0.5.
|
|
22
|
+
SDK_VERSION = "0.5.31";
|
|
23
23
|
API_URL = process.env.TENSORLAKE_API_URL ?? "https://api.tensorlake.ai";
|
|
24
24
|
API_KEY = process.env.TENSORLAKE_API_KEY ?? void 0;
|
|
25
25
|
NAMESPACE = process.env.INDEXIFY_NAMESPACE ?? "default";
|
|
@@ -184,12 +184,13 @@ function anySignal(signals) {
|
|
|
184
184
|
function sleep(ms) {
|
|
185
185
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
186
186
|
}
|
|
187
|
-
var HttpClient;
|
|
187
|
+
var REQUEST_TIMEOUT_HEADER, HttpClient;
|
|
188
188
|
var init_http = __esm({
|
|
189
189
|
"src/http.ts"() {
|
|
190
190
|
"use strict";
|
|
191
191
|
init_defaults();
|
|
192
192
|
init_errors();
|
|
193
|
+
REQUEST_TIMEOUT_HEADER = "X-Tensorlake-Request-Timeout-Ms";
|
|
193
194
|
setGlobalDispatcher(
|
|
194
195
|
new Agent({
|
|
195
196
|
keepAliveTimeout: 6e4,
|
|
@@ -208,10 +209,13 @@ var init_http = __esm({
|
|
|
208
209
|
this.baseUrl = url.endsWith("/") ? url.slice(0, -1) : url;
|
|
209
210
|
this.maxRetries = options.maxRetries ?? MAX_RETRIES;
|
|
210
211
|
this.retryBackoffMs = options.retryBackoffMs ?? RETRY_BACKOFF_MS;
|
|
211
|
-
this.timeoutMs = options.timeoutMs
|
|
212
|
+
this.timeoutMs = options.timeoutMs === void 0 ? DEFAULT_HTTP_TIMEOUT_MS : options.timeoutMs;
|
|
212
213
|
this.headers = {
|
|
213
214
|
"User-Agent": `tensorlake-typescript-sdk/${SDK_VERSION}`
|
|
214
215
|
};
|
|
216
|
+
if (this.timeoutMs != null) {
|
|
217
|
+
this.headers[REQUEST_TIMEOUT_HEADER] = String(this.timeoutMs);
|
|
218
|
+
}
|
|
215
219
|
if (options.apiKey) {
|
|
216
220
|
this.headers["Authorization"] = `Bearer ${options.apiKey}`;
|
|
217
221
|
}
|
|
@@ -240,7 +244,10 @@ var init_http = __esm({
|
|
|
240
244
|
const response = await this.requestResponse(method, path2, {
|
|
241
245
|
json: options?.body,
|
|
242
246
|
headers: options?.headers,
|
|
243
|
-
signal: options?.signal
|
|
247
|
+
signal: options?.signal,
|
|
248
|
+
retryableStatusCodes: options?.retryableStatusCodes,
|
|
249
|
+
allowedErrorStatusCodes: options?.allowedErrorStatusCodes,
|
|
250
|
+
allowHttpErrors: options?.allowHttpErrors
|
|
244
251
|
});
|
|
245
252
|
const text = await response.text();
|
|
246
253
|
const data = text ? JSON.parse(text) : void 0;
|
|
@@ -292,7 +299,9 @@ var init_http = __esm({
|
|
|
292
299
|
body,
|
|
293
300
|
headers,
|
|
294
301
|
options?.signal,
|
|
295
|
-
options?.allowHttpErrors ?? false
|
|
302
|
+
options?.allowHttpErrors ?? false,
|
|
303
|
+
options?.retryableStatusCodes ?? RETRYABLE_STATUS_CODES,
|
|
304
|
+
options?.allowedErrorStatusCodes ?? /* @__PURE__ */ new Set()
|
|
296
305
|
);
|
|
297
306
|
return withTraceId(response, traceId);
|
|
298
307
|
}
|
|
@@ -302,7 +311,7 @@ var init_http = __esm({
|
|
|
302
311
|
const spanId = randomHex(8);
|
|
303
312
|
return { traceparent: `00-${traceId}-${spanId}-01`, traceId };
|
|
304
313
|
}
|
|
305
|
-
async doFetch(method, path2, body, headers, signal, allowHttpErrors = false) {
|
|
314
|
+
async doFetch(method, path2, body, headers, signal, allowHttpErrors = false, retryableStatusCodes = RETRYABLE_STATUS_CODES, allowedErrorStatusCodes = /* @__PURE__ */ new Set()) {
|
|
306
315
|
const url = `${this.baseUrl}${path2}`;
|
|
307
316
|
const { traceparent, traceId } = _HttpClient.makeTraceparent();
|
|
308
317
|
headers["traceparent"] = traceparent;
|
|
@@ -313,10 +322,7 @@ var init_http = __esm({
|
|
|
313
322
|
await sleep(delay);
|
|
314
323
|
}
|
|
315
324
|
this.abortController = new AbortController();
|
|
316
|
-
const timeoutId = setTimeout(
|
|
317
|
-
() => this.abortController?.abort(),
|
|
318
|
-
this.timeoutMs
|
|
319
|
-
);
|
|
325
|
+
const timeoutId = this.timeoutMs == null ? null : setTimeout(() => this.abortController?.abort(), this.timeoutMs);
|
|
320
326
|
const combinedSignal = signal ? anySignal([signal, this.abortController.signal]) : this.abortController.signal;
|
|
321
327
|
try {
|
|
322
328
|
const response = await undiciFetch(url, {
|
|
@@ -325,22 +331,22 @@ var init_http = __esm({
|
|
|
325
331
|
body,
|
|
326
332
|
signal: combinedSignal
|
|
327
333
|
});
|
|
328
|
-
clearTimeout(timeoutId);
|
|
334
|
+
if (timeoutId != null) clearTimeout(timeoutId);
|
|
329
335
|
if (response.ok) return { response, traceId };
|
|
330
|
-
if (
|
|
336
|
+
if (retryableStatusCodes.has(response.status) && attempt < this.maxRetries) {
|
|
331
337
|
lastError = new RemoteAPIError(
|
|
332
338
|
response.status,
|
|
333
339
|
await response.text().catch(() => "")
|
|
334
340
|
);
|
|
335
341
|
continue;
|
|
336
342
|
}
|
|
337
|
-
if (allowHttpErrors) {
|
|
343
|
+
if (allowHttpErrors || allowedErrorStatusCodes.has(response.status)) {
|
|
338
344
|
return { response, traceId };
|
|
339
345
|
}
|
|
340
346
|
const errorBody = await response.text().catch(() => "");
|
|
341
347
|
throwMappedError(response.status, errorBody, path2);
|
|
342
348
|
} catch (err) {
|
|
343
|
-
clearTimeout(timeoutId);
|
|
349
|
+
if (timeoutId != null) clearTimeout(timeoutId);
|
|
344
350
|
if (err instanceof RemoteAPIError || err instanceof SandboxNotFoundError || err instanceof PoolNotFoundError || err instanceof PoolInUseError) {
|
|
345
351
|
throw err;
|
|
346
352
|
}
|
|
@@ -412,6 +418,7 @@ var init_models = __esm({
|
|
|
412
418
|
SandboxStatus3["SUSPENDING"] = "suspending";
|
|
413
419
|
SandboxStatus3["SUSPENDED"] = "suspended";
|
|
414
420
|
SandboxStatus3["TERMINATED"] = "terminated";
|
|
421
|
+
SandboxStatus3["TIMEOUT"] = "timeout";
|
|
415
422
|
return SandboxStatus3;
|
|
416
423
|
})(SandboxStatus || {});
|
|
417
424
|
SnapshotStatus = /* @__PURE__ */ ((SnapshotStatus2) => {
|
|
@@ -2957,6 +2964,14 @@ function resolveProxyTarget(proxyUrl, sandboxId) {
|
|
|
2957
2964
|
};
|
|
2958
2965
|
}
|
|
2959
2966
|
}
|
|
2967
|
+
function sandboxUrlFromIngressEndpoint(ingressEndpoint, sandboxId, port = 9501) {
|
|
2968
|
+
const parsed = new URL(ingressEndpoint);
|
|
2969
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
2970
|
+
throw new Error("ingressEndpoint must be an absolute http(s) URL");
|
|
2971
|
+
}
|
|
2972
|
+
const label = port === 9501 ? sandboxId : `${port}-${sandboxId}`;
|
|
2973
|
+
return `${parsed.protocol}//${label}.${parsed.host}`;
|
|
2974
|
+
}
|
|
2960
2975
|
function resolveSandboxLifecycleUrl(apiUrl) {
|
|
2961
2976
|
if (isLocalhost(apiUrl)) return apiUrl;
|
|
2962
2977
|
try {
|
|
@@ -3016,7 +3031,13 @@ function sendPtyFrame(socket, frame) {
|
|
|
3016
3031
|
socket.send(frame, (error) => error ? reject(error) : resolve());
|
|
3017
3032
|
});
|
|
3018
3033
|
}
|
|
3019
|
-
|
|
3034
|
+
function secondsToMillis3(seconds) {
|
|
3035
|
+
if (!Number.isFinite(seconds) || seconds <= 0) {
|
|
3036
|
+
throw new SandboxError("requestTimeout must be a positive number of seconds");
|
|
3037
|
+
}
|
|
3038
|
+
return Math.ceil(seconds * 1e3);
|
|
3039
|
+
}
|
|
3040
|
+
var DEFAULT_PROCESS_USER, SandboxProxyConnection, PTY_OP_DATA, PTY_OP_RESIZE, PTY_OP_READY, PTY_OP_EXIT, Pty, Sandbox;
|
|
3020
3041
|
var init_sandbox = __esm({
|
|
3021
3042
|
"src/sandbox.ts"() {
|
|
3022
3043
|
"use strict";
|
|
@@ -3029,6 +3050,99 @@ var init_sandbox = __esm({
|
|
|
3029
3050
|
init_sse();
|
|
3030
3051
|
init_url();
|
|
3031
3052
|
DEFAULT_PROCESS_USER = "tl-user";
|
|
3053
|
+
SandboxProxyConnection = class {
|
|
3054
|
+
constructor(sandbox, options) {
|
|
3055
|
+
this.sandbox = sandbox;
|
|
3056
|
+
this.options = options;
|
|
3057
|
+
this.routingHint = options.routingHint;
|
|
3058
|
+
this.http = this.configureProxy(
|
|
3059
|
+
options.proxyUrl ?? SANDBOX_PROXY_URL,
|
|
3060
|
+
options.sandboxId,
|
|
3061
|
+
options.routingHint
|
|
3062
|
+
);
|
|
3063
|
+
this.resolveProxyInfo = options.resolveProxyInfo;
|
|
3064
|
+
}
|
|
3065
|
+
baseUrl = "";
|
|
3066
|
+
wsHeaders = {};
|
|
3067
|
+
http;
|
|
3068
|
+
resolveProxyInfo;
|
|
3069
|
+
resolvePromise = null;
|
|
3070
|
+
routingHint;
|
|
3071
|
+
async ensureResolved() {
|
|
3072
|
+
if (this.resolveProxyInfo == null) {
|
|
3073
|
+
return;
|
|
3074
|
+
}
|
|
3075
|
+
if (this.resolvePromise != null) {
|
|
3076
|
+
return this.resolvePromise;
|
|
3077
|
+
}
|
|
3078
|
+
this.resolvePromise = this.resolveProxyInfo(this.sandbox._getLifecycleIdentifier()).then((info) => {
|
|
3079
|
+
this.resolveProxyInfo = void 0;
|
|
3080
|
+
this.sandbox.traceId = info.traceId;
|
|
3081
|
+
this.sandbox._setLifecycleIdentifier(info.sandboxId);
|
|
3082
|
+
this.sandbox._setName(info.name ?? null);
|
|
3083
|
+
this.routingHint = this.routingHint ?? info.routingHint;
|
|
3084
|
+
const proxyUrl = info.ingressEndpoint ?? this.options.proxyUrl ?? SANDBOX_PROXY_URL;
|
|
3085
|
+
const nextHttp = this.configureProxy(proxyUrl, info.sandboxId, this.routingHint);
|
|
3086
|
+
this.http.close();
|
|
3087
|
+
this.http = nextHttp;
|
|
3088
|
+
}).finally(() => {
|
|
3089
|
+
this.resolvePromise = null;
|
|
3090
|
+
});
|
|
3091
|
+
return this.resolvePromise;
|
|
3092
|
+
}
|
|
3093
|
+
async requestJson(method, path2, options) {
|
|
3094
|
+
await this.ensureResolved();
|
|
3095
|
+
return this.http.requestJson(method, path2, options);
|
|
3096
|
+
}
|
|
3097
|
+
async requestBytes(method, path2, options) {
|
|
3098
|
+
await this.ensureResolved();
|
|
3099
|
+
return this.http.requestBytes(method, path2, options);
|
|
3100
|
+
}
|
|
3101
|
+
async requestStream(method, path2, options) {
|
|
3102
|
+
await this.ensureResolved();
|
|
3103
|
+
return this.http.requestStream(method, path2, options);
|
|
3104
|
+
}
|
|
3105
|
+
async requestResponse(method, path2, options) {
|
|
3106
|
+
await this.ensureResolved();
|
|
3107
|
+
return this.http.requestResponse(method, path2, options);
|
|
3108
|
+
}
|
|
3109
|
+
close() {
|
|
3110
|
+
this.http.close();
|
|
3111
|
+
}
|
|
3112
|
+
configureProxy(proxyUrl, sandboxId, routingHint) {
|
|
3113
|
+
const { baseUrl, hostHeader, sandboxIdHeader } = resolveProxyTarget(
|
|
3114
|
+
proxyUrl,
|
|
3115
|
+
sandboxId
|
|
3116
|
+
);
|
|
3117
|
+
this.baseUrl = baseUrl;
|
|
3118
|
+
this.wsHeaders = {};
|
|
3119
|
+
if (this.options.apiKey) {
|
|
3120
|
+
this.wsHeaders.Authorization = `Bearer ${this.options.apiKey}`;
|
|
3121
|
+
}
|
|
3122
|
+
if (this.options.organizationId) {
|
|
3123
|
+
this.wsHeaders["X-Forwarded-Organization-Id"] = this.options.organizationId;
|
|
3124
|
+
}
|
|
3125
|
+
if (this.options.projectId) {
|
|
3126
|
+
this.wsHeaders["X-Forwarded-Project-Id"] = this.options.projectId;
|
|
3127
|
+
}
|
|
3128
|
+
if (hostHeader) {
|
|
3129
|
+
this.wsHeaders.Host = hostHeader;
|
|
3130
|
+
}
|
|
3131
|
+
if (sandboxIdHeader) {
|
|
3132
|
+
this.wsHeaders["X-Tensorlake-Sandbox-Id"] = sandboxIdHeader;
|
|
3133
|
+
}
|
|
3134
|
+
return new HttpClient({
|
|
3135
|
+
baseUrl,
|
|
3136
|
+
apiKey: this.options.apiKey,
|
|
3137
|
+
organizationId: this.options.organizationId,
|
|
3138
|
+
projectId: this.options.projectId,
|
|
3139
|
+
hostHeader,
|
|
3140
|
+
sandboxIdHeader,
|
|
3141
|
+
routingHint,
|
|
3142
|
+
timeoutMs: this.options.requestTimeout != null ? secondsToMillis3(this.options.requestTimeout) : this.options.timeoutMs ?? null
|
|
3143
|
+
});
|
|
3144
|
+
}
|
|
3145
|
+
};
|
|
3032
3146
|
PTY_OP_DATA = 0;
|
|
3033
3147
|
PTY_OP_RESIZE = 1;
|
|
3034
3148
|
PTY_OP_READY = 2;
|
|
@@ -3194,9 +3308,8 @@ var init_sandbox = __esm({
|
|
|
3194
3308
|
Sandbox = class {
|
|
3195
3309
|
sandboxId;
|
|
3196
3310
|
traceId = null;
|
|
3311
|
+
proxy;
|
|
3197
3312
|
http;
|
|
3198
|
-
baseUrl;
|
|
3199
|
-
wsHeaders;
|
|
3200
3313
|
ownsSandbox = false;
|
|
3201
3314
|
lifecycleClient = null;
|
|
3202
3315
|
lifecycleIdentifier;
|
|
@@ -3204,34 +3317,14 @@ var init_sandbox = __esm({
|
|
|
3204
3317
|
constructor(options) {
|
|
3205
3318
|
this.sandboxId = options.sandboxId;
|
|
3206
3319
|
this.lifecycleIdentifier = options.sandboxId;
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
this.wsHeaders["X-Forwarded-Organization-Id"] = options.organizationId;
|
|
3216
|
-
}
|
|
3217
|
-
if (options.projectId) {
|
|
3218
|
-
this.wsHeaders["X-Forwarded-Project-Id"] = options.projectId;
|
|
3219
|
-
}
|
|
3220
|
-
if (hostHeader) {
|
|
3221
|
-
this.wsHeaders.Host = hostHeader;
|
|
3222
|
-
}
|
|
3223
|
-
if (sandboxIdHeader) {
|
|
3224
|
-
this.wsHeaders["X-Tensorlake-Sandbox-Id"] = sandboxIdHeader;
|
|
3225
|
-
}
|
|
3226
|
-
this.http = new HttpClient({
|
|
3227
|
-
baseUrl,
|
|
3228
|
-
apiKey: options.apiKey,
|
|
3229
|
-
organizationId: options.organizationId,
|
|
3230
|
-
projectId: options.projectId,
|
|
3231
|
-
hostHeader,
|
|
3232
|
-
sandboxIdHeader,
|
|
3233
|
-
routingHint: options.routingHint
|
|
3234
|
-
});
|
|
3320
|
+
this.proxy = new SandboxProxyConnection(this, options);
|
|
3321
|
+
this.http = this.proxy;
|
|
3322
|
+
}
|
|
3323
|
+
get baseUrl() {
|
|
3324
|
+
return this.proxy.baseUrl;
|
|
3325
|
+
}
|
|
3326
|
+
get wsHeaders() {
|
|
3327
|
+
return this.proxy.wsHeaders;
|
|
3235
3328
|
}
|
|
3236
3329
|
get name() {
|
|
3237
3330
|
return this.sandboxName;
|
|
@@ -3244,6 +3337,10 @@ var init_sandbox = __esm({
|
|
|
3244
3337
|
_setLifecycleIdentifier(identifier) {
|
|
3245
3338
|
this.lifecycleIdentifier = identifier;
|
|
3246
3339
|
}
|
|
3340
|
+
/** @internal Used by the lazy proxy resolver. */
|
|
3341
|
+
_getLifecycleIdentifier() {
|
|
3342
|
+
return this.lifecycleIdentifier;
|
|
3343
|
+
}
|
|
3247
3344
|
/** @internal Used by SandboxClient.createAndConnect to set ownership. */
|
|
3248
3345
|
_setOwner(client) {
|
|
3249
3346
|
this.ownsSandbox = true;
|
|
@@ -3263,16 +3360,14 @@ var init_sandbox = __esm({
|
|
|
3263
3360
|
/* _internal */
|
|
3264
3361
|
true
|
|
3265
3362
|
);
|
|
3266
|
-
|
|
3267
|
-
sandbox.lifecycleClient = client;
|
|
3268
|
-
return sandbox;
|
|
3363
|
+
return client.createAndConnect(options);
|
|
3269
3364
|
}
|
|
3270
3365
|
/**
|
|
3271
3366
|
* Attach to an existing sandbox and return a connected handle.
|
|
3272
3367
|
*
|
|
3273
|
-
*
|
|
3274
|
-
*
|
|
3275
|
-
* sandbox — call `sandbox.resume()` explicitly.
|
|
3368
|
+
* When `proxyUrl` is omitted, resolves the sandbox first so the handle uses
|
|
3369
|
+
* the correct cloud/region ingress endpoint. Does **not** auto-resume a
|
|
3370
|
+
* suspended sandbox — call `sandbox.resume()` explicitly.
|
|
3276
3371
|
*/
|
|
3277
3372
|
static async connect(options) {
|
|
3278
3373
|
const { SandboxClient: SandboxClient2 } = await Promise.resolve().then(() => (init_client(), client_exports));
|
|
@@ -3284,7 +3379,8 @@ var init_sandbox = __esm({
|
|
|
3284
3379
|
const sandbox = client.connect(
|
|
3285
3380
|
options.sandboxId,
|
|
3286
3381
|
options.proxyUrl,
|
|
3287
|
-
options.routingHint
|
|
3382
|
+
options.routingHint,
|
|
3383
|
+
options.requestTimeout
|
|
3288
3384
|
);
|
|
3289
3385
|
sandbox.lifecycleClient = client;
|
|
3290
3386
|
return sandbox;
|
|
@@ -3686,6 +3782,7 @@ var init_sandbox = __esm({
|
|
|
3686
3782
|
}
|
|
3687
3783
|
/** Attach to an existing PTY session by ID and token and return a connected `Pty` handle. */
|
|
3688
3784
|
async connectPty(sessionId, token, options) {
|
|
3785
|
+
await this.proxy.ensureResolved();
|
|
3689
3786
|
const wsUrl = new URL(this.ptyWsUrl(sessionId, token));
|
|
3690
3787
|
const authToken = wsUrl.searchParams.get("token") ?? token;
|
|
3691
3788
|
const pty = new Pty({
|
|
@@ -3711,6 +3808,7 @@ var init_sandbox = __esm({
|
|
|
3711
3808
|
}
|
|
3712
3809
|
/** Open a TCP tunnel to a port inside the sandbox and return the local listener. */
|
|
3713
3810
|
async createTunnel(remotePort, options) {
|
|
3811
|
+
await this.proxy.ensureResolved();
|
|
3714
3812
|
return TcpTunnel.listen({
|
|
3715
3813
|
baseUrl: this.baseUrl,
|
|
3716
3814
|
wsHeaders: this.wsHeaders,
|
|
@@ -3722,6 +3820,7 @@ var init_sandbox = __esm({
|
|
|
3722
3820
|
}
|
|
3723
3821
|
/** Connect to a sandbox VNC session for programmatic desktop control. */
|
|
3724
3822
|
async connectDesktop(options) {
|
|
3823
|
+
await this.proxy.ensureResolved();
|
|
3725
3824
|
const port = options?.port ?? 5901;
|
|
3726
3825
|
const connectTimeout = options?.connectTimeout ?? 10;
|
|
3727
3826
|
const startMs = Date.now();
|
|
@@ -3806,6 +3905,27 @@ var client_exports = {};
|
|
|
3806
3905
|
__export(client_exports, {
|
|
3807
3906
|
SandboxClient: () => SandboxClient
|
|
3808
3907
|
});
|
|
3908
|
+
function resolveRequestTimeoutMs(options) {
|
|
3909
|
+
if (options?.requestTimeout != null) {
|
|
3910
|
+
return secondsToMillis4(options.requestTimeout);
|
|
3911
|
+
}
|
|
3912
|
+
if (options?.timeoutMs != null) {
|
|
3913
|
+
validateTimeoutMs(options.timeoutMs);
|
|
3914
|
+
return options.timeoutMs;
|
|
3915
|
+
}
|
|
3916
|
+
return DEFAULT_HTTP_TIMEOUT_MS;
|
|
3917
|
+
}
|
|
3918
|
+
function secondsToMillis4(seconds) {
|
|
3919
|
+
if (!Number.isFinite(seconds) || seconds <= 0) {
|
|
3920
|
+
throw new SandboxError("requestTimeout must be a positive number of seconds");
|
|
3921
|
+
}
|
|
3922
|
+
return Math.ceil(seconds * 1e3);
|
|
3923
|
+
}
|
|
3924
|
+
function validateTimeoutMs(timeoutMs) {
|
|
3925
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
3926
|
+
throw new SandboxError("timeoutMs must be a positive number of milliseconds");
|
|
3927
|
+
}
|
|
3928
|
+
}
|
|
3809
3929
|
function sleep2(ms) {
|
|
3810
3930
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3811
3931
|
}
|
|
@@ -3862,7 +3982,7 @@ function validateUserPort(port) {
|
|
|
3862
3982
|
function dedupeAndSortPorts(ports) {
|
|
3863
3983
|
return [...new Set(ports)].sort((a, b) => a - b);
|
|
3864
3984
|
}
|
|
3865
|
-
var SandboxClient, RESERVED_SANDBOX_MANAGEMENT_PORT;
|
|
3985
|
+
var CREATE_SANDBOX_RETRYABLE_STATUS_CODES, CREATE_SANDBOX_ALLOWED_ERROR_STATUS_CODES, SandboxClient, RESERVED_SANDBOX_MANAGEMENT_PORT;
|
|
3866
3986
|
var init_client = __esm({
|
|
3867
3987
|
"src/client.ts"() {
|
|
3868
3988
|
"use strict";
|
|
@@ -3872,6 +3992,8 @@ var init_client = __esm({
|
|
|
3872
3992
|
init_models();
|
|
3873
3993
|
init_sandbox();
|
|
3874
3994
|
init_url();
|
|
3995
|
+
CREATE_SANDBOX_RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([502, 503]);
|
|
3996
|
+
CREATE_SANDBOX_ALLOWED_ERROR_STATUS_CODES = /* @__PURE__ */ new Set([504]);
|
|
3875
3997
|
SandboxClient = class _SandboxClient {
|
|
3876
3998
|
http;
|
|
3877
3999
|
apiUrl;
|
|
@@ -3880,6 +4002,9 @@ var init_client = __esm({
|
|
|
3880
4002
|
projectId;
|
|
3881
4003
|
namespace;
|
|
3882
4004
|
local;
|
|
4005
|
+
maxRetries;
|
|
4006
|
+
retryBackoffMs;
|
|
4007
|
+
requestTimeoutMs;
|
|
3883
4008
|
/** @internal Pass `true` to suppress the deprecation warning when used by `Sandbox.create()` / `Sandbox.connect()`. */
|
|
3884
4009
|
constructor(options, _internal = false) {
|
|
3885
4010
|
if (!_internal) {
|
|
@@ -3893,13 +4018,17 @@ var init_client = __esm({
|
|
|
3893
4018
|
this.projectId = options?.projectId;
|
|
3894
4019
|
this.namespace = options?.namespace ?? NAMESPACE;
|
|
3895
4020
|
this.local = isLocalhost(this.apiUrl);
|
|
4021
|
+
this.maxRetries = options?.maxRetries ?? MAX_RETRIES;
|
|
4022
|
+
this.retryBackoffMs = options?.retryBackoffMs ?? RETRY_BACKOFF_MS;
|
|
4023
|
+
this.requestTimeoutMs = resolveRequestTimeoutMs(options);
|
|
3896
4024
|
this.http = new HttpClient({
|
|
3897
4025
|
baseUrl: resolveSandboxLifecycleUrl(this.apiUrl),
|
|
3898
4026
|
apiKey: this.apiKey,
|
|
3899
4027
|
organizationId: this.organizationId,
|
|
3900
4028
|
projectId: this.projectId,
|
|
3901
|
-
maxRetries:
|
|
3902
|
-
retryBackoffMs:
|
|
4029
|
+
maxRetries: this.maxRetries,
|
|
4030
|
+
retryBackoffMs: this.retryBackoffMs,
|
|
4031
|
+
timeoutMs: this.requestTimeoutMs
|
|
3903
4032
|
});
|
|
3904
4033
|
}
|
|
3905
4034
|
/** Create a client for the TensorLake cloud platform. */
|
|
@@ -3908,19 +4037,46 @@ var init_client = __esm({
|
|
|
3908
4037
|
apiUrl: options?.apiUrl ?? "https://api.tensorlake.ai",
|
|
3909
4038
|
apiKey: options?.apiKey,
|
|
3910
4039
|
organizationId: options?.organizationId,
|
|
3911
|
-
projectId: options?.projectId
|
|
4040
|
+
projectId: options?.projectId,
|
|
4041
|
+
requestTimeout: options?.requestTimeout,
|
|
4042
|
+
timeoutMs: options?.timeoutMs
|
|
3912
4043
|
});
|
|
3913
4044
|
}
|
|
3914
4045
|
/** Create a client for a local Indexify server. */
|
|
3915
4046
|
static forLocalhost(options) {
|
|
3916
4047
|
return new _SandboxClient({
|
|
3917
4048
|
apiUrl: options?.apiUrl ?? "http://localhost:8900",
|
|
3918
|
-
namespace: options?.namespace ?? "default"
|
|
4049
|
+
namespace: options?.namespace ?? "default",
|
|
4050
|
+
requestTimeout: options?.requestTimeout,
|
|
4051
|
+
timeoutMs: options?.timeoutMs
|
|
3919
4052
|
});
|
|
3920
4053
|
}
|
|
3921
4054
|
close() {
|
|
3922
4055
|
this.http.close();
|
|
3923
4056
|
}
|
|
4057
|
+
withRequestTimeout(requestTimeout) {
|
|
4058
|
+
if (requestTimeout == null) {
|
|
4059
|
+
return this;
|
|
4060
|
+
}
|
|
4061
|
+
const timeoutMs = secondsToMillis4(requestTimeout);
|
|
4062
|
+
if (timeoutMs === this.requestTimeoutMs) {
|
|
4063
|
+
return this;
|
|
4064
|
+
}
|
|
4065
|
+
return new _SandboxClient(
|
|
4066
|
+
{
|
|
4067
|
+
apiUrl: this.apiUrl,
|
|
4068
|
+
apiKey: this.apiKey,
|
|
4069
|
+
organizationId: this.organizationId,
|
|
4070
|
+
projectId: this.projectId,
|
|
4071
|
+
namespace: this.namespace,
|
|
4072
|
+
maxRetries: this.maxRetries,
|
|
4073
|
+
retryBackoffMs: this.retryBackoffMs,
|
|
4074
|
+
timeoutMs
|
|
4075
|
+
},
|
|
4076
|
+
/* _internal */
|
|
4077
|
+
true
|
|
4078
|
+
);
|
|
4079
|
+
}
|
|
3924
4080
|
// --- Path helper ---
|
|
3925
4081
|
path(subpath) {
|
|
3926
4082
|
return lifecyclePath(subpath, this.local, this.namespace);
|
|
@@ -3951,7 +4107,11 @@ var init_client = __esm({
|
|
|
3951
4107
|
const raw = await this.http.requestJson(
|
|
3952
4108
|
"POST",
|
|
3953
4109
|
this.path("sandboxes"),
|
|
3954
|
-
{
|
|
4110
|
+
{
|
|
4111
|
+
body,
|
|
4112
|
+
retryableStatusCodes: CREATE_SANDBOX_RETRYABLE_STATUS_CODES,
|
|
4113
|
+
allowedErrorStatusCodes: CREATE_SANDBOX_ALLOWED_ERROR_STATUS_CODES
|
|
4114
|
+
}
|
|
3955
4115
|
);
|
|
3956
4116
|
const result = fromSnakeKeys(raw, "sandboxId");
|
|
3957
4117
|
return Object.assign(result, { traceId: raw.traceId });
|
|
@@ -4041,6 +4201,7 @@ var init_client = __esm({
|
|
|
4041
4201
|
return {
|
|
4042
4202
|
allowUnauthenticatedAccess: info.allowUnauthenticatedAccess ?? false,
|
|
4043
4203
|
exposedPorts: dedupeAndSortPorts(info.exposedPorts ?? []),
|
|
4204
|
+
ingressEndpoint: info.ingressEndpoint,
|
|
4044
4205
|
sandboxUrl: info.sandboxUrl
|
|
4045
4206
|
};
|
|
4046
4207
|
}
|
|
@@ -4144,7 +4305,11 @@ var init_client = __esm({
|
|
|
4144
4305
|
async claim(poolId) {
|
|
4145
4306
|
const raw = await this.http.requestJson(
|
|
4146
4307
|
"POST",
|
|
4147
|
-
this.path(`sandbox-pools/${poolId}/sandboxes`)
|
|
4308
|
+
this.path(`sandbox-pools/${poolId}/sandboxes`),
|
|
4309
|
+
{
|
|
4310
|
+
retryableStatusCodes: CREATE_SANDBOX_RETRYABLE_STATUS_CODES,
|
|
4311
|
+
allowedErrorStatusCodes: CREATE_SANDBOX_ALLOWED_ERROR_STATUS_CODES
|
|
4312
|
+
}
|
|
4148
4313
|
);
|
|
4149
4314
|
const result = fromSnakeKeys(raw, "sandboxId");
|
|
4150
4315
|
return Object.assign(result, { traceId: raw.traceId });
|
|
@@ -4306,7 +4471,7 @@ var init_client = __esm({
|
|
|
4306
4471
|
}
|
|
4307
4472
|
// --- Connect ---
|
|
4308
4473
|
/** Return a `Sandbox` handle for an existing running sandbox without verifying it exists. */
|
|
4309
|
-
connect(identifier, proxyUrl, routingHint) {
|
|
4474
|
+
connect(identifier, proxyUrl, routingHint, requestTimeout) {
|
|
4310
4475
|
const resolvedProxy = proxyUrl ?? resolveProxyUrl(this.apiUrl);
|
|
4311
4476
|
return new Sandbox({
|
|
4312
4477
|
sandboxId: identifier,
|
|
@@ -4314,32 +4479,41 @@ var init_client = __esm({
|
|
|
4314
4479
|
apiKey: this.apiKey,
|
|
4315
4480
|
organizationId: this.organizationId,
|
|
4316
4481
|
projectId: this.projectId,
|
|
4317
|
-
routingHint
|
|
4482
|
+
routingHint,
|
|
4483
|
+
resolveProxyInfo: proxyUrl == null ? async (currentIdentifier) => this.get(currentIdentifier) : void 0,
|
|
4484
|
+
requestTimeout
|
|
4318
4485
|
});
|
|
4319
4486
|
}
|
|
4320
4487
|
/**
|
|
4321
4488
|
* Create a sandbox, wait for it to reach `Running`, and return a connected handle.
|
|
4322
4489
|
*
|
|
4323
|
-
* Blocks until the sandbox is ready or `
|
|
4490
|
+
* Blocks until the sandbox is ready or `requestTimeout` elapses. The returned
|
|
4324
4491
|
* `Sandbox` auto-terminates when `terminate()` is called.
|
|
4325
4492
|
*
|
|
4326
|
-
* @param options.
|
|
4493
|
+
* @param options.requestTimeout - Max seconds to wait for `Running` status (default: client requestTimeout).
|
|
4494
|
+
* @param options.startupTimeout - Deprecated alias for `requestTimeout`.
|
|
4327
4495
|
* @throws {SandboxError} If the sandbox terminates during startup or the timeout elapses.
|
|
4328
4496
|
*/
|
|
4329
4497
|
async createAndConnect(options) {
|
|
4330
|
-
const
|
|
4331
|
-
const
|
|
4498
|
+
const requestTimeout = options?.requestTimeout ?? options?.startupTimeout ?? this.requestTimeoutMs / 1e3;
|
|
4499
|
+
const requestClient = this.withRequestTimeout(requestTimeout);
|
|
4500
|
+
const result = options?.poolId != null ? await requestClient.claim(options.poolId) : await requestClient.create(options);
|
|
4332
4501
|
const requestedName = options?.poolId != null ? null : options?.name ?? null;
|
|
4333
|
-
const finishConnect = (routingHint, name) => {
|
|
4334
|
-
const sandbox =
|
|
4335
|
-
|
|
4502
|
+
const finishConnect = (routingHint, name, ingressEndpoint) => {
|
|
4503
|
+
const sandbox = requestClient.connect(
|
|
4504
|
+
result.sandboxId,
|
|
4505
|
+
options?.proxyUrl ?? ingressEndpoint,
|
|
4506
|
+
routingHint,
|
|
4507
|
+
requestTimeout
|
|
4508
|
+
);
|
|
4509
|
+
sandbox._setOwner(requestClient);
|
|
4336
4510
|
sandbox.traceId = result.traceId;
|
|
4337
4511
|
sandbox._setLifecycleIdentifier(result.sandboxId);
|
|
4338
4512
|
sandbox._setName(name ?? requestedName);
|
|
4339
4513
|
return sandbox;
|
|
4340
4514
|
};
|
|
4341
4515
|
if (result.status === "running" /* RUNNING */) {
|
|
4342
|
-
return finishConnect(result.routingHint, result.name);
|
|
4516
|
+
return finishConnect(result.routingHint, result.name, result.ingressEndpoint);
|
|
4343
4517
|
}
|
|
4344
4518
|
if (result.status === "suspended" /* SUSPENDED */ || result.status === "terminated" /* TERMINATED */) {
|
|
4345
4519
|
throw new SandboxError(
|
|
@@ -4349,11 +4523,20 @@ var init_client = __esm({
|
|
|
4349
4523
|
})
|
|
4350
4524
|
);
|
|
4351
4525
|
}
|
|
4352
|
-
|
|
4526
|
+
if (result.status === "timeout" /* TIMEOUT */) {
|
|
4527
|
+
try {
|
|
4528
|
+
await requestClient.delete(result.sandboxId);
|
|
4529
|
+
} catch {
|
|
4530
|
+
}
|
|
4531
|
+
throw new SandboxError(
|
|
4532
|
+
`Sandbox ${result.sandboxId} did not start within ${requestTimeout}s`
|
|
4533
|
+
);
|
|
4534
|
+
}
|
|
4535
|
+
const deadline = Date.now() + secondsToMillis4(requestTimeout);
|
|
4353
4536
|
while (Date.now() < deadline) {
|
|
4354
|
-
const info = await
|
|
4537
|
+
const info = await requestClient.get(result.sandboxId);
|
|
4355
4538
|
if (info.status === "running" /* RUNNING */) {
|
|
4356
|
-
return finishConnect(info.routingHint, info.name);
|
|
4539
|
+
return finishConnect(info.routingHint, info.name, info.ingressEndpoint);
|
|
4357
4540
|
}
|
|
4358
4541
|
if (info.status === "suspended" /* SUSPENDED */ || info.status === "terminated" /* TERMINATED */) {
|
|
4359
4542
|
throw new SandboxError(
|
|
@@ -4366,11 +4549,11 @@ var init_client = __esm({
|
|
|
4366
4549
|
await sleep2(500);
|
|
4367
4550
|
}
|
|
4368
4551
|
try {
|
|
4369
|
-
await
|
|
4552
|
+
await requestClient.delete(result.sandboxId);
|
|
4370
4553
|
} catch {
|
|
4371
4554
|
}
|
|
4372
4555
|
throw new SandboxError(
|
|
4373
|
-
`Sandbox ${result.sandboxId} did not start within ${
|
|
4556
|
+
`Sandbox ${result.sandboxId} did not start within ${requestTimeout}s`
|
|
4374
4557
|
);
|
|
4375
4558
|
}
|
|
4376
4559
|
};
|
|
@@ -5121,6 +5304,7 @@ var APIClient = class {
|
|
|
5121
5304
|
// src/index.ts
|
|
5122
5305
|
init_sandbox_image();
|
|
5123
5306
|
init_image();
|
|
5307
|
+
init_url();
|
|
5124
5308
|
init_errors();
|
|
5125
5309
|
init_models();
|
|
5126
5310
|
export {
|
|
@@ -5150,6 +5334,7 @@ export {
|
|
|
5150
5334
|
StdinMode,
|
|
5151
5335
|
TcpTunnel,
|
|
5152
5336
|
createSandboxImage,
|
|
5153
|
-
dockerfileContent
|
|
5337
|
+
dockerfileContent,
|
|
5338
|
+
sandboxUrlFromIngressEndpoint
|
|
5154
5339
|
};
|
|
5155
5340
|
//# sourceMappingURL=index.js.map
|