tensorlake 0.5.30 → 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 +130 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -4
- package/dist/index.d.ts +25 -4
- package/dist/index.js +130 -39
- 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.d.cts
CHANGED
|
@@ -24,7 +24,8 @@ declare enum SandboxStatus {
|
|
|
24
24
|
SNAPSHOTTING = "snapshotting",
|
|
25
25
|
SUSPENDING = "suspending",
|
|
26
26
|
SUSPENDED = "suspended",
|
|
27
|
-
TERMINATED = "terminated"
|
|
27
|
+
TERMINATED = "terminated",
|
|
28
|
+
TIMEOUT = "timeout"
|
|
28
29
|
}
|
|
29
30
|
declare enum SnapshotStatus {
|
|
30
31
|
IN_PROGRESS = "in_progress",
|
|
@@ -332,6 +333,10 @@ interface SandboxClientOptions {
|
|
|
332
333
|
namespace?: string;
|
|
333
334
|
maxRetries?: number;
|
|
334
335
|
retryBackoffMs?: number;
|
|
336
|
+
/** Total HTTP request timeout in seconds. Default: 300. */
|
|
337
|
+
requestTimeout?: number;
|
|
338
|
+
/** @deprecated Use requestTimeout. Total HTTP request timeout in milliseconds. */
|
|
339
|
+
timeoutMs?: number;
|
|
335
340
|
}
|
|
336
341
|
interface SandboxOptions {
|
|
337
342
|
sandboxId: string;
|
|
@@ -343,10 +348,17 @@ interface SandboxOptions {
|
|
|
343
348
|
resolveProxyInfo?: (identifier: string) => Promise<SandboxInfo & {
|
|
344
349
|
readonly traceId: string;
|
|
345
350
|
}>;
|
|
351
|
+
/** Optional total HTTP request timeout in seconds for sandbox proxy operations. Omit for no total proxy timeout. */
|
|
352
|
+
requestTimeout?: number;
|
|
353
|
+
/** @deprecated Use requestTimeout. Optional total HTTP request timeout in milliseconds for sandbox proxy operations. */
|
|
354
|
+
timeoutMs?: number;
|
|
346
355
|
}
|
|
347
356
|
interface CreateAndConnectOptions extends CreateSandboxOptions {
|
|
348
357
|
poolId?: string;
|
|
349
358
|
proxyUrl?: string;
|
|
359
|
+
/** Total HTTP request timeout in seconds for sandbox startup. Default: client requestTimeout. */
|
|
360
|
+
requestTimeout?: number;
|
|
361
|
+
/** @deprecated Use requestTimeout. */
|
|
350
362
|
startupTimeout?: number;
|
|
351
363
|
}
|
|
352
364
|
interface SuspendResumeOptions {
|
|
@@ -694,6 +706,9 @@ declare class SandboxClient {
|
|
|
694
706
|
private readonly projectId;
|
|
695
707
|
private readonly namespace;
|
|
696
708
|
private readonly local;
|
|
709
|
+
private readonly maxRetries;
|
|
710
|
+
private readonly retryBackoffMs;
|
|
711
|
+
private readonly requestTimeoutMs;
|
|
697
712
|
/** @internal Pass `true` to suppress the deprecation warning when used by `Sandbox.create()` / `Sandbox.connect()`. */
|
|
698
713
|
constructor(options?: SandboxClientOptions, _internal?: boolean);
|
|
699
714
|
/** Create a client for the TensorLake cloud platform. */
|
|
@@ -702,13 +717,18 @@ declare class SandboxClient {
|
|
|
702
717
|
organizationId?: string;
|
|
703
718
|
projectId?: string;
|
|
704
719
|
apiUrl?: string;
|
|
720
|
+
requestTimeout?: number;
|
|
721
|
+
timeoutMs?: number;
|
|
705
722
|
}): SandboxClient;
|
|
706
723
|
/** Create a client for a local Indexify server. */
|
|
707
724
|
static forLocalhost(options?: {
|
|
708
725
|
apiUrl?: string;
|
|
709
726
|
namespace?: string;
|
|
727
|
+
requestTimeout?: number;
|
|
728
|
+
timeoutMs?: number;
|
|
710
729
|
}): SandboxClient;
|
|
711
730
|
close(): void;
|
|
731
|
+
private withRequestTimeout;
|
|
712
732
|
private path;
|
|
713
733
|
/** Create a new sandbox. Returns immediately; the sandbox may still be starting. Use `createAndConnect()` for a blocking, ready-to-use handle. */
|
|
714
734
|
create(options?: CreateSandboxOptions): Promise<Traced<CreateSandboxResponse>>;
|
|
@@ -813,14 +833,15 @@ declare class SandboxClient {
|
|
|
813
833
|
/** Delete a sandbox pool. Fails if the pool has active containers. */
|
|
814
834
|
deletePool(poolId: string): Promise<void>;
|
|
815
835
|
/** Return a `Sandbox` handle for an existing running sandbox without verifying it exists. */
|
|
816
|
-
connect(identifier: string, proxyUrl?: string, routingHint?: string): Sandbox;
|
|
836
|
+
connect(identifier: string, proxyUrl?: string, routingHint?: string, requestTimeout?: number): Sandbox;
|
|
817
837
|
/**
|
|
818
838
|
* Create a sandbox, wait for it to reach `Running`, and return a connected handle.
|
|
819
839
|
*
|
|
820
|
-
* Blocks until the sandbox is ready or `
|
|
840
|
+
* Blocks until the sandbox is ready or `requestTimeout` elapses. The returned
|
|
821
841
|
* `Sandbox` auto-terminates when `terminate()` is called.
|
|
822
842
|
*
|
|
823
|
-
* @param options.
|
|
843
|
+
* @param options.requestTimeout - Max seconds to wait for `Running` status (default: client requestTimeout).
|
|
844
|
+
* @param options.startupTimeout - Deprecated alias for `requestTimeout`.
|
|
824
845
|
* @throws {SandboxError} If the sandbox terminates during startup or the timeout elapses.
|
|
825
846
|
*/
|
|
826
847
|
createAndConnect(options?: CreateAndConnectOptions): Promise<Sandbox>;
|
package/dist/index.d.ts
CHANGED
|
@@ -24,7 +24,8 @@ declare enum SandboxStatus {
|
|
|
24
24
|
SNAPSHOTTING = "snapshotting",
|
|
25
25
|
SUSPENDING = "suspending",
|
|
26
26
|
SUSPENDED = "suspended",
|
|
27
|
-
TERMINATED = "terminated"
|
|
27
|
+
TERMINATED = "terminated",
|
|
28
|
+
TIMEOUT = "timeout"
|
|
28
29
|
}
|
|
29
30
|
declare enum SnapshotStatus {
|
|
30
31
|
IN_PROGRESS = "in_progress",
|
|
@@ -332,6 +333,10 @@ interface SandboxClientOptions {
|
|
|
332
333
|
namespace?: string;
|
|
333
334
|
maxRetries?: number;
|
|
334
335
|
retryBackoffMs?: number;
|
|
336
|
+
/** Total HTTP request timeout in seconds. Default: 300. */
|
|
337
|
+
requestTimeout?: number;
|
|
338
|
+
/** @deprecated Use requestTimeout. Total HTTP request timeout in milliseconds. */
|
|
339
|
+
timeoutMs?: number;
|
|
335
340
|
}
|
|
336
341
|
interface SandboxOptions {
|
|
337
342
|
sandboxId: string;
|
|
@@ -343,10 +348,17 @@ interface SandboxOptions {
|
|
|
343
348
|
resolveProxyInfo?: (identifier: string) => Promise<SandboxInfo & {
|
|
344
349
|
readonly traceId: string;
|
|
345
350
|
}>;
|
|
351
|
+
/** Optional total HTTP request timeout in seconds for sandbox proxy operations. Omit for no total proxy timeout. */
|
|
352
|
+
requestTimeout?: number;
|
|
353
|
+
/** @deprecated Use requestTimeout. Optional total HTTP request timeout in milliseconds for sandbox proxy operations. */
|
|
354
|
+
timeoutMs?: number;
|
|
346
355
|
}
|
|
347
356
|
interface CreateAndConnectOptions extends CreateSandboxOptions {
|
|
348
357
|
poolId?: string;
|
|
349
358
|
proxyUrl?: string;
|
|
359
|
+
/** Total HTTP request timeout in seconds for sandbox startup. Default: client requestTimeout. */
|
|
360
|
+
requestTimeout?: number;
|
|
361
|
+
/** @deprecated Use requestTimeout. */
|
|
350
362
|
startupTimeout?: number;
|
|
351
363
|
}
|
|
352
364
|
interface SuspendResumeOptions {
|
|
@@ -694,6 +706,9 @@ declare class SandboxClient {
|
|
|
694
706
|
private readonly projectId;
|
|
695
707
|
private readonly namespace;
|
|
696
708
|
private readonly local;
|
|
709
|
+
private readonly maxRetries;
|
|
710
|
+
private readonly retryBackoffMs;
|
|
711
|
+
private readonly requestTimeoutMs;
|
|
697
712
|
/** @internal Pass `true` to suppress the deprecation warning when used by `Sandbox.create()` / `Sandbox.connect()`. */
|
|
698
713
|
constructor(options?: SandboxClientOptions, _internal?: boolean);
|
|
699
714
|
/** Create a client for the TensorLake cloud platform. */
|
|
@@ -702,13 +717,18 @@ declare class SandboxClient {
|
|
|
702
717
|
organizationId?: string;
|
|
703
718
|
projectId?: string;
|
|
704
719
|
apiUrl?: string;
|
|
720
|
+
requestTimeout?: number;
|
|
721
|
+
timeoutMs?: number;
|
|
705
722
|
}): SandboxClient;
|
|
706
723
|
/** Create a client for a local Indexify server. */
|
|
707
724
|
static forLocalhost(options?: {
|
|
708
725
|
apiUrl?: string;
|
|
709
726
|
namespace?: string;
|
|
727
|
+
requestTimeout?: number;
|
|
728
|
+
timeoutMs?: number;
|
|
710
729
|
}): SandboxClient;
|
|
711
730
|
close(): void;
|
|
731
|
+
private withRequestTimeout;
|
|
712
732
|
private path;
|
|
713
733
|
/** Create a new sandbox. Returns immediately; the sandbox may still be starting. Use `createAndConnect()` for a blocking, ready-to-use handle. */
|
|
714
734
|
create(options?: CreateSandboxOptions): Promise<Traced<CreateSandboxResponse>>;
|
|
@@ -813,14 +833,15 @@ declare class SandboxClient {
|
|
|
813
833
|
/** Delete a sandbox pool. Fails if the pool has active containers. */
|
|
814
834
|
deletePool(poolId: string): Promise<void>;
|
|
815
835
|
/** Return a `Sandbox` handle for an existing running sandbox without verifying it exists. */
|
|
816
|
-
connect(identifier: string, proxyUrl?: string, routingHint?: string): Sandbox;
|
|
836
|
+
connect(identifier: string, proxyUrl?: string, routingHint?: string, requestTimeout?: number): Sandbox;
|
|
817
837
|
/**
|
|
818
838
|
* Create a sandbox, wait for it to reach `Running`, and return a connected handle.
|
|
819
839
|
*
|
|
820
|
-
* Blocks until the sandbox is ready or `
|
|
840
|
+
* Blocks until the sandbox is ready or `requestTimeout` elapses. The returned
|
|
821
841
|
* `Sandbox` auto-terminates when `terminate()` is called.
|
|
822
842
|
*
|
|
823
|
-
* @param options.
|
|
843
|
+
* @param options.requestTimeout - Max seconds to wait for `Running` status (default: client requestTimeout).
|
|
844
|
+
* @param options.startupTimeout - Deprecated alias for `requestTimeout`.
|
|
824
845
|
* @throws {SandboxError} If the sandbox terminates during startup or the timeout elapses.
|
|
825
846
|
*/
|
|
826
847
|
createAndConnect(options?: CreateAndConnectOptions): Promise<Sandbox>;
|
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) => {
|
|
@@ -3024,6 +3031,12 @@ function sendPtyFrame(socket, frame) {
|
|
|
3024
3031
|
socket.send(frame, (error) => error ? reject(error) : resolve());
|
|
3025
3032
|
});
|
|
3026
3033
|
}
|
|
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
|
+
}
|
|
3027
3040
|
var DEFAULT_PROCESS_USER, SandboxProxyConnection, PTY_OP_DATA, PTY_OP_RESIZE, PTY_OP_READY, PTY_OP_EXIT, Pty, Sandbox;
|
|
3028
3041
|
var init_sandbox = __esm({
|
|
3029
3042
|
"src/sandbox.ts"() {
|
|
@@ -3125,7 +3138,8 @@ var init_sandbox = __esm({
|
|
|
3125
3138
|
projectId: this.options.projectId,
|
|
3126
3139
|
hostHeader,
|
|
3127
3140
|
sandboxIdHeader,
|
|
3128
|
-
routingHint
|
|
3141
|
+
routingHint,
|
|
3142
|
+
timeoutMs: this.options.requestTimeout != null ? secondsToMillis3(this.options.requestTimeout) : this.options.timeoutMs ?? null
|
|
3129
3143
|
});
|
|
3130
3144
|
}
|
|
3131
3145
|
};
|
|
@@ -3346,9 +3360,7 @@ var init_sandbox = __esm({
|
|
|
3346
3360
|
/* _internal */
|
|
3347
3361
|
true
|
|
3348
3362
|
);
|
|
3349
|
-
|
|
3350
|
-
sandbox.lifecycleClient = client;
|
|
3351
|
-
return sandbox;
|
|
3363
|
+
return client.createAndConnect(options);
|
|
3352
3364
|
}
|
|
3353
3365
|
/**
|
|
3354
3366
|
* Attach to an existing sandbox and return a connected handle.
|
|
@@ -3367,7 +3379,8 @@ var init_sandbox = __esm({
|
|
|
3367
3379
|
const sandbox = client.connect(
|
|
3368
3380
|
options.sandboxId,
|
|
3369
3381
|
options.proxyUrl,
|
|
3370
|
-
options.routingHint
|
|
3382
|
+
options.routingHint,
|
|
3383
|
+
options.requestTimeout
|
|
3371
3384
|
);
|
|
3372
3385
|
sandbox.lifecycleClient = client;
|
|
3373
3386
|
return sandbox;
|
|
@@ -3892,6 +3905,27 @@ var client_exports = {};
|
|
|
3892
3905
|
__export(client_exports, {
|
|
3893
3906
|
SandboxClient: () => SandboxClient
|
|
3894
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
|
+
}
|
|
3895
3929
|
function sleep2(ms) {
|
|
3896
3930
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3897
3931
|
}
|
|
@@ -3948,7 +3982,7 @@ function validateUserPort(port) {
|
|
|
3948
3982
|
function dedupeAndSortPorts(ports) {
|
|
3949
3983
|
return [...new Set(ports)].sort((a, b) => a - b);
|
|
3950
3984
|
}
|
|
3951
|
-
var SandboxClient, RESERVED_SANDBOX_MANAGEMENT_PORT;
|
|
3985
|
+
var CREATE_SANDBOX_RETRYABLE_STATUS_CODES, CREATE_SANDBOX_ALLOWED_ERROR_STATUS_CODES, SandboxClient, RESERVED_SANDBOX_MANAGEMENT_PORT;
|
|
3952
3986
|
var init_client = __esm({
|
|
3953
3987
|
"src/client.ts"() {
|
|
3954
3988
|
"use strict";
|
|
@@ -3958,6 +3992,8 @@ var init_client = __esm({
|
|
|
3958
3992
|
init_models();
|
|
3959
3993
|
init_sandbox();
|
|
3960
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]);
|
|
3961
3997
|
SandboxClient = class _SandboxClient {
|
|
3962
3998
|
http;
|
|
3963
3999
|
apiUrl;
|
|
@@ -3966,6 +4002,9 @@ var init_client = __esm({
|
|
|
3966
4002
|
projectId;
|
|
3967
4003
|
namespace;
|
|
3968
4004
|
local;
|
|
4005
|
+
maxRetries;
|
|
4006
|
+
retryBackoffMs;
|
|
4007
|
+
requestTimeoutMs;
|
|
3969
4008
|
/** @internal Pass `true` to suppress the deprecation warning when used by `Sandbox.create()` / `Sandbox.connect()`. */
|
|
3970
4009
|
constructor(options, _internal = false) {
|
|
3971
4010
|
if (!_internal) {
|
|
@@ -3979,13 +4018,17 @@ var init_client = __esm({
|
|
|
3979
4018
|
this.projectId = options?.projectId;
|
|
3980
4019
|
this.namespace = options?.namespace ?? NAMESPACE;
|
|
3981
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);
|
|
3982
4024
|
this.http = new HttpClient({
|
|
3983
4025
|
baseUrl: resolveSandboxLifecycleUrl(this.apiUrl),
|
|
3984
4026
|
apiKey: this.apiKey,
|
|
3985
4027
|
organizationId: this.organizationId,
|
|
3986
4028
|
projectId: this.projectId,
|
|
3987
|
-
maxRetries:
|
|
3988
|
-
retryBackoffMs:
|
|
4029
|
+
maxRetries: this.maxRetries,
|
|
4030
|
+
retryBackoffMs: this.retryBackoffMs,
|
|
4031
|
+
timeoutMs: this.requestTimeoutMs
|
|
3989
4032
|
});
|
|
3990
4033
|
}
|
|
3991
4034
|
/** Create a client for the TensorLake cloud platform. */
|
|
@@ -3994,19 +4037,46 @@ var init_client = __esm({
|
|
|
3994
4037
|
apiUrl: options?.apiUrl ?? "https://api.tensorlake.ai",
|
|
3995
4038
|
apiKey: options?.apiKey,
|
|
3996
4039
|
organizationId: options?.organizationId,
|
|
3997
|
-
projectId: options?.projectId
|
|
4040
|
+
projectId: options?.projectId,
|
|
4041
|
+
requestTimeout: options?.requestTimeout,
|
|
4042
|
+
timeoutMs: options?.timeoutMs
|
|
3998
4043
|
});
|
|
3999
4044
|
}
|
|
4000
4045
|
/** Create a client for a local Indexify server. */
|
|
4001
4046
|
static forLocalhost(options) {
|
|
4002
4047
|
return new _SandboxClient({
|
|
4003
4048
|
apiUrl: options?.apiUrl ?? "http://localhost:8900",
|
|
4004
|
-
namespace: options?.namespace ?? "default"
|
|
4049
|
+
namespace: options?.namespace ?? "default",
|
|
4050
|
+
requestTimeout: options?.requestTimeout,
|
|
4051
|
+
timeoutMs: options?.timeoutMs
|
|
4005
4052
|
});
|
|
4006
4053
|
}
|
|
4007
4054
|
close() {
|
|
4008
4055
|
this.http.close();
|
|
4009
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
|
+
}
|
|
4010
4080
|
// --- Path helper ---
|
|
4011
4081
|
path(subpath) {
|
|
4012
4082
|
return lifecyclePath(subpath, this.local, this.namespace);
|
|
@@ -4037,7 +4107,11 @@ var init_client = __esm({
|
|
|
4037
4107
|
const raw = await this.http.requestJson(
|
|
4038
4108
|
"POST",
|
|
4039
4109
|
this.path("sandboxes"),
|
|
4040
|
-
{
|
|
4110
|
+
{
|
|
4111
|
+
body,
|
|
4112
|
+
retryableStatusCodes: CREATE_SANDBOX_RETRYABLE_STATUS_CODES,
|
|
4113
|
+
allowedErrorStatusCodes: CREATE_SANDBOX_ALLOWED_ERROR_STATUS_CODES
|
|
4114
|
+
}
|
|
4041
4115
|
);
|
|
4042
4116
|
const result = fromSnakeKeys(raw, "sandboxId");
|
|
4043
4117
|
return Object.assign(result, { traceId: raw.traceId });
|
|
@@ -4231,7 +4305,11 @@ var init_client = __esm({
|
|
|
4231
4305
|
async claim(poolId) {
|
|
4232
4306
|
const raw = await this.http.requestJson(
|
|
4233
4307
|
"POST",
|
|
4234
|
-
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
|
+
}
|
|
4235
4313
|
);
|
|
4236
4314
|
const result = fromSnakeKeys(raw, "sandboxId");
|
|
4237
4315
|
return Object.assign(result, { traceId: raw.traceId });
|
|
@@ -4393,7 +4471,7 @@ var init_client = __esm({
|
|
|
4393
4471
|
}
|
|
4394
4472
|
// --- Connect ---
|
|
4395
4473
|
/** Return a `Sandbox` handle for an existing running sandbox without verifying it exists. */
|
|
4396
|
-
connect(identifier, proxyUrl, routingHint) {
|
|
4474
|
+
connect(identifier, proxyUrl, routingHint, requestTimeout) {
|
|
4397
4475
|
const resolvedProxy = proxyUrl ?? resolveProxyUrl(this.apiUrl);
|
|
4398
4476
|
return new Sandbox({
|
|
4399
4477
|
sandboxId: identifier,
|
|
@@ -4402,29 +4480,33 @@ var init_client = __esm({
|
|
|
4402
4480
|
organizationId: this.organizationId,
|
|
4403
4481
|
projectId: this.projectId,
|
|
4404
4482
|
routingHint,
|
|
4405
|
-
resolveProxyInfo: proxyUrl == null ? async (currentIdentifier) => this.get(currentIdentifier) : void 0
|
|
4483
|
+
resolveProxyInfo: proxyUrl == null ? async (currentIdentifier) => this.get(currentIdentifier) : void 0,
|
|
4484
|
+
requestTimeout
|
|
4406
4485
|
});
|
|
4407
4486
|
}
|
|
4408
4487
|
/**
|
|
4409
4488
|
* Create a sandbox, wait for it to reach `Running`, and return a connected handle.
|
|
4410
4489
|
*
|
|
4411
|
-
* Blocks until the sandbox is ready or `
|
|
4490
|
+
* Blocks until the sandbox is ready or `requestTimeout` elapses. The returned
|
|
4412
4491
|
* `Sandbox` auto-terminates when `terminate()` is called.
|
|
4413
4492
|
*
|
|
4414
|
-
* @param options.
|
|
4493
|
+
* @param options.requestTimeout - Max seconds to wait for `Running` status (default: client requestTimeout).
|
|
4494
|
+
* @param options.startupTimeout - Deprecated alias for `requestTimeout`.
|
|
4415
4495
|
* @throws {SandboxError} If the sandbox terminates during startup or the timeout elapses.
|
|
4416
4496
|
*/
|
|
4417
4497
|
async createAndConnect(options) {
|
|
4418
|
-
const
|
|
4419
|
-
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);
|
|
4420
4501
|
const requestedName = options?.poolId != null ? null : options?.name ?? null;
|
|
4421
4502
|
const finishConnect = (routingHint, name, ingressEndpoint) => {
|
|
4422
|
-
const sandbox =
|
|
4503
|
+
const sandbox = requestClient.connect(
|
|
4423
4504
|
result.sandboxId,
|
|
4424
4505
|
options?.proxyUrl ?? ingressEndpoint,
|
|
4425
|
-
routingHint
|
|
4506
|
+
routingHint,
|
|
4507
|
+
requestTimeout
|
|
4426
4508
|
);
|
|
4427
|
-
sandbox._setOwner(
|
|
4509
|
+
sandbox._setOwner(requestClient);
|
|
4428
4510
|
sandbox.traceId = result.traceId;
|
|
4429
4511
|
sandbox._setLifecycleIdentifier(result.sandboxId);
|
|
4430
4512
|
sandbox._setName(name ?? requestedName);
|
|
@@ -4441,9 +4523,18 @@ var init_client = __esm({
|
|
|
4441
4523
|
})
|
|
4442
4524
|
);
|
|
4443
4525
|
}
|
|
4444
|
-
|
|
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);
|
|
4445
4536
|
while (Date.now() < deadline) {
|
|
4446
|
-
const info = await
|
|
4537
|
+
const info = await requestClient.get(result.sandboxId);
|
|
4447
4538
|
if (info.status === "running" /* RUNNING */) {
|
|
4448
4539
|
return finishConnect(info.routingHint, info.name, info.ingressEndpoint);
|
|
4449
4540
|
}
|
|
@@ -4458,11 +4549,11 @@ var init_client = __esm({
|
|
|
4458
4549
|
await sleep2(500);
|
|
4459
4550
|
}
|
|
4460
4551
|
try {
|
|
4461
|
-
await
|
|
4552
|
+
await requestClient.delete(result.sandboxId);
|
|
4462
4553
|
} catch {
|
|
4463
4554
|
}
|
|
4464
4555
|
throw new SandboxError(
|
|
4465
|
-
`Sandbox ${result.sandboxId} did not start within ${
|
|
4556
|
+
`Sandbox ${result.sandboxId} did not start within ${requestTimeout}s`
|
|
4466
4557
|
);
|
|
4467
4558
|
}
|
|
4468
4559
|
};
|