tensorlake 0.5.37 → 0.5.40
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-arm64/tensorlake +0 -0
- package/dist/bin/linux-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 +808 -798
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +96 -36
- package/dist/index.d.ts +96 -36
- package/dist/index.js +805 -796
- package/dist/index.js.map +1 -1
- package/dist/native/darwin-arm64/tensorlake-node.node +0 -0
- package/dist/native/linux-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.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.40";
|
|
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";
|
|
@@ -155,360 +155,155 @@ var init_errors = __esm({
|
|
|
155
155
|
}
|
|
156
156
|
});
|
|
157
157
|
|
|
158
|
-
// src/
|
|
159
|
-
function
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
function sdkTimingPayloadsEnabled() {
|
|
164
|
-
const value = process.env[SDK_TIMING_PAYLOADS_ENV_VAR];
|
|
165
|
-
return value === "1" || value === "true" || value === "yes";
|
|
166
|
-
}
|
|
167
|
-
function nowMs() {
|
|
168
|
-
return performance.now();
|
|
169
|
-
}
|
|
170
|
-
function logSdkTiming(op, phase, startedAt, fields = {}) {
|
|
171
|
-
if (!sdkTimingsEnabled()) return;
|
|
172
|
-
logSdkTimingEvent(op, phase, {
|
|
173
|
-
...fields,
|
|
174
|
-
duration_ms: Math.round((nowMs() - startedAt) * 100) / 100
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
function logSdkTimingEvent(op, phase, fields = {}) {
|
|
178
|
-
if (!sdkTimingsEnabled()) return;
|
|
179
|
-
const parts = [
|
|
180
|
-
"[tensorlake:sdk-timing]",
|
|
181
|
-
`op=${op}`,
|
|
182
|
-
`phase=${phase}`
|
|
183
|
-
];
|
|
184
|
-
for (const [key, value] of Object.entries(fields)) {
|
|
185
|
-
if (value == null) continue;
|
|
186
|
-
parts.push(`${key}=${formatSdkTimingValue(value)}`);
|
|
158
|
+
// src/native-sandbox.ts
|
|
159
|
+
function resolveRequire() {
|
|
160
|
+
if (typeof module !== "undefined" && module.exports != null && typeof require !== "undefined") {
|
|
161
|
+
return require;
|
|
187
162
|
}
|
|
188
|
-
|
|
163
|
+
return (0, import_node_module.createRequire)(import_meta.url);
|
|
189
164
|
}
|
|
190
|
-
function
|
|
191
|
-
if (
|
|
192
|
-
|
|
165
|
+
function loadNativeSandboxBinding() {
|
|
166
|
+
if (cachedBinding) return cachedBinding;
|
|
167
|
+
if (cachedBindingError) throw cachedBindingError;
|
|
168
|
+
try {
|
|
169
|
+
const { loadNative } = resolveRequire()("../lib/runtime.cjs");
|
|
170
|
+
const binding = loadNative();
|
|
171
|
+
if (binding == null || typeof binding.NativeSandboxClient !== "function" || typeof binding.NativeSandboxProxyClient !== "function") {
|
|
172
|
+
throw new SandboxError(
|
|
173
|
+
"native binding does not export the sandbox clients; rebuild with 'npm run build:native'"
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
cachedBinding = binding;
|
|
177
|
+
return cachedBinding;
|
|
178
|
+
} catch (error) {
|
|
179
|
+
cachedBindingError = error instanceof Error ? error : new Error(String(error));
|
|
180
|
+
throw cachedBindingError;
|
|
193
181
|
}
|
|
194
|
-
|
|
195
|
-
|
|
182
|
+
}
|
|
183
|
+
function parseNativeError(error) {
|
|
184
|
+
const message = error instanceof Error ? error.message : typeof error === "string" ? error : "";
|
|
185
|
+
if (!message) return null;
|
|
186
|
+
try {
|
|
187
|
+
const parsed = JSON.parse(message);
|
|
188
|
+
if (parsed && typeof parsed.category === "string") {
|
|
189
|
+
return {
|
|
190
|
+
category: parsed.category,
|
|
191
|
+
status: typeof parsed.status === "number" ? parsed.status : null,
|
|
192
|
+
message: typeof parsed.message === "string" ? parsed.message : message
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
} catch {
|
|
196
196
|
}
|
|
197
|
-
return
|
|
197
|
+
return null;
|
|
198
198
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
SDK_TIMING_PAYLOADS_ENV_VAR = "TENSORLAKE_SDK_TIMING_PAYLOADS";
|
|
199
|
+
function translateNativeError(error, context) {
|
|
200
|
+
const payload = parseNativeError(error);
|
|
201
|
+
if (!payload) {
|
|
202
|
+
if (error instanceof Error) return error;
|
|
203
|
+
return new SandboxError(String(error));
|
|
205
204
|
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
function withTraceId(value, traceId) {
|
|
210
|
-
if (value == null) {
|
|
211
|
-
return { traceId };
|
|
205
|
+
const { category, status, message } = payload;
|
|
206
|
+
if (category === "connection") {
|
|
207
|
+
return new SandboxConnectionError(message, { cause: error });
|
|
212
208
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
return void 0;
|
|
209
|
+
if (status === 404) {
|
|
210
|
+
if (context?.notFoundKind === "pool" && context.poolId) {
|
|
211
|
+
return new PoolNotFoundError(context.poolId);
|
|
212
|
+
}
|
|
213
|
+
if (context?.notFoundKind === "sandbox" && context.sandboxId) {
|
|
214
|
+
return new SandboxNotFoundError(context.sandboxId);
|
|
215
|
+
}
|
|
216
|
+
return new RemoteAPIError(404, message);
|
|
222
217
|
}
|
|
223
|
-
if (
|
|
224
|
-
return
|
|
218
|
+
if (status === 409 && context?.poolId) {
|
|
219
|
+
return new PoolInUseError(context.poolId, message);
|
|
225
220
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
return queryStart === -1 ? path2 : path2.slice(0, queryStart);
|
|
221
|
+
if (typeof status === "number") {
|
|
222
|
+
return new RemoteAPIError(status, message);
|
|
223
|
+
}
|
|
224
|
+
return new SandboxError(message);
|
|
231
225
|
}
|
|
232
|
-
function
|
|
233
|
-
let message = body;
|
|
226
|
+
async function callNative(fn, context) {
|
|
234
227
|
try {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
} catch {
|
|
228
|
+
return await fn();
|
|
229
|
+
} catch (error) {
|
|
230
|
+
throw translateNativeError(error, context);
|
|
239
231
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
232
|
+
}
|
|
233
|
+
async function* nativeEventStream(start, context, signal) {
|
|
234
|
+
const queue = [];
|
|
235
|
+
let wake = null;
|
|
236
|
+
let finished = false;
|
|
237
|
+
let failure = null;
|
|
238
|
+
const notify = () => {
|
|
239
|
+
if (wake) {
|
|
240
|
+
const w = wake;
|
|
241
|
+
wake = null;
|
|
242
|
+
w();
|
|
244
243
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
244
|
+
};
|
|
245
|
+
const emit = (eventJson) => {
|
|
246
|
+
queue.push(eventJson);
|
|
247
|
+
notify();
|
|
248
|
+
};
|
|
249
|
+
const onAbort = () => notify();
|
|
250
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
251
|
+
const startPromise = start(emit).catch((error) => {
|
|
252
|
+
failure = error;
|
|
253
|
+
}).finally(() => {
|
|
254
|
+
finished = true;
|
|
255
|
+
notify();
|
|
256
|
+
});
|
|
257
|
+
try {
|
|
258
|
+
while (true) {
|
|
259
|
+
if (queue.length > 0) {
|
|
260
|
+
yield JSON.parse(queue.shift());
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
if (signal?.aborted) break;
|
|
264
|
+
if (finished) break;
|
|
265
|
+
await new Promise((resolve) => {
|
|
266
|
+
wake = resolve;
|
|
267
|
+
});
|
|
248
268
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
if (status === 409) {
|
|
252
|
-
if (path2.includes("sandbox-pools") || path2.includes("pools")) {
|
|
253
|
-
const match = path2.match(/sandbox-pools\/([^/]+)/);
|
|
254
|
-
if (match) throw new PoolInUseError(match[1], message);
|
|
269
|
+
if (failure != null) {
|
|
270
|
+
throw translateNativeError(failure, context);
|
|
255
271
|
}
|
|
272
|
+
} finally {
|
|
273
|
+
signal?.removeEventListener("abort", onAbort);
|
|
274
|
+
void startPromise.catch(() => {
|
|
275
|
+
});
|
|
256
276
|
}
|
|
257
|
-
throw new RemoteAPIError(status, message);
|
|
258
277
|
}
|
|
259
|
-
function
|
|
260
|
-
const
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
278
|
+
function assembleCommandResult(events) {
|
|
279
|
+
const stdoutLines = [];
|
|
280
|
+
const stderrLines = [];
|
|
281
|
+
let exitCode = -1;
|
|
282
|
+
for (const eventJson of events) {
|
|
283
|
+
const raw = JSON.parse(eventJson);
|
|
284
|
+
if (typeof raw.line === "string") {
|
|
285
|
+
if (raw.stream === "stderr") {
|
|
286
|
+
stderrLines.push(raw.line);
|
|
287
|
+
} else {
|
|
288
|
+
stdoutLines.push(raw.line);
|
|
289
|
+
}
|
|
290
|
+
} else if ("exit_code" in raw || "signal" in raw) {
|
|
291
|
+
if (typeof raw.exit_code === "number") {
|
|
292
|
+
exitCode = raw.exit_code;
|
|
293
|
+
} else if (typeof raw.signal === "number") {
|
|
294
|
+
exitCode = -raw.signal;
|
|
295
|
+
}
|
|
265
296
|
}
|
|
266
|
-
signal.addEventListener("abort", () => controller.abort(signal.reason), {
|
|
267
|
-
once: true
|
|
268
|
-
});
|
|
269
297
|
}
|
|
270
|
-
return
|
|
271
|
-
}
|
|
272
|
-
function sleep(ms) {
|
|
273
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
298
|
+
return { exitCode, stdout: stdoutLines.join("\n"), stderr: stderrLines.join("\n") };
|
|
274
299
|
}
|
|
275
|
-
var
|
|
276
|
-
var
|
|
277
|
-
"src/
|
|
300
|
+
var import_node_module, import_meta, cachedBinding, cachedBindingError;
|
|
301
|
+
var init_native_sandbox = __esm({
|
|
302
|
+
"src/native-sandbox.ts"() {
|
|
278
303
|
"use strict";
|
|
279
|
-
|
|
280
|
-
init_defaults();
|
|
304
|
+
import_node_module = require("module");
|
|
281
305
|
init_errors();
|
|
282
|
-
|
|
283
|
-
REQUEST_TIMEOUT_HEADER = "X-Tensorlake-Request-Timeout-Ms";
|
|
284
|
-
(0, import_undici.setGlobalDispatcher)(
|
|
285
|
-
new import_undici.Agent({
|
|
286
|
-
keepAliveTimeout: 6e4,
|
|
287
|
-
allowH2: true
|
|
288
|
-
})
|
|
289
|
-
);
|
|
290
|
-
HttpClient = class _HttpClient {
|
|
291
|
-
baseUrl;
|
|
292
|
-
headers;
|
|
293
|
-
maxRetries;
|
|
294
|
-
retryBackoffMs;
|
|
295
|
-
timeoutMs;
|
|
296
|
-
abortController = null;
|
|
297
|
-
constructor(options) {
|
|
298
|
-
const url = options.baseUrl;
|
|
299
|
-
this.baseUrl = url.endsWith("/") ? url.slice(0, -1) : url;
|
|
300
|
-
this.maxRetries = options.maxRetries ?? MAX_RETRIES;
|
|
301
|
-
this.retryBackoffMs = options.retryBackoffMs ?? RETRY_BACKOFF_MS;
|
|
302
|
-
this.timeoutMs = options.timeoutMs === void 0 ? DEFAULT_HTTP_TIMEOUT_MS : options.timeoutMs;
|
|
303
|
-
this.headers = {
|
|
304
|
-
"User-Agent": `tensorlake-typescript-sdk/${SDK_VERSION}`
|
|
305
|
-
};
|
|
306
|
-
if (this.timeoutMs != null) {
|
|
307
|
-
this.headers[REQUEST_TIMEOUT_HEADER] = String(this.timeoutMs);
|
|
308
|
-
}
|
|
309
|
-
if (options.apiKey) {
|
|
310
|
-
this.headers["Authorization"] = `Bearer ${options.apiKey}`;
|
|
311
|
-
}
|
|
312
|
-
if (options.organizationId) {
|
|
313
|
-
this.headers["X-Forwarded-Organization-Id"] = options.organizationId;
|
|
314
|
-
}
|
|
315
|
-
if (options.projectId) {
|
|
316
|
-
this.headers["X-Forwarded-Project-Id"] = options.projectId;
|
|
317
|
-
}
|
|
318
|
-
if (options.hostHeader) {
|
|
319
|
-
this.headers["Host"] = options.hostHeader;
|
|
320
|
-
}
|
|
321
|
-
if (options.sandboxIdHeader) {
|
|
322
|
-
this.headers["X-Tensorlake-Sandbox-Id"] = options.sandboxIdHeader;
|
|
323
|
-
}
|
|
324
|
-
if (options.routingHint) {
|
|
325
|
-
this.headers["X-Tensorlake-Route-Hint"] = options.routingHint;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
close() {
|
|
329
|
-
this.abortController?.abort();
|
|
330
|
-
this.abortController = null;
|
|
331
|
-
}
|
|
332
|
-
/** Make a JSON request, returning the parsed response body. */
|
|
333
|
-
async requestJson(method, path2, options) {
|
|
334
|
-
const response = await this.requestResponse(method, path2, {
|
|
335
|
-
json: options?.body,
|
|
336
|
-
headers: options?.headers,
|
|
337
|
-
signal: options?.signal,
|
|
338
|
-
retryableStatusCodes: options?.retryableStatusCodes,
|
|
339
|
-
allowedErrorStatusCodes: options?.allowedErrorStatusCodes,
|
|
340
|
-
allowHttpErrors: options?.allowHttpErrors
|
|
341
|
-
});
|
|
342
|
-
const text = await response.text();
|
|
343
|
-
const data = text ? JSON.parse(text) : void 0;
|
|
344
|
-
return withTraceId(data, response.traceId);
|
|
345
|
-
}
|
|
346
|
-
/** Make a request returning raw bytes. */
|
|
347
|
-
async requestBytes(method, path2, options) {
|
|
348
|
-
const headers = { ...options?.headers ?? {} };
|
|
349
|
-
if (options?.contentType) {
|
|
350
|
-
headers["Content-Type"] = options.contentType;
|
|
351
|
-
}
|
|
352
|
-
const response = await this.requestResponse(method, path2, {
|
|
353
|
-
body: options?.body,
|
|
354
|
-
headers,
|
|
355
|
-
signal: options?.signal
|
|
356
|
-
});
|
|
357
|
-
const buffer = await response.arrayBuffer();
|
|
358
|
-
return withTraceId(new Uint8Array(buffer), response.traceId);
|
|
359
|
-
}
|
|
360
|
-
/** Make a request and return the response body as an SSE stream. */
|
|
361
|
-
async requestStream(method, path2, options) {
|
|
362
|
-
const response = await this.requestResponse(method, path2, {
|
|
363
|
-
json: options?.json,
|
|
364
|
-
headers: { Accept: "text/event-stream" },
|
|
365
|
-
signal: options?.signal
|
|
366
|
-
});
|
|
367
|
-
if (!response.body) {
|
|
368
|
-
throw new RemoteAPIError(
|
|
369
|
-
response.status,
|
|
370
|
-
"No response body for SSE stream"
|
|
371
|
-
);
|
|
372
|
-
}
|
|
373
|
-
return withTraceId(response.body, response.traceId);
|
|
374
|
-
}
|
|
375
|
-
/** Make a request and return the raw Response. */
|
|
376
|
-
async requestResponse(method, path2, options) {
|
|
377
|
-
const headers = {
|
|
378
|
-
...this.headers,
|
|
379
|
-
...options?.headers ?? {}
|
|
380
|
-
};
|
|
381
|
-
const hasJsonBody = options?.json !== void 0;
|
|
382
|
-
if (hasJsonBody && !hasHeader(headers, "Content-Type")) {
|
|
383
|
-
headers["Content-Type"] = "application/json";
|
|
384
|
-
}
|
|
385
|
-
const body = hasJsonBody ? JSON.stringify(options?.json) : normalizeRequestBody(options?.body);
|
|
386
|
-
const { response, traceId } = await this.doFetch(
|
|
387
|
-
method,
|
|
388
|
-
path2,
|
|
389
|
-
body,
|
|
390
|
-
headers,
|
|
391
|
-
options?.signal,
|
|
392
|
-
options?.allowHttpErrors ?? false,
|
|
393
|
-
options?.retryableStatusCodes ?? RETRYABLE_STATUS_CODES,
|
|
394
|
-
options?.allowedErrorStatusCodes ?? /* @__PURE__ */ new Set()
|
|
395
|
-
);
|
|
396
|
-
return withTraceId(response, traceId);
|
|
397
|
-
}
|
|
398
|
-
static makeTraceparent() {
|
|
399
|
-
const randomHex = (bytes) => Array.from(crypto.getRandomValues(new Uint8Array(bytes))).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
400
|
-
const traceId = randomHex(16);
|
|
401
|
-
const spanId = randomHex(8);
|
|
402
|
-
return { traceparent: `00-${traceId}-${spanId}-01`, traceId };
|
|
403
|
-
}
|
|
404
|
-
async doFetch(method, path2, body, headers, signal, allowHttpErrors = false, retryableStatusCodes = RETRYABLE_STATUS_CODES, allowedErrorStatusCodes = /* @__PURE__ */ new Set()) {
|
|
405
|
-
const url = `${this.baseUrl}${path2}`;
|
|
406
|
-
const { traceparent, traceId } = _HttpClient.makeTraceparent();
|
|
407
|
-
headers["traceparent"] = traceparent;
|
|
408
|
-
let lastError;
|
|
409
|
-
const operationStart = nowMs();
|
|
410
|
-
const timingPath = sdkTimingPayloadsEnabled() ? path2 : stripPathPayload(path2);
|
|
411
|
-
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
412
|
-
if (attempt > 0) {
|
|
413
|
-
const delay = this.retryBackoffMs * Math.pow(2, attempt - 1);
|
|
414
|
-
logSdkTimingEvent("http.request", "retry_sleep_start", {
|
|
415
|
-
method,
|
|
416
|
-
path: timingPath,
|
|
417
|
-
attempt,
|
|
418
|
-
delay_ms: delay,
|
|
419
|
-
server_trace_id: traceId
|
|
420
|
-
});
|
|
421
|
-
await sleep(delay);
|
|
422
|
-
}
|
|
423
|
-
this.abortController = new AbortController();
|
|
424
|
-
let timedOut = false;
|
|
425
|
-
const timeoutId = this.timeoutMs == null ? null : setTimeout(() => {
|
|
426
|
-
timedOut = true;
|
|
427
|
-
this.abortController?.abort();
|
|
428
|
-
}, this.timeoutMs);
|
|
429
|
-
const combinedSignal = signal ? anySignal([signal, this.abortController.signal]) : this.abortController.signal;
|
|
430
|
-
const attemptStart = nowMs();
|
|
431
|
-
try {
|
|
432
|
-
const response = await (0, import_undici.fetch)(url, {
|
|
433
|
-
method,
|
|
434
|
-
headers,
|
|
435
|
-
body,
|
|
436
|
-
signal: combinedSignal
|
|
437
|
-
});
|
|
438
|
-
if (timeoutId != null) clearTimeout(timeoutId);
|
|
439
|
-
logSdkTiming("http.request", "headers", attemptStart, {
|
|
440
|
-
method,
|
|
441
|
-
path: timingPath,
|
|
442
|
-
status: response.status,
|
|
443
|
-
attempt,
|
|
444
|
-
server_trace_id: traceId
|
|
445
|
-
});
|
|
446
|
-
if (response.ok) {
|
|
447
|
-
logSdkTiming("http.request", "complete", operationStart, {
|
|
448
|
-
method,
|
|
449
|
-
path: timingPath,
|
|
450
|
-
status: response.status,
|
|
451
|
-
attempts: attempt + 1,
|
|
452
|
-
server_trace_id: traceId
|
|
453
|
-
});
|
|
454
|
-
return { response, traceId };
|
|
455
|
-
}
|
|
456
|
-
if (retryableStatusCodes.has(response.status) && attempt < this.maxRetries) {
|
|
457
|
-
lastError = new RemoteAPIError(
|
|
458
|
-
response.status,
|
|
459
|
-
await response.text().catch(() => "")
|
|
460
|
-
);
|
|
461
|
-
logSdkTimingEvent("http.request", "retryable_status", {
|
|
462
|
-
method,
|
|
463
|
-
path: timingPath,
|
|
464
|
-
status: response.status,
|
|
465
|
-
attempt,
|
|
466
|
-
server_trace_id: traceId
|
|
467
|
-
});
|
|
468
|
-
continue;
|
|
469
|
-
}
|
|
470
|
-
if (allowHttpErrors || allowedErrorStatusCodes.has(response.status)) {
|
|
471
|
-
logSdkTiming("http.request", "complete", operationStart, {
|
|
472
|
-
method,
|
|
473
|
-
path: timingPath,
|
|
474
|
-
status: response.status,
|
|
475
|
-
attempts: attempt + 1,
|
|
476
|
-
server_trace_id: traceId
|
|
477
|
-
});
|
|
478
|
-
return { response, traceId };
|
|
479
|
-
}
|
|
480
|
-
const errorBody = await response.text().catch(() => "");
|
|
481
|
-
throwMappedError(response.status, errorBody, path2);
|
|
482
|
-
} catch (err) {
|
|
483
|
-
if (timeoutId != null) clearTimeout(timeoutId);
|
|
484
|
-
if (err instanceof RemoteAPIError || err instanceof SandboxNotFoundError || err instanceof PoolNotFoundError || err instanceof PoolInUseError) {
|
|
485
|
-
throw err;
|
|
486
|
-
}
|
|
487
|
-
if (signal?.aborted && !timedOut) {
|
|
488
|
-
throw new SandboxConnectionError("request aborted by caller", {
|
|
489
|
-
cause: err
|
|
490
|
-
});
|
|
491
|
-
}
|
|
492
|
-
lastError = err instanceof Error ? err : new Error(String(err));
|
|
493
|
-
logSdkTiming("http.request", "error", attemptStart, {
|
|
494
|
-
method,
|
|
495
|
-
path: timingPath,
|
|
496
|
-
attempt,
|
|
497
|
-
server_trace_id: traceId,
|
|
498
|
-
error: timedOut ? `request timed out after ${this.timeoutMs}ms` : describeError(err)
|
|
499
|
-
});
|
|
500
|
-
if (attempt >= this.maxRetries) {
|
|
501
|
-
const detail = timedOut ? `request timed out after ${this.timeoutMs}ms` : describeError(err);
|
|
502
|
-
throw new SandboxConnectionError(detail, { cause: err });
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
throw new SandboxConnectionError(
|
|
507
|
-
lastError ? describeError(lastError) : "request failed",
|
|
508
|
-
{ cause: lastError }
|
|
509
|
-
);
|
|
510
|
-
}
|
|
511
|
-
};
|
|
306
|
+
import_meta = {};
|
|
512
307
|
}
|
|
513
308
|
});
|
|
514
309
|
|
|
@@ -3017,75 +2812,67 @@ var init_desktop = __esm({
|
|
|
3017
2812
|
}
|
|
3018
2813
|
});
|
|
3019
2814
|
|
|
3020
|
-
// src/
|
|
3021
|
-
|
|
3022
|
-
const
|
|
3023
|
-
|
|
3024
|
-
let buffer = "";
|
|
3025
|
-
try {
|
|
3026
|
-
while (true) {
|
|
3027
|
-
if (signal?.aborted) break;
|
|
3028
|
-
const { done, value } = await reader.read();
|
|
3029
|
-
if (done) break;
|
|
3030
|
-
buffer += decoder.decode(value, { stream: true });
|
|
3031
|
-
const parts = buffer.split(/\r?\n\r?\n/);
|
|
3032
|
-
buffer = parts.pop() ?? "";
|
|
3033
|
-
for (const part of parts) {
|
|
3034
|
-
const lines = part.split(/\r?\n/);
|
|
3035
|
-
const dataLines = [];
|
|
3036
|
-
let event;
|
|
3037
|
-
let id;
|
|
3038
|
-
for (const line of lines) {
|
|
3039
|
-
if (!line || line.startsWith(":")) continue;
|
|
3040
|
-
const separator = line.indexOf(":");
|
|
3041
|
-
const field = separator === -1 ? line : line.slice(0, separator);
|
|
3042
|
-
let value2 = separator === -1 ? "" : line.slice(separator + 1);
|
|
3043
|
-
if (value2.startsWith(" ")) {
|
|
3044
|
-
value2 = value2.slice(1);
|
|
3045
|
-
}
|
|
3046
|
-
if (field === "data") {
|
|
3047
|
-
dataLines.push(value2);
|
|
3048
|
-
} else if (field === "event") {
|
|
3049
|
-
event = value2;
|
|
3050
|
-
} else if (field === "id") {
|
|
3051
|
-
id = value2;
|
|
3052
|
-
}
|
|
3053
|
-
}
|
|
3054
|
-
if (dataLines.length > 0 || event || id) {
|
|
3055
|
-
yield { data: dataLines.join("\n"), event, id };
|
|
3056
|
-
}
|
|
3057
|
-
}
|
|
3058
|
-
}
|
|
3059
|
-
} finally {
|
|
3060
|
-
reader.releaseLock();
|
|
3061
|
-
}
|
|
2815
|
+
// src/sdk-timings.ts
|
|
2816
|
+
function sdkTimingsEnabled() {
|
|
2817
|
+
const value = process.env[SDK_TIMINGS_ENV_VAR];
|
|
2818
|
+
return value === "1" || value === "true" || value === "yes";
|
|
3062
2819
|
}
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
try {
|
|
3067
|
-
yield JSON.parse(message.data);
|
|
3068
|
-
} catch {
|
|
3069
|
-
}
|
|
3070
|
-
}
|
|
2820
|
+
function sdkTimingPayloadsEnabled() {
|
|
2821
|
+
const value = process.env[SDK_TIMING_PAYLOADS_ENV_VAR];
|
|
2822
|
+
return value === "1" || value === "true" || value === "yes";
|
|
3071
2823
|
}
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
"use strict";
|
|
3075
|
-
}
|
|
3076
|
-
});
|
|
3077
|
-
|
|
3078
|
-
// src/url.ts
|
|
3079
|
-
function trimTrailingSlashes(url) {
|
|
3080
|
-
return url.endsWith("/") ? url.slice(0, -1) : url;
|
|
2824
|
+
function nowMs() {
|
|
2825
|
+
return performance.now();
|
|
3081
2826
|
}
|
|
3082
|
-
function
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
2827
|
+
function logSdkTiming(op, phase, startedAt, fields = {}) {
|
|
2828
|
+
if (!sdkTimingsEnabled()) return;
|
|
2829
|
+
logSdkTimingEvent(op, phase, {
|
|
2830
|
+
...fields,
|
|
2831
|
+
duration_ms: Math.round((nowMs() - startedAt) * 100) / 100
|
|
2832
|
+
});
|
|
2833
|
+
}
|
|
2834
|
+
function logSdkTimingEvent(op, phase, fields = {}) {
|
|
2835
|
+
if (!sdkTimingsEnabled()) return;
|
|
2836
|
+
const parts = [
|
|
2837
|
+
"[tensorlake:sdk-timing]",
|
|
2838
|
+
`op=${op}`,
|
|
2839
|
+
`phase=${phase}`
|
|
2840
|
+
];
|
|
2841
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
2842
|
+
if (value == null) continue;
|
|
2843
|
+
parts.push(`${key}=${formatSdkTimingValue(value)}`);
|
|
2844
|
+
}
|
|
2845
|
+
console.error(parts.join(" "));
|
|
2846
|
+
}
|
|
2847
|
+
function formatSdkTimingValue(value) {
|
|
2848
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
2849
|
+
return String(value);
|
|
2850
|
+
}
|
|
2851
|
+
if (/^[A-Za-z0-9_./:@-]+$/.test(value)) {
|
|
2852
|
+
return value;
|
|
2853
|
+
}
|
|
2854
|
+
return JSON.stringify(value);
|
|
2855
|
+
}
|
|
2856
|
+
var SDK_TIMINGS_ENV_VAR, SDK_TIMING_PAYLOADS_ENV_VAR;
|
|
2857
|
+
var init_sdk_timings = __esm({
|
|
2858
|
+
"src/sdk-timings.ts"() {
|
|
2859
|
+
"use strict";
|
|
2860
|
+
SDK_TIMINGS_ENV_VAR = "TENSORLAKE_SDK_TIMINGS";
|
|
2861
|
+
SDK_TIMING_PAYLOADS_ENV_VAR = "TENSORLAKE_SDK_TIMING_PAYLOADS";
|
|
2862
|
+
}
|
|
2863
|
+
});
|
|
2864
|
+
|
|
2865
|
+
// src/url.ts
|
|
2866
|
+
function trimTrailingSlashes(url) {
|
|
2867
|
+
return url.endsWith("/") ? url.slice(0, -1) : url;
|
|
2868
|
+
}
|
|
2869
|
+
function isLocalhost(apiUrl) {
|
|
2870
|
+
try {
|
|
2871
|
+
const parsed = new URL(apiUrl);
|
|
2872
|
+
return parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1";
|
|
2873
|
+
} catch {
|
|
2874
|
+
return false;
|
|
2875
|
+
}
|
|
3089
2876
|
}
|
|
3090
2877
|
function resolveProxyUrl(apiUrl) {
|
|
3091
2878
|
const explicit = process.env.TENSORLAKE_SANDBOX_PROXY_URL;
|
|
@@ -3135,24 +2922,6 @@ function sandboxUrlFromIngressEndpoint(ingressEndpoint, sandboxId, port = 9501)
|
|
|
3135
2922
|
const label = port === 9501 ? sandboxId : `${port}-${sandboxId}`;
|
|
3136
2923
|
return `${parsed.protocol}//${label}.${parsed.host}`;
|
|
3137
2924
|
}
|
|
3138
|
-
function resolveSandboxLifecycleUrl(apiUrl) {
|
|
3139
|
-
if (isLocalhost(apiUrl)) return apiUrl;
|
|
3140
|
-
try {
|
|
3141
|
-
const parsed = new URL(apiUrl);
|
|
3142
|
-
if (parsed.hostname.startsWith("api.")) {
|
|
3143
|
-
parsed.hostname = "sandbox." + parsed.hostname.slice(4);
|
|
3144
|
-
return parsed.toString().replace(/\/$/, "");
|
|
3145
|
-
}
|
|
3146
|
-
} catch {
|
|
3147
|
-
}
|
|
3148
|
-
return apiUrl;
|
|
3149
|
-
}
|
|
3150
|
-
function lifecyclePath(path2, isLocal, namespace) {
|
|
3151
|
-
if (isLocal) {
|
|
3152
|
-
return `/v1/namespaces/${namespace}/${path2}`;
|
|
3153
|
-
}
|
|
3154
|
-
return `/${path2}`;
|
|
3155
|
-
}
|
|
3156
2925
|
var init_url = __esm({
|
|
3157
2926
|
"src/url.ts"() {
|
|
3158
2927
|
"use strict";
|
|
@@ -3163,7 +2932,7 @@ var init_url = __esm({
|
|
|
3163
2932
|
// src/sandbox.ts
|
|
3164
2933
|
function processUserPayload(user) {
|
|
3165
2934
|
if (user == null) {
|
|
3166
|
-
return
|
|
2935
|
+
return void 0;
|
|
3167
2936
|
}
|
|
3168
2937
|
if (typeof user === "string" && user.trim() === "") {
|
|
3169
2938
|
throw new SandboxError("process user must not be empty");
|
|
@@ -3193,33 +2962,25 @@ function sendPtyFrame(socket, frame) {
|
|
|
3193
2962
|
socket.send(frame, (error) => error ? reject(error) : resolve());
|
|
3194
2963
|
});
|
|
3195
2964
|
}
|
|
3196
|
-
|
|
3197
|
-
if (!Number.isFinite(seconds) || seconds <= 0) {
|
|
3198
|
-
throw new SandboxError("requestTimeout must be a positive number of seconds");
|
|
3199
|
-
}
|
|
3200
|
-
return Math.ceil(seconds * 1e3);
|
|
3201
|
-
}
|
|
3202
|
-
var import_ws2, DEFAULT_PROCESS_USER, SandboxProxyConnection, PTY_OP_DATA, PTY_OP_RESIZE, PTY_OP_READY, PTY_OP_EXIT, Pty, Sandbox;
|
|
2965
|
+
var import_ws2, SandboxProxyConnection, PTY_OP_DATA, PTY_OP_RESIZE, PTY_OP_READY, PTY_OP_EXIT, Pty, Sandbox;
|
|
3203
2966
|
var init_sandbox = __esm({
|
|
3204
2967
|
"src/sandbox.ts"() {
|
|
3205
2968
|
"use strict";
|
|
3206
2969
|
init_desktop();
|
|
3207
2970
|
init_defaults();
|
|
3208
2971
|
init_errors();
|
|
3209
|
-
|
|
2972
|
+
init_native_sandbox();
|
|
3210
2973
|
init_models();
|
|
3211
2974
|
init_tunnel();
|
|
3212
|
-
init_sse();
|
|
3213
2975
|
init_sdk_timings();
|
|
3214
2976
|
init_url();
|
|
3215
2977
|
import_ws2 = __toESM(require("ws"), 1);
|
|
3216
|
-
DEFAULT_PROCESS_USER = "tl-user";
|
|
3217
2978
|
SandboxProxyConnection = class {
|
|
3218
2979
|
constructor(sandbox, options) {
|
|
3219
2980
|
this.sandbox = sandbox;
|
|
3220
2981
|
this.options = options;
|
|
3221
2982
|
this.routingHint = options.routingHint;
|
|
3222
|
-
this.
|
|
2983
|
+
this.nativeProxy = this.configureProxy(
|
|
3223
2984
|
options.proxyUrl ?? SANDBOX_PROXY_URL,
|
|
3224
2985
|
options.sandboxId,
|
|
3225
2986
|
options.routingHint
|
|
@@ -3228,7 +2989,7 @@ var init_sandbox = __esm({
|
|
|
3228
2989
|
}
|
|
3229
2990
|
baseUrl = "";
|
|
3230
2991
|
wsHeaders = {};
|
|
3231
|
-
|
|
2992
|
+
nativeProxy;
|
|
3232
2993
|
resolveProxyInfo;
|
|
3233
2994
|
resolvePromise = null;
|
|
3234
2995
|
routingHint;
|
|
@@ -3251,9 +3012,11 @@ var init_sandbox = __esm({
|
|
|
3251
3012
|
this.sandbox._setName(info.name ?? null);
|
|
3252
3013
|
this.routingHint = this.routingHint ?? info.routingHint;
|
|
3253
3014
|
const proxyUrl = info.ingressEndpoint ?? this.options.proxyUrl ?? SANDBOX_PROXY_URL;
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3015
|
+
this.nativeProxy = this.configureProxy(
|
|
3016
|
+
proxyUrl,
|
|
3017
|
+
info.sandboxId,
|
|
3018
|
+
this.routingHint
|
|
3019
|
+
);
|
|
3257
3020
|
logSdkTiming("sandbox.proxy", "resolve_complete", resolveStart, {
|
|
3258
3021
|
sandbox_id: info.sandboxId,
|
|
3259
3022
|
server_trace_id: info.traceId,
|
|
@@ -3265,24 +3028,12 @@ var init_sandbox = __esm({
|
|
|
3265
3028
|
});
|
|
3266
3029
|
return this.resolvePromise;
|
|
3267
3030
|
}
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
return this.http.requestJson(method, path2, options);
|
|
3271
|
-
}
|
|
3272
|
-
async requestBytes(method, path2, options) {
|
|
3031
|
+
/** Await proxy resolution and return the Rust-backed proxy client. */
|
|
3032
|
+
async client() {
|
|
3273
3033
|
await this.ensureResolved();
|
|
3274
|
-
return this.
|
|
3275
|
-
}
|
|
3276
|
-
async requestStream(method, path2, options) {
|
|
3277
|
-
await this.ensureResolved();
|
|
3278
|
-
return this.http.requestStream(method, path2, options);
|
|
3279
|
-
}
|
|
3280
|
-
async requestResponse(method, path2, options) {
|
|
3281
|
-
await this.ensureResolved();
|
|
3282
|
-
return this.http.requestResponse(method, path2, options);
|
|
3034
|
+
return this.nativeProxy;
|
|
3283
3035
|
}
|
|
3284
3036
|
close() {
|
|
3285
|
-
this.http.close();
|
|
3286
3037
|
}
|
|
3287
3038
|
configureProxy(proxyUrl, sandboxId, routingHint) {
|
|
3288
3039
|
const { baseUrl, hostHeader, sandboxIdHeader } = resolveProxyTarget(
|
|
@@ -3306,16 +3057,34 @@ var init_sandbox = __esm({
|
|
|
3306
3057
|
if (sandboxIdHeader) {
|
|
3307
3058
|
this.wsHeaders["X-Tensorlake-Sandbox-Id"] = sandboxIdHeader;
|
|
3308
3059
|
}
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3060
|
+
if (this.options.nativeClient) {
|
|
3061
|
+
return this.options.nativeClient.connectProxy(
|
|
3062
|
+
proxyUrl,
|
|
3063
|
+
sandboxId,
|
|
3064
|
+
routingHint ?? null,
|
|
3065
|
+
this.proxyRequestTimeoutSec()
|
|
3066
|
+
);
|
|
3067
|
+
}
|
|
3068
|
+
const binding = loadNativeSandboxBinding();
|
|
3069
|
+
return new binding.NativeSandboxProxyClient(
|
|
3070
|
+
proxyUrl,
|
|
3071
|
+
sandboxId,
|
|
3072
|
+
this.options.apiKey ?? null,
|
|
3073
|
+
this.options.organizationId ?? null,
|
|
3074
|
+
this.options.projectId ?? null,
|
|
3075
|
+
routingHint ?? null,
|
|
3076
|
+
null,
|
|
3077
|
+
this.proxyRequestTimeoutSec()
|
|
3078
|
+
);
|
|
3079
|
+
}
|
|
3080
|
+
proxyRequestTimeoutSec() {
|
|
3081
|
+
if (this.options.requestTimeout != null) {
|
|
3082
|
+
return this.options.requestTimeout;
|
|
3083
|
+
}
|
|
3084
|
+
if (this.options.timeoutMs != null) {
|
|
3085
|
+
return this.options.timeoutMs / 1e3;
|
|
3086
|
+
}
|
|
3087
|
+
return null;
|
|
3319
3088
|
}
|
|
3320
3089
|
};
|
|
3321
3090
|
PTY_OP_DATA = 0;
|
|
@@ -3484,7 +3253,6 @@ var init_sandbox = __esm({
|
|
|
3484
3253
|
sandboxId;
|
|
3485
3254
|
traceId = null;
|
|
3486
3255
|
proxy;
|
|
3487
|
-
http;
|
|
3488
3256
|
ownsSandbox = false;
|
|
3489
3257
|
lifecycleClient = null;
|
|
3490
3258
|
lifecycleIdentifier;
|
|
@@ -3493,7 +3261,6 @@ var init_sandbox = __esm({
|
|
|
3493
3261
|
this.sandboxId = options.sandboxId;
|
|
3494
3262
|
this.lifecycleIdentifier = options.sandboxId;
|
|
3495
3263
|
this.proxy = new SandboxProxyConnection(this, options);
|
|
3496
|
-
this.http = this.proxy;
|
|
3497
3264
|
}
|
|
3498
3265
|
get baseUrl() {
|
|
3499
3266
|
return this.proxy.baseUrl;
|
|
@@ -3698,9 +3465,9 @@ var init_sandbox = __esm({
|
|
|
3698
3465
|
const filtered = all.filter((s) => s.sandboxId === this.lifecycleIdentifier);
|
|
3699
3466
|
return Object.assign(filtered, { traceId: all.traceId });
|
|
3700
3467
|
}
|
|
3701
|
-
/** Close the
|
|
3468
|
+
/** Close the proxy connection. The sandbox keeps running. */
|
|
3702
3469
|
close() {
|
|
3703
|
-
this.
|
|
3470
|
+
this.proxy.close();
|
|
3704
3471
|
}
|
|
3705
3472
|
/** Terminate the sandbox and release all resources. */
|
|
3706
3473
|
async terminate() {
|
|
@@ -3727,51 +3494,18 @@ var init_sandbox = __esm({
|
|
|
3727
3494
|
if (options?.workingDir) body.working_dir = options.workingDir;
|
|
3728
3495
|
if (options?.timeout != null) body.timeout = options.timeout;
|
|
3729
3496
|
const user = processUserPayload(options?.user);
|
|
3730
|
-
body.user = user;
|
|
3497
|
+
if (user !== void 0) body.user = user;
|
|
3731
3498
|
logSdkTimingEvent("sandbox.run", "start", {
|
|
3732
3499
|
sandbox_id: this.sandboxId,
|
|
3733
3500
|
command: sdkTimingPayloadsEnabled() ? command : void 0,
|
|
3734
3501
|
command_length: command.length
|
|
3735
3502
|
});
|
|
3736
|
-
const
|
|
3737
|
-
const
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
{ json: body }
|
|
3503
|
+
const proxy = await this.proxy.client();
|
|
3504
|
+
const { traceId, events } = await callNative(
|
|
3505
|
+
() => proxy.runProcess(JSON.stringify(body)),
|
|
3506
|
+
{ sandboxId: this.sandboxId }
|
|
3741
3507
|
);
|
|
3742
|
-
const
|
|
3743
|
-
logSdkTiming("sandbox.run", "stream_headers", requestStart, {
|
|
3744
|
-
sandbox_id: this.sandboxId,
|
|
3745
|
-
server_trace_id: traceId,
|
|
3746
|
-
command: sdkTimingPayloadsEnabled() ? command : void 0,
|
|
3747
|
-
command_length: command.length
|
|
3748
|
-
});
|
|
3749
|
-
const stdoutLines = [];
|
|
3750
|
-
const stderrLines = [];
|
|
3751
|
-
let exitCode = -1;
|
|
3752
|
-
const streamStart = nowMs();
|
|
3753
|
-
for await (const raw of parseSSEStream(sseStream)) {
|
|
3754
|
-
if (typeof raw.line === "string") {
|
|
3755
|
-
if (raw.stream === "stderr") {
|
|
3756
|
-
stderrLines.push(raw.line);
|
|
3757
|
-
} else {
|
|
3758
|
-
stdoutLines.push(raw.line);
|
|
3759
|
-
}
|
|
3760
|
-
} else if ("exit_code" in raw || "signal" in raw) {
|
|
3761
|
-
if (typeof raw.exit_code === "number") {
|
|
3762
|
-
exitCode = raw.exit_code;
|
|
3763
|
-
} else if (typeof raw.signal === "number") {
|
|
3764
|
-
exitCode = -raw.signal;
|
|
3765
|
-
}
|
|
3766
|
-
}
|
|
3767
|
-
}
|
|
3768
|
-
logSdkTiming("sandbox.run", "stream_complete", streamStart, {
|
|
3769
|
-
sandbox_id: this.sandboxId,
|
|
3770
|
-
server_trace_id: traceId,
|
|
3771
|
-
command: sdkTimingPayloadsEnabled() ? command : void 0,
|
|
3772
|
-
command_length: command.length,
|
|
3773
|
-
exit_code: exitCode
|
|
3774
|
-
});
|
|
3508
|
+
const { exitCode, stdout, stderr } = assembleCommandResult(events);
|
|
3775
3509
|
logSdkTiming("sandbox.run", "complete", opStart, {
|
|
3776
3510
|
sandbox_id: this.sandboxId,
|
|
3777
3511
|
server_trace_id: traceId,
|
|
@@ -3779,10 +3513,7 @@ var init_sandbox = __esm({
|
|
|
3779
3513
|
command_length: command.length,
|
|
3780
3514
|
exit_code: exitCode
|
|
3781
3515
|
});
|
|
3782
|
-
return Object.assign(
|
|
3783
|
-
{ exitCode, stdout: stdoutLines.join("\n"), stderr: stderrLines.join("\n") },
|
|
3784
|
-
{ traceId }
|
|
3785
|
-
);
|
|
3516
|
+
return Object.assign({ exitCode, stdout, stderr }, { traceId });
|
|
3786
3517
|
}
|
|
3787
3518
|
// --- Process management ---
|
|
3788
3519
|
/**
|
|
@@ -3799,7 +3530,7 @@ var init_sandbox = __esm({
|
|
|
3799
3530
|
if (options?.env != null) payload.env = options.env;
|
|
3800
3531
|
if (options?.workingDir != null) payload.working_dir = options.workingDir;
|
|
3801
3532
|
const user = processUserPayload(options?.user);
|
|
3802
|
-
payload.user = user;
|
|
3533
|
+
if (user !== void 0) payload.user = user;
|
|
3803
3534
|
if (options?.stdinMode != null && options.stdinMode !== "closed" /* CLOSED */) {
|
|
3804
3535
|
payload.stdin_mode = options.stdinMode;
|
|
3805
3536
|
}
|
|
@@ -3814,97 +3545,101 @@ var init_sandbox = __esm({
|
|
|
3814
3545
|
if (options?.healthCheck != null) {
|
|
3815
3546
|
payload.health_check = toSnakeKeys(options.healthCheck);
|
|
3816
3547
|
}
|
|
3817
|
-
const
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
{
|
|
3548
|
+
const proxy = await this.proxy.client();
|
|
3549
|
+
const { traceId, json } = await callNative(
|
|
3550
|
+
() => proxy.startProcess(JSON.stringify(payload)),
|
|
3551
|
+
{ sandboxId: this.sandboxId }
|
|
3821
3552
|
);
|
|
3822
|
-
return Object.assign(fromSnakeKeys(
|
|
3553
|
+
return Object.assign(fromSnakeKeys(JSON.parse(json)), { traceId });
|
|
3823
3554
|
}
|
|
3824
3555
|
/** List all processes (running and exited) tracked by the sandbox daemon. */
|
|
3825
3556
|
async listProcesses() {
|
|
3826
|
-
const
|
|
3827
|
-
|
|
3828
|
-
|
|
3557
|
+
const proxy = await this.proxy.client();
|
|
3558
|
+
const { traceId, json } = await callNative(() => proxy.listProcesses(), {
|
|
3559
|
+
sandboxId: this.sandboxId
|
|
3560
|
+
});
|
|
3561
|
+
const parsed = JSON.parse(json);
|
|
3562
|
+
const processes = (parsed.processes ?? []).map(
|
|
3563
|
+
(p) => fromSnakeKeys(p)
|
|
3829
3564
|
);
|
|
3830
|
-
|
|
3831
|
-
return Object.assign(processes, { traceId: raw.traceId });
|
|
3565
|
+
return Object.assign(processes, { traceId });
|
|
3832
3566
|
}
|
|
3833
3567
|
/** Get current status and metadata for a process by PID. */
|
|
3834
3568
|
async getProcess(pid) {
|
|
3835
|
-
const
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
);
|
|
3839
|
-
return Object.assign(fromSnakeKeys(
|
|
3569
|
+
const proxy = await this.proxy.client();
|
|
3570
|
+
const { traceId, json } = await callNative(() => proxy.getProcess(pid), {
|
|
3571
|
+
sandboxId: this.sandboxId
|
|
3572
|
+
});
|
|
3573
|
+
return Object.assign(fromSnakeKeys(JSON.parse(json)), { traceId });
|
|
3840
3574
|
}
|
|
3841
3575
|
/** Send SIGKILL to a process. */
|
|
3842
3576
|
async killProcess(pid) {
|
|
3843
|
-
await this.
|
|
3577
|
+
const proxy = await this.proxy.client();
|
|
3578
|
+
await callNative(() => proxy.killProcess(pid), { sandboxId: this.sandboxId });
|
|
3844
3579
|
}
|
|
3845
3580
|
/** Restart a managed process by PID. */
|
|
3846
3581
|
async restartProcess(pid) {
|
|
3847
|
-
const
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
);
|
|
3851
|
-
return Object.assign(fromSnakeKeys(
|
|
3582
|
+
const proxy = await this.proxy.client();
|
|
3583
|
+
const { traceId, json } = await callNative(() => proxy.restartProcess(pid), {
|
|
3584
|
+
sandboxId: this.sandboxId
|
|
3585
|
+
});
|
|
3586
|
+
return Object.assign(fromSnakeKeys(JSON.parse(json)), { traceId });
|
|
3852
3587
|
}
|
|
3853
3588
|
/** Send an arbitrary signal to a process (e.g. `15` for SIGTERM, `9` for SIGKILL). */
|
|
3854
3589
|
async sendSignal(pid, signal) {
|
|
3855
|
-
const
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
{
|
|
3590
|
+
const proxy = await this.proxy.client();
|
|
3591
|
+
const { traceId, json } = await callNative(
|
|
3592
|
+
() => proxy.sendSignal(pid, signal),
|
|
3593
|
+
{ sandboxId: this.sandboxId }
|
|
3859
3594
|
);
|
|
3860
|
-
return Object.assign(fromSnakeKeys(
|
|
3595
|
+
return Object.assign(fromSnakeKeys(JSON.parse(json)), {
|
|
3596
|
+
traceId
|
|
3597
|
+
});
|
|
3861
3598
|
}
|
|
3862
3599
|
// --- Process I/O ---
|
|
3863
3600
|
/** Write bytes to a process's stdin. The process must have been started with `stdinMode: StdinMode.PIPE`. */
|
|
3864
3601
|
async writeStdin(pid, data) {
|
|
3865
|
-
await this.
|
|
3866
|
-
|
|
3867
|
-
|
|
3602
|
+
const proxy = await this.proxy.client();
|
|
3603
|
+
await callNative(() => proxy.writeStdin(pid, Buffer.from(data)), {
|
|
3604
|
+
sandboxId: this.sandboxId
|
|
3868
3605
|
});
|
|
3869
3606
|
}
|
|
3870
3607
|
/** Close a process's stdin pipe, signalling EOF to the process. */
|
|
3871
3608
|
async closeStdin(pid) {
|
|
3872
|
-
await this.
|
|
3609
|
+
const proxy = await this.proxy.client();
|
|
3610
|
+
await callNative(() => proxy.closeStdin(pid), { sandboxId: this.sandboxId });
|
|
3873
3611
|
}
|
|
3874
3612
|
/** Return all captured stdout lines produced so far by a process. */
|
|
3875
3613
|
async getStdout(pid) {
|
|
3876
|
-
const
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
);
|
|
3880
|
-
return Object.assign(fromSnakeKeys(
|
|
3614
|
+
const proxy = await this.proxy.client();
|
|
3615
|
+
const { traceId, json } = await callNative(() => proxy.getStdout(pid), {
|
|
3616
|
+
sandboxId: this.sandboxId
|
|
3617
|
+
});
|
|
3618
|
+
return Object.assign(fromSnakeKeys(JSON.parse(json)), { traceId });
|
|
3881
3619
|
}
|
|
3882
3620
|
/** Return all captured stderr lines produced so far by a process. */
|
|
3883
3621
|
async getStderr(pid) {
|
|
3884
|
-
const
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
);
|
|
3888
|
-
return Object.assign(fromSnakeKeys(
|
|
3622
|
+
const proxy = await this.proxy.client();
|
|
3623
|
+
const { traceId, json } = await callNative(() => proxy.getStderr(pid), {
|
|
3624
|
+
sandboxId: this.sandboxId
|
|
3625
|
+
});
|
|
3626
|
+
return Object.assign(fromSnakeKeys(JSON.parse(json)), { traceId });
|
|
3889
3627
|
}
|
|
3890
3628
|
/** Return all captured stdout+stderr lines produced so far by a process. */
|
|
3891
3629
|
async getOutput(pid) {
|
|
3892
|
-
const
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
);
|
|
3896
|
-
return Object.assign(fromSnakeKeys(
|
|
3630
|
+
const proxy = await this.proxy.client();
|
|
3631
|
+
const { traceId, json } = await callNative(() => proxy.getOutput(pid), {
|
|
3632
|
+
sandboxId: this.sandboxId
|
|
3633
|
+
});
|
|
3634
|
+
return Object.assign(fromSnakeKeys(JSON.parse(json)), { traceId });
|
|
3897
3635
|
}
|
|
3898
3636
|
// --- Streaming (SSE) ---
|
|
3899
3637
|
/** Stream stdout events from a process until it exits. Yields one `OutputEvent` per line. */
|
|
3900
3638
|
async *followStdout(pid, options) {
|
|
3901
|
-
const
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
);
|
|
3906
|
-
for await (const raw of parseSSEStream(
|
|
3907
|
-
stream,
|
|
3639
|
+
const proxy = await this.proxy.client();
|
|
3640
|
+
for await (const raw of nativeEventStream(
|
|
3641
|
+
(emit) => proxy.followStdout(pid, emit),
|
|
3642
|
+
{ sandboxId: this.sandboxId },
|
|
3908
3643
|
options?.signal
|
|
3909
3644
|
)) {
|
|
3910
3645
|
yield fromSnakeKeys(raw);
|
|
@@ -3912,13 +3647,10 @@ var init_sandbox = __esm({
|
|
|
3912
3647
|
}
|
|
3913
3648
|
/** Stream stderr events from a process until it exits. Yields one `OutputEvent` per line. */
|
|
3914
3649
|
async *followStderr(pid, options) {
|
|
3915
|
-
const
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
);
|
|
3920
|
-
for await (const raw of parseSSEStream(
|
|
3921
|
-
stream,
|
|
3650
|
+
const proxy = await this.proxy.client();
|
|
3651
|
+
for await (const raw of nativeEventStream(
|
|
3652
|
+
(emit) => proxy.followStderr(pid, emit),
|
|
3653
|
+
{ sandboxId: this.sandboxId },
|
|
3922
3654
|
options?.signal
|
|
3923
3655
|
)) {
|
|
3924
3656
|
yield fromSnakeKeys(raw);
|
|
@@ -3926,13 +3658,10 @@ var init_sandbox = __esm({
|
|
|
3926
3658
|
}
|
|
3927
3659
|
/** Stream combined stdout+stderr events from a process until it exits. Yields one `OutputEvent` per line. */
|
|
3928
3660
|
async *followOutput(pid, options) {
|
|
3929
|
-
const
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
);
|
|
3934
|
-
for await (const raw of parseSSEStream(
|
|
3935
|
-
stream,
|
|
3661
|
+
const proxy = await this.proxy.client();
|
|
3662
|
+
for await (const raw of nativeEventStream(
|
|
3663
|
+
(emit) => proxy.followOutput(pid, emit),
|
|
3664
|
+
{ sandboxId: this.sandboxId },
|
|
3936
3665
|
options?.signal
|
|
3937
3666
|
)) {
|
|
3938
3667
|
yield fromSnakeKeys(raw);
|
|
@@ -3941,33 +3670,33 @@ var init_sandbox = __esm({
|
|
|
3941
3670
|
// --- File operations ---
|
|
3942
3671
|
/** Read a file from the sandbox and return its raw bytes. */
|
|
3943
3672
|
async readFile(path2) {
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
);
|
|
3673
|
+
const proxy = await this.proxy.client();
|
|
3674
|
+
const { traceId, data } = await callNative(() => proxy.readFile(path2), {
|
|
3675
|
+
sandboxId: this.sandboxId
|
|
3676
|
+
});
|
|
3677
|
+
return Object.assign(Uint8Array.from(data), { traceId });
|
|
3948
3678
|
}
|
|
3949
3679
|
/** Write raw bytes to a file in the sandbox, creating it if it does not exist. */
|
|
3950
3680
|
async writeFile(path2, content) {
|
|
3951
|
-
await this.
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
);
|
|
3681
|
+
const proxy = await this.proxy.client();
|
|
3682
|
+
await callNative(() => proxy.writeFile(path2, Buffer.from(content)), {
|
|
3683
|
+
sandboxId: this.sandboxId
|
|
3684
|
+
});
|
|
3956
3685
|
}
|
|
3957
3686
|
/** Delete a file from the sandbox. */
|
|
3958
3687
|
async deleteFile(path2) {
|
|
3959
|
-
await this.
|
|
3960
|
-
|
|
3961
|
-
`/api/v1/files?path=${encodeURIComponent(path2)}`
|
|
3962
|
-
);
|
|
3688
|
+
const proxy = await this.proxy.client();
|
|
3689
|
+
await callNative(() => proxy.deleteFile(path2), { sandboxId: this.sandboxId });
|
|
3963
3690
|
}
|
|
3964
3691
|
/** List the contents of a directory in the sandbox. */
|
|
3965
3692
|
async listDirectory(path2) {
|
|
3966
|
-
const
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
);
|
|
3970
|
-
return Object.assign(fromSnakeKeys(
|
|
3693
|
+
const proxy = await this.proxy.client();
|
|
3694
|
+
const { traceId, json } = await callNative(() => proxy.listDirectory(path2), {
|
|
3695
|
+
sandboxId: this.sandboxId
|
|
3696
|
+
});
|
|
3697
|
+
return Object.assign(fromSnakeKeys(JSON.parse(json)), {
|
|
3698
|
+
traceId
|
|
3699
|
+
});
|
|
3971
3700
|
}
|
|
3972
3701
|
// --- PTY ---
|
|
3973
3702
|
/** Create an interactive PTY session. Returns a `sessionId` and `token` for WebSocket connection via `connectPty()`. */
|
|
@@ -3980,12 +3709,12 @@ var init_sandbox = __esm({
|
|
|
3980
3709
|
if (options.args != null) payload.args = options.args;
|
|
3981
3710
|
if (options.env != null) payload.env = options.env;
|
|
3982
3711
|
if (options.workingDir != null) payload.working_dir = options.workingDir;
|
|
3983
|
-
const
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
{
|
|
3712
|
+
const proxy = await this.proxy.client();
|
|
3713
|
+
const { traceId, json } = await callNative(
|
|
3714
|
+
() => proxy.createPtySession(JSON.stringify(payload)),
|
|
3715
|
+
{ sandboxId: this.sandboxId }
|
|
3987
3716
|
);
|
|
3988
|
-
return Object.assign(fromSnakeKeys(
|
|
3717
|
+
return Object.assign(fromSnakeKeys(JSON.parse(json)), { traceId });
|
|
3989
3718
|
}
|
|
3990
3719
|
/** Create a PTY session and connect to it immediately. Cleans up the session if the WebSocket connection fails. */
|
|
3991
3720
|
async createPty(options) {
|
|
@@ -3995,7 +3724,8 @@ var init_sandbox = __esm({
|
|
|
3995
3724
|
return await this.connectPty(session.sessionId, session.token, { onData, onExit });
|
|
3996
3725
|
} catch (error) {
|
|
3997
3726
|
try {
|
|
3998
|
-
await this.
|
|
3727
|
+
const proxy = await this.proxy.client();
|
|
3728
|
+
await proxy.deletePtySession(session.sessionId);
|
|
3999
3729
|
} catch {
|
|
4000
3730
|
}
|
|
4001
3731
|
throw error;
|
|
@@ -4015,7 +3745,8 @@ var init_sandbox = __esm({
|
|
|
4015
3745
|
"X-PTY-Token": authToken
|
|
4016
3746
|
},
|
|
4017
3747
|
killSession: async () => {
|
|
4018
|
-
await this.
|
|
3748
|
+
const proxy = await this.proxy.client();
|
|
3749
|
+
await proxy.deletePtySession(sessionId);
|
|
4019
3750
|
}
|
|
4020
3751
|
});
|
|
4021
3752
|
if (options?.onData) {
|
|
@@ -4103,19 +3834,19 @@ var init_sandbox = __esm({
|
|
|
4103
3834
|
// --- Health ---
|
|
4104
3835
|
/** Check the sandbox daemon health. */
|
|
4105
3836
|
async health() {
|
|
4106
|
-
const
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
);
|
|
4110
|
-
return Object.assign(fromSnakeKeys(
|
|
3837
|
+
const proxy = await this.proxy.client();
|
|
3838
|
+
const { traceId, json } = await callNative(() => proxy.health(), {
|
|
3839
|
+
sandboxId: this.sandboxId
|
|
3840
|
+
});
|
|
3841
|
+
return Object.assign(fromSnakeKeys(JSON.parse(json)), { traceId });
|
|
4111
3842
|
}
|
|
4112
3843
|
/** Get sandbox daemon info (version, uptime, process counts). */
|
|
4113
3844
|
async daemonInfo() {
|
|
4114
|
-
const
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
);
|
|
4118
|
-
return Object.assign(fromSnakeKeys(
|
|
3845
|
+
const proxy = await this.proxy.client();
|
|
3846
|
+
const { traceId, json } = await callNative(() => proxy.info(), {
|
|
3847
|
+
sandboxId: this.sandboxId
|
|
3848
|
+
});
|
|
3849
|
+
return Object.assign(fromSnakeKeys(JSON.parse(json)), { traceId });
|
|
4119
3850
|
}
|
|
4120
3851
|
};
|
|
4121
3852
|
}
|
|
@@ -4171,7 +3902,7 @@ async function readCloudInitBase64(cloudInit) {
|
|
|
4171
3902
|
}
|
|
4172
3903
|
function resolveRequestTimeoutMs(options) {
|
|
4173
3904
|
if (options?.requestTimeout != null) {
|
|
4174
|
-
return
|
|
3905
|
+
return secondsToMillis3(options.requestTimeout);
|
|
4175
3906
|
}
|
|
4176
3907
|
if (options?.timeoutMs != null) {
|
|
4177
3908
|
validateTimeoutMs(options.timeoutMs);
|
|
@@ -4179,7 +3910,7 @@ function resolveRequestTimeoutMs(options) {
|
|
|
4179
3910
|
}
|
|
4180
3911
|
return DEFAULT_HTTP_TIMEOUT_MS;
|
|
4181
3912
|
}
|
|
4182
|
-
function
|
|
3913
|
+
function secondsToMillis3(seconds) {
|
|
4183
3914
|
if (!Number.isFinite(seconds) || seconds <= 0) {
|
|
4184
3915
|
throw new SandboxError("requestTimeout must be a positive number of seconds");
|
|
4185
3916
|
}
|
|
@@ -4190,7 +3921,7 @@ function validateTimeoutMs(timeoutMs) {
|
|
|
4190
3921
|
throw new SandboxError("timeoutMs must be a positive number of milliseconds");
|
|
4191
3922
|
}
|
|
4192
3923
|
}
|
|
4193
|
-
function
|
|
3924
|
+
function sleep(ms) {
|
|
4194
3925
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
4195
3926
|
}
|
|
4196
3927
|
function snapshotStatusSatisfiesWaitCondition(status, waitUntil) {
|
|
@@ -4246,32 +3977,26 @@ function validateUserPort(port) {
|
|
|
4246
3977
|
function dedupeAndSortPorts(ports) {
|
|
4247
3978
|
return [...new Set(ports)].sort((a, b) => a - b);
|
|
4248
3979
|
}
|
|
4249
|
-
var import_promises,
|
|
3980
|
+
var import_promises, MAX_CLOUD_INIT_USER_DATA_BYTES, SandboxClient, RESERVED_SANDBOX_MANAGEMENT_PORT;
|
|
4250
3981
|
var init_client = __esm({
|
|
4251
3982
|
"src/client.ts"() {
|
|
4252
3983
|
"use strict";
|
|
4253
3984
|
import_promises = require("fs/promises");
|
|
4254
3985
|
init_defaults();
|
|
4255
3986
|
init_errors();
|
|
4256
|
-
|
|
3987
|
+
init_native_sandbox();
|
|
4257
3988
|
init_models();
|
|
4258
3989
|
init_sandbox();
|
|
4259
3990
|
init_sdk_timings();
|
|
4260
3991
|
init_url();
|
|
4261
|
-
CREATE_SANDBOX_RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([502, 503]);
|
|
4262
|
-
CREATE_SANDBOX_ALLOWED_ERROR_STATUS_CODES = /* @__PURE__ */ new Set([504]);
|
|
4263
|
-
COPY_SANDBOX_ALLOWED_ERROR_STATUS_CODES = /* @__PURE__ */ new Set([422, 504]);
|
|
4264
3992
|
MAX_CLOUD_INIT_USER_DATA_BYTES = 16 * 1024;
|
|
4265
3993
|
SandboxClient = class _SandboxClient {
|
|
4266
|
-
|
|
3994
|
+
native;
|
|
4267
3995
|
apiUrl;
|
|
4268
3996
|
apiKey;
|
|
4269
3997
|
organizationId;
|
|
4270
3998
|
projectId;
|
|
4271
3999
|
namespace;
|
|
4272
|
-
local;
|
|
4273
|
-
maxRetries;
|
|
4274
|
-
retryBackoffMs;
|
|
4275
4000
|
requestTimeoutMs;
|
|
4276
4001
|
/** @internal Pass `true` to suppress the deprecation warning when used by `Sandbox.create()` / `Sandbox.connect()`. */
|
|
4277
4002
|
constructor(options, _internal = false) {
|
|
@@ -4285,19 +4010,17 @@ var init_client = __esm({
|
|
|
4285
4010
|
this.organizationId = options?.organizationId;
|
|
4286
4011
|
this.projectId = options?.projectId;
|
|
4287
4012
|
this.namespace = options?.namespace ?? NAMESPACE;
|
|
4288
|
-
this.local = isLocalhost(this.apiUrl);
|
|
4289
|
-
this.maxRetries = options?.maxRetries ?? MAX_RETRIES;
|
|
4290
|
-
this.retryBackoffMs = options?.retryBackoffMs ?? RETRY_BACKOFF_MS;
|
|
4291
4013
|
this.requestTimeoutMs = resolveRequestTimeoutMs(options);
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4014
|
+
const binding = loadNativeSandboxBinding();
|
|
4015
|
+
this.native = new binding.NativeSandboxClient(
|
|
4016
|
+
this.apiUrl,
|
|
4017
|
+
this.apiKey ?? null,
|
|
4018
|
+
this.organizationId ?? null,
|
|
4019
|
+
this.projectId ?? null,
|
|
4020
|
+
this.namespace,
|
|
4021
|
+
null,
|
|
4022
|
+
this.requestTimeoutMs / 1e3
|
|
4023
|
+
);
|
|
4301
4024
|
}
|
|
4302
4025
|
/** Create a client for the TensorLake cloud platform. */
|
|
4303
4026
|
static forCloud(options) {
|
|
@@ -4320,13 +4043,12 @@ var init_client = __esm({
|
|
|
4320
4043
|
});
|
|
4321
4044
|
}
|
|
4322
4045
|
close() {
|
|
4323
|
-
this.http.close();
|
|
4324
4046
|
}
|
|
4325
4047
|
withRequestTimeout(requestTimeout) {
|
|
4326
4048
|
if (requestTimeout == null) {
|
|
4327
4049
|
return this;
|
|
4328
4050
|
}
|
|
4329
|
-
const timeoutMs =
|
|
4051
|
+
const timeoutMs = secondsToMillis3(requestTimeout);
|
|
4330
4052
|
if (timeoutMs === this.requestTimeoutMs) {
|
|
4331
4053
|
return this;
|
|
4332
4054
|
}
|
|
@@ -4337,17 +4059,24 @@ var init_client = __esm({
|
|
|
4337
4059
|
organizationId: this.organizationId,
|
|
4338
4060
|
projectId: this.projectId,
|
|
4339
4061
|
namespace: this.namespace,
|
|
4340
|
-
maxRetries: this.maxRetries,
|
|
4341
|
-
retryBackoffMs: this.retryBackoffMs,
|
|
4342
4062
|
timeoutMs
|
|
4343
4063
|
},
|
|
4344
4064
|
/* _internal */
|
|
4345
4065
|
true
|
|
4346
4066
|
);
|
|
4347
4067
|
}
|
|
4348
|
-
// ---
|
|
4349
|
-
|
|
4350
|
-
|
|
4068
|
+
// --- Native marshalling helpers ---
|
|
4069
|
+
/** Run a native JSON call and reshape it into a `Traced<T>`. */
|
|
4070
|
+
async tracedJson(fn, idField, context) {
|
|
4071
|
+
const { traceId, json } = await callNative(fn, context);
|
|
4072
|
+
return Object.assign(fromSnakeKeys(JSON.parse(json), idField), {
|
|
4073
|
+
traceId
|
|
4074
|
+
});
|
|
4075
|
+
}
|
|
4076
|
+
/** Run a native JSON call and reshape it into a plain `T` (no trace id). */
|
|
4077
|
+
async plainJson(fn, idField, context) {
|
|
4078
|
+
const { json } = await callNative(fn, context);
|
|
4079
|
+
return fromSnakeKeys(JSON.parse(json), idField);
|
|
4351
4080
|
}
|
|
4352
4081
|
// --- Sandbox CRUD ---
|
|
4353
4082
|
/** Create a new sandbox. Returns immediately; the sandbox may still be starting. Use `createAndConnect()` for a blocking, ready-to-use handle. */
|
|
@@ -4373,36 +4102,27 @@ var init_client = __esm({
|
|
|
4373
4102
|
deny_out: options?.denyOut ?? []
|
|
4374
4103
|
};
|
|
4375
4104
|
}
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
{
|
|
4380
|
-
body,
|
|
4381
|
-
retryableStatusCodes: CREATE_SANDBOX_RETRYABLE_STATUS_CODES,
|
|
4382
|
-
allowedErrorStatusCodes: CREATE_SANDBOX_ALLOWED_ERROR_STATUS_CODES
|
|
4383
|
-
}
|
|
4105
|
+
return this.tracedJson(
|
|
4106
|
+
() => this.native.createSandbox(JSON.stringify(body)),
|
|
4107
|
+
"sandboxId"
|
|
4384
4108
|
);
|
|
4385
|
-
const result = fromSnakeKeys(raw, "sandboxId");
|
|
4386
|
-
return Object.assign(result, { traceId: raw.traceId });
|
|
4387
4109
|
}
|
|
4388
4110
|
/** Get current state and metadata for a sandbox by ID. */
|
|
4389
4111
|
async get(sandboxId) {
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4112
|
+
return this.tracedJson(
|
|
4113
|
+
() => this.native.getSandbox(sandboxId),
|
|
4114
|
+
"sandboxId",
|
|
4115
|
+
{ sandboxId, notFoundKind: "sandbox" }
|
|
4393
4116
|
);
|
|
4394
|
-
return Object.assign(fromSnakeKeys(raw, "sandboxId"), { traceId: raw.traceId });
|
|
4395
4117
|
}
|
|
4396
4118
|
/** List all sandboxes in the namespace. */
|
|
4397
4119
|
async list() {
|
|
4398
|
-
const
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
);
|
|
4402
|
-
const sandboxes = (raw.sandboxes ?? []).map(
|
|
4120
|
+
const { traceId, json } = await callNative(() => this.native.listSandboxes());
|
|
4121
|
+
const parsed = JSON.parse(json);
|
|
4122
|
+
const sandboxes = (parsed.sandboxes ?? []).map(
|
|
4403
4123
|
(s) => fromSnakeKeys(s, "sandboxId")
|
|
4404
4124
|
);
|
|
4405
|
-
return Object.assign(sandboxes, { traceId
|
|
4125
|
+
return Object.assign(sandboxes, { traceId });
|
|
4406
4126
|
}
|
|
4407
4127
|
/**
|
|
4408
4128
|
* List archived (terminated) sandboxes in the namespace.
|
|
@@ -4411,37 +4131,30 @@ var init_client = __esm({
|
|
|
4411
4131
|
* archived sandboxes store until the server-configured TTL expires.
|
|
4412
4132
|
*/
|
|
4413
4133
|
async listArchived(options) {
|
|
4414
|
-
const
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
}
|
|
4424
|
-
const suffix = query.length ? `?${query.join("&")}` : "";
|
|
4425
|
-
const raw = await this.http.requestJson("GET", this.path(`archived-sandboxes${suffix}`));
|
|
4426
|
-
const sandboxes = (raw.sandboxes ?? []).map(
|
|
4134
|
+
const { traceId, json } = await callNative(
|
|
4135
|
+
() => this.native.listArchivedSandboxes(
|
|
4136
|
+
options?.limit ?? null,
|
|
4137
|
+
options?.cursor ?? null,
|
|
4138
|
+
options?.direction ?? null
|
|
4139
|
+
)
|
|
4140
|
+
);
|
|
4141
|
+
const parsed = JSON.parse(json);
|
|
4142
|
+
const sandboxes = (parsed.sandboxes ?? []).map(
|
|
4427
4143
|
(s) => fromSnakeKeys(s, "sandboxId")
|
|
4428
4144
|
);
|
|
4429
4145
|
const response = {
|
|
4430
4146
|
sandboxes,
|
|
4431
|
-
prevCursor:
|
|
4432
|
-
nextCursor:
|
|
4147
|
+
prevCursor: parsed.prev_cursor,
|
|
4148
|
+
nextCursor: parsed.next_cursor
|
|
4433
4149
|
};
|
|
4434
|
-
return Object.assign(response, { traceId
|
|
4150
|
+
return Object.assign(response, { traceId });
|
|
4435
4151
|
}
|
|
4436
4152
|
/** Get a single archived sandbox by id. */
|
|
4437
4153
|
async getArchived(sandboxId) {
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
return Object.assign(
|
|
4443
|
-
fromSnakeKeys(raw, "sandboxId"),
|
|
4444
|
-
{ traceId: raw.traceId }
|
|
4154
|
+
return this.tracedJson(
|
|
4155
|
+
() => this.native.getArchivedSandbox(sandboxId),
|
|
4156
|
+
"sandboxId",
|
|
4157
|
+
{ sandboxId, notFoundKind: "sandbox" }
|
|
4445
4158
|
);
|
|
4446
4159
|
}
|
|
4447
4160
|
/** Update sandbox properties such as name, exposed ports, and proxy auth settings. */
|
|
@@ -4457,12 +4170,11 @@ var init_client = __esm({
|
|
|
4457
4170
|
if (Object.keys(body).length === 0) {
|
|
4458
4171
|
throw new SandboxError("At least one sandbox update field must be provided.");
|
|
4459
4172
|
}
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
{
|
|
4173
|
+
return this.tracedJson(
|
|
4174
|
+
() => this.native.updateSandbox(sandboxId, JSON.stringify(body)),
|
|
4175
|
+
"sandboxId",
|
|
4176
|
+
{ sandboxId, notFoundKind: "sandbox" }
|
|
4464
4177
|
);
|
|
4465
|
-
return Object.assign(fromSnakeKeys(raw, "sandboxId"), { traceId: raw.traceId });
|
|
4466
4178
|
}
|
|
4467
4179
|
/** Get the current proxy port settings for a sandbox. */
|
|
4468
4180
|
async getPortAccess(sandboxId) {
|
|
@@ -4500,10 +4212,7 @@ var init_client = __esm({
|
|
|
4500
4212
|
}
|
|
4501
4213
|
/** Terminate and delete a sandbox. */
|
|
4502
4214
|
async delete(sandboxId) {
|
|
4503
|
-
await this.
|
|
4504
|
-
"DELETE",
|
|
4505
|
-
this.path(`sandboxes/${sandboxId}`)
|
|
4506
|
-
);
|
|
4215
|
+
await callNative(() => this.native.deleteSandbox(sandboxId), { sandboxId, notFoundKind: "sandbox" });
|
|
4507
4216
|
}
|
|
4508
4217
|
/**
|
|
4509
4218
|
* Suspend a named sandbox, preserving its state for later resume.
|
|
@@ -4512,18 +4221,9 @@ var init_client = __esm({
|
|
|
4512
4221
|
* cannot. By default blocks until the sandbox is fully `Suspended`. Pass
|
|
4513
4222
|
* `{ wait: false }` to return immediately after the request is sent
|
|
4514
4223
|
* (fire-and-return); the server processes the suspend asynchronously.
|
|
4515
|
-
*
|
|
4516
|
-
* @param sandboxId - ID or name of the sandbox.
|
|
4517
|
-
* @param options.wait - If `true` (default), poll until `Suspended`. Pass `false` to fire-and-return.
|
|
4518
|
-
* @param options.timeout - Max seconds to wait when `wait=true` (default 300).
|
|
4519
|
-
* @param options.pollInterval - Seconds between status polls when `wait=true` (default 1).
|
|
4520
|
-
* @throws {SandboxError} If `wait=true` and the sandbox does not reach `Suspended` within `timeout`.
|
|
4521
4224
|
*/
|
|
4522
4225
|
async suspend(sandboxId, options) {
|
|
4523
|
-
await this.
|
|
4524
|
-
"POST",
|
|
4525
|
-
this.path(`sandboxes/${sandboxId}/suspend`)
|
|
4526
|
-
);
|
|
4226
|
+
await callNative(() => this.native.suspendSandbox(sandboxId), { sandboxId, notFoundKind: "sandbox" });
|
|
4527
4227
|
if (options?.wait === false) return;
|
|
4528
4228
|
const timeout = options?.timeout ?? 300;
|
|
4529
4229
|
const pollInterval = options?.pollInterval ?? 1;
|
|
@@ -4534,7 +4234,7 @@ var init_client = __esm({
|
|
|
4534
4234
|
if (info.status === "terminated" /* TERMINATED */) {
|
|
4535
4235
|
throw new SandboxError(`Sandbox ${sandboxId} terminated while waiting for suspend`);
|
|
4536
4236
|
}
|
|
4537
|
-
await
|
|
4237
|
+
await sleep(pollInterval * 1e3);
|
|
4538
4238
|
}
|
|
4539
4239
|
throw new SandboxError(`Sandbox ${sandboxId} did not suspend within ${timeout}s`);
|
|
4540
4240
|
}
|
|
@@ -4544,18 +4244,9 @@ var init_client = __esm({
|
|
|
4544
4244
|
* By default blocks until the sandbox is `Running` and routable. Pass
|
|
4545
4245
|
* `{ wait: false }` to return immediately after the request is sent
|
|
4546
4246
|
* (fire-and-return); the server processes the resume asynchronously.
|
|
4547
|
-
*
|
|
4548
|
-
* @param sandboxId - ID or name of the sandbox.
|
|
4549
|
-
* @param options.wait - If `true` (default), poll until `Running`. Pass `false` to fire-and-return.
|
|
4550
|
-
* @param options.timeout - Max seconds to wait when `wait=true` (default 300).
|
|
4551
|
-
* @param options.pollInterval - Seconds between status polls when `wait=true` (default 1).
|
|
4552
|
-
* @throws {SandboxError} If `wait=true` and the sandbox does not reach `Running` within `timeout`.
|
|
4553
4247
|
*/
|
|
4554
4248
|
async resume(sandboxId, options) {
|
|
4555
|
-
await this.
|
|
4556
|
-
"POST",
|
|
4557
|
-
this.path(`sandboxes/${sandboxId}/resume`)
|
|
4558
|
-
);
|
|
4249
|
+
await callNative(() => this.native.resumeSandbox(sandboxId), { sandboxId, notFoundKind: "sandbox" });
|
|
4559
4250
|
if (options?.wait === false) return;
|
|
4560
4251
|
const timeout = options?.timeout ?? 300;
|
|
4561
4252
|
const pollInterval = options?.pollInterval ?? 1;
|
|
@@ -4566,22 +4257,17 @@ var init_client = __esm({
|
|
|
4566
4257
|
if (info.status === "terminated" /* TERMINATED */) {
|
|
4567
4258
|
throw new SandboxError(`Sandbox ${sandboxId} terminated while waiting for resume`);
|
|
4568
4259
|
}
|
|
4569
|
-
await
|
|
4260
|
+
await sleep(pollInterval * 1e3);
|
|
4570
4261
|
}
|
|
4571
4262
|
throw new SandboxError(`Sandbox ${sandboxId} did not resume within ${timeout}s`);
|
|
4572
4263
|
}
|
|
4573
4264
|
/** Claim a warm sandbox from a pool, creating one if no warm containers are available. */
|
|
4574
4265
|
async claim(poolId) {
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
{
|
|
4579
|
-
retryableStatusCodes: CREATE_SANDBOX_RETRYABLE_STATUS_CODES,
|
|
4580
|
-
allowedErrorStatusCodes: CREATE_SANDBOX_ALLOWED_ERROR_STATUS_CODES
|
|
4581
|
-
}
|
|
4266
|
+
return this.tracedJson(
|
|
4267
|
+
() => this.native.claimSandbox(poolId),
|
|
4268
|
+
"sandboxId",
|
|
4269
|
+
{ poolId, notFoundKind: "pool" }
|
|
4582
4270
|
);
|
|
4583
|
-
const result = fromSnakeKeys(raw, "sandboxId");
|
|
4584
|
-
return Object.assign(result, { traceId: raw.traceId });
|
|
4585
4271
|
}
|
|
4586
4272
|
/**
|
|
4587
4273
|
* Live-copy a running sandbox.
|
|
@@ -4596,13 +4282,11 @@ var init_client = __esm({
|
|
|
4596
4282
|
throw new SandboxError("times must be a positive integer");
|
|
4597
4283
|
}
|
|
4598
4284
|
const client = this.withRequestTimeout(options?.requestTimeout);
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
{
|
|
4285
|
+
return client.tracedJson(
|
|
4286
|
+
() => client.native.copySandbox(sandboxId, times),
|
|
4287
|
+
"sandboxId",
|
|
4288
|
+
{ sandboxId, notFoundKind: "sandbox" }
|
|
4603
4289
|
);
|
|
4604
|
-
const result = fromSnakeKeys(raw, "sandboxId");
|
|
4605
|
-
return Object.assign(result, { traceId: raw.traceId });
|
|
4606
4290
|
}
|
|
4607
4291
|
// --- Snapshots ---
|
|
4608
4292
|
/**
|
|
@@ -4612,44 +4296,33 @@ var init_client = __esm({
|
|
|
4612
4296
|
* status — the snapshot is created asynchronously. Poll `getSnapshot()` until
|
|
4613
4297
|
* `local_ready`, `completed`, or `failed`, or use `snapshotAndWait()` to
|
|
4614
4298
|
* block automatically.
|
|
4615
|
-
*
|
|
4616
|
-
* @param options.snapshotType - `"filesystem"` for cold-boot snapshots (e.g. image builds).
|
|
4617
|
-
* Omit to use the server default (`filesystem`).
|
|
4618
4299
|
*/
|
|
4619
4300
|
async snapshot(sandboxId, options) {
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
"
|
|
4623
|
-
|
|
4624
|
-
requestOptions
|
|
4301
|
+
return this.plainJson(
|
|
4302
|
+
() => this.native.createSnapshot(sandboxId, options?.snapshotType ?? null),
|
|
4303
|
+
"snapshotId",
|
|
4304
|
+
{ sandboxId, notFoundKind: "sandbox" }
|
|
4625
4305
|
);
|
|
4626
|
-
return fromSnakeKeys(raw, "snapshotId");
|
|
4627
4306
|
}
|
|
4628
4307
|
/** Get current status and metadata for a snapshot by ID. */
|
|
4629
4308
|
async getSnapshot(snapshotId) {
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4309
|
+
return this.tracedJson(
|
|
4310
|
+
() => this.native.getSnapshot(snapshotId),
|
|
4311
|
+
"snapshotId"
|
|
4633
4312
|
);
|
|
4634
|
-
return Object.assign(fromSnakeKeys(raw, "snapshotId"), { traceId: raw.traceId });
|
|
4635
4313
|
}
|
|
4636
4314
|
/** List all snapshots in the namespace. */
|
|
4637
4315
|
async listSnapshots() {
|
|
4638
|
-
const
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
);
|
|
4642
|
-
const snapshots = (raw.snapshots ?? []).map(
|
|
4316
|
+
const { traceId, json } = await callNative(() => this.native.listSnapshots());
|
|
4317
|
+
const parsed = JSON.parse(json);
|
|
4318
|
+
const snapshots = (parsed.snapshots ?? []).map(
|
|
4643
4319
|
(s) => fromSnakeKeys(s, "snapshotId")
|
|
4644
4320
|
);
|
|
4645
|
-
return Object.assign(snapshots, { traceId
|
|
4321
|
+
return Object.assign(snapshots, { traceId });
|
|
4646
4322
|
}
|
|
4647
4323
|
/** Delete a snapshot by ID. */
|
|
4648
4324
|
async deleteSnapshot(snapshotId) {
|
|
4649
|
-
await this.
|
|
4650
|
-
"DELETE",
|
|
4651
|
-
this.path(`snapshots/${snapshotId}`)
|
|
4652
|
-
);
|
|
4325
|
+
await callNative(() => this.native.deleteSnapshot(snapshotId));
|
|
4653
4326
|
}
|
|
4654
4327
|
/**
|
|
4655
4328
|
* Create a snapshot and block until it is locally ready.
|
|
@@ -4657,14 +4330,6 @@ var init_client = __esm({
|
|
|
4657
4330
|
* Combines `snapshot()` with polling `getSnapshot()` until `local_ready`
|
|
4658
4331
|
* or `completed`. Pass `{ waitUntil: "completed" }` when durable
|
|
4659
4332
|
* `snapshotUri` metadata is required.
|
|
4660
|
-
* Prefer `sandbox.checkpoint()` on a `Sandbox` handle for the same behavior
|
|
4661
|
-
* without managing the client separately.
|
|
4662
|
-
*
|
|
4663
|
-
* @param sandboxId - ID of the running sandbox to snapshot.
|
|
4664
|
-
* @param options.timeout - Max seconds to wait (default 300).
|
|
4665
|
-
* @param options.pollInterval - Seconds between status polls (default 1).
|
|
4666
|
-
* @param options.snapshotType - Snapshot type passed through to `snapshot()`.
|
|
4667
|
-
* @throws {SandboxError} If the snapshot fails or `timeout` elapses.
|
|
4668
4333
|
*/
|
|
4669
4334
|
async snapshotAndWait(sandboxId, options) {
|
|
4670
4335
|
const timeout = options?.timeout ?? 300;
|
|
@@ -4682,7 +4347,7 @@ var init_client = __esm({
|
|
|
4682
4347
|
`Snapshot ${result.snapshotId} failed: ${info.error}`
|
|
4683
4348
|
);
|
|
4684
4349
|
}
|
|
4685
|
-
await
|
|
4350
|
+
await sleep(pollInterval * 1e3);
|
|
4686
4351
|
}
|
|
4687
4352
|
throw new SandboxError(
|
|
4688
4353
|
`Snapshot ${result.snapshotId} did not reach ${waitUntil} within ${timeout}s`
|
|
@@ -4703,31 +4368,27 @@ var init_client = __esm({
|
|
|
4703
4368
|
if (options.entrypoint != null) body.entrypoint = options.entrypoint;
|
|
4704
4369
|
if (options.maxContainers != null) body.max_containers = options.maxContainers;
|
|
4705
4370
|
if (options.warmContainers != null) body.warm_containers = options.warmContainers;
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
{ body }
|
|
4371
|
+
return this.plainJson(
|
|
4372
|
+
() => this.native.createPool(JSON.stringify(body)),
|
|
4373
|
+
"poolId"
|
|
4710
4374
|
);
|
|
4711
|
-
return fromSnakeKeys(raw, "poolId");
|
|
4712
4375
|
}
|
|
4713
4376
|
/** Get current state and metadata for a sandbox pool by ID. */
|
|
4714
4377
|
async getPool(poolId) {
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4378
|
+
return this.plainJson(
|
|
4379
|
+
() => this.native.getPool(poolId),
|
|
4380
|
+
"poolId",
|
|
4381
|
+
{ poolId, notFoundKind: "pool" }
|
|
4718
4382
|
);
|
|
4719
|
-
return fromSnakeKeys(raw, "poolId");
|
|
4720
4383
|
}
|
|
4721
4384
|
/** List all sandbox pools in the namespace. */
|
|
4722
4385
|
async listPools() {
|
|
4723
|
-
const
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
);
|
|
4727
|
-
const pools = (raw.pools ?? []).map(
|
|
4386
|
+
const { traceId, json } = await callNative(() => this.native.listPools());
|
|
4387
|
+
const parsed = JSON.parse(json);
|
|
4388
|
+
const pools = (parsed.pools ?? []).map(
|
|
4728
4389
|
(p) => fromSnakeKeys(p, "poolId")
|
|
4729
4390
|
);
|
|
4730
|
-
return Object.assign(pools, { traceId
|
|
4391
|
+
return Object.assign(pools, { traceId });
|
|
4731
4392
|
}
|
|
4732
4393
|
/** Replace the configuration of an existing sandbox pool. */
|
|
4733
4394
|
async updatePool(poolId, options) {
|
|
@@ -4743,19 +4404,15 @@ var init_client = __esm({
|
|
|
4743
4404
|
if (options.entrypoint != null) body.entrypoint = options.entrypoint;
|
|
4744
4405
|
if (options.maxContainers != null) body.max_containers = options.maxContainers;
|
|
4745
4406
|
if (options.warmContainers != null) body.warm_containers = options.warmContainers;
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
{
|
|
4407
|
+
return this.plainJson(
|
|
4408
|
+
() => this.native.updatePool(poolId, JSON.stringify(body)),
|
|
4409
|
+
"poolId",
|
|
4410
|
+
{ poolId, notFoundKind: "pool" }
|
|
4750
4411
|
);
|
|
4751
|
-
return fromSnakeKeys(raw, "poolId");
|
|
4752
4412
|
}
|
|
4753
4413
|
/** Delete a sandbox pool. Fails if the pool has active containers. */
|
|
4754
4414
|
async deletePool(poolId) {
|
|
4755
|
-
await this.
|
|
4756
|
-
"DELETE",
|
|
4757
|
-
this.path(`sandbox-pools/${poolId}`)
|
|
4758
|
-
);
|
|
4415
|
+
await callNative(() => this.native.deletePool(poolId), { poolId, notFoundKind: "pool" });
|
|
4759
4416
|
}
|
|
4760
4417
|
// --- Connect ---
|
|
4761
4418
|
/** Return a `Sandbox` handle for an existing running sandbox without verifying it exists. */
|
|
@@ -4769,7 +4426,8 @@ var init_client = __esm({
|
|
|
4769
4426
|
projectId: this.projectId,
|
|
4770
4427
|
routingHint,
|
|
4771
4428
|
resolveProxyInfo: proxyUrl == null ? async (currentIdentifier) => this.get(currentIdentifier) : void 0,
|
|
4772
|
-
requestTimeout
|
|
4429
|
+
requestTimeout,
|
|
4430
|
+
nativeClient: this.native
|
|
4773
4431
|
});
|
|
4774
4432
|
}
|
|
4775
4433
|
/**
|
|
@@ -4777,10 +4435,6 @@ var init_client = __esm({
|
|
|
4777
4435
|
*
|
|
4778
4436
|
* Blocks until the sandbox is ready or `requestTimeout` elapses. The returned
|
|
4779
4437
|
* `Sandbox` auto-terminates when `terminate()` is called.
|
|
4780
|
-
*
|
|
4781
|
-
* @param options.requestTimeout - Max seconds to wait for `Running` status (default: client requestTimeout).
|
|
4782
|
-
* @param options.startupTimeout - Deprecated alias for `requestTimeout`.
|
|
4783
|
-
* @throws {SandboxError} If the sandbox terminates during startup or the timeout elapses.
|
|
4784
4438
|
*/
|
|
4785
4439
|
async createAndConnect(options) {
|
|
4786
4440
|
if (options?.poolId != null && options?.cloudInit != null) {
|
|
@@ -4842,7 +4496,7 @@ var init_client = __esm({
|
|
|
4842
4496
|
`Sandbox ${result.sandboxId} did not start within ${requestTimeout}s`
|
|
4843
4497
|
);
|
|
4844
4498
|
}
|
|
4845
|
-
const deadline = Date.now() +
|
|
4499
|
+
const deadline = Date.now() + secondsToMillis3(requestTimeout);
|
|
4846
4500
|
while (Date.now() < deadline) {
|
|
4847
4501
|
const pollStart = nowMs();
|
|
4848
4502
|
const info = await requestClient.get(result.sandboxId);
|
|
@@ -4862,7 +4516,7 @@ var init_client = __esm({
|
|
|
4862
4516
|
})
|
|
4863
4517
|
);
|
|
4864
4518
|
}
|
|
4865
|
-
await
|
|
4519
|
+
await sleep(500);
|
|
4866
4520
|
}
|
|
4867
4521
|
try {
|
|
4868
4522
|
await requestClient.delete(result.sandboxId);
|
|
@@ -5008,17 +4662,17 @@ __export(sandbox_image_exports, {
|
|
|
5008
4662
|
createSandboxImage: () => createSandboxImage,
|
|
5009
4663
|
runCreateSandboxImageCli: () => runCreateSandboxImageCli
|
|
5010
4664
|
});
|
|
5011
|
-
function
|
|
4665
|
+
function resolveRequire2() {
|
|
5012
4666
|
if (typeof module !== "undefined" && module.exports != null && typeof require !== "undefined") {
|
|
5013
4667
|
return require;
|
|
5014
4668
|
}
|
|
5015
|
-
return (0,
|
|
4669
|
+
return (0, import_node_module2.createRequire)(import_meta2.url);
|
|
5016
4670
|
}
|
|
5017
4671
|
function loadNativeBinding() {
|
|
5018
4672
|
if (cachedNativeBinding) return cachedNativeBinding;
|
|
5019
4673
|
if (cachedNativeBindingError) throw cachedNativeBindingError;
|
|
5020
4674
|
try {
|
|
5021
|
-
const { loadNative } =
|
|
4675
|
+
const { loadNative } = resolveRequire2()("../lib/runtime.cjs");
|
|
5022
4676
|
cachedNativeBinding = loadNative();
|
|
5023
4677
|
return cachedNativeBinding;
|
|
5024
4678
|
} catch (error) {
|
|
@@ -5216,16 +4870,16 @@ async function runCreateSandboxImageCli(argv = process.argv.slice(2)) {
|
|
|
5216
4870
|
{ emit: ndjsonStdoutEmit }
|
|
5217
4871
|
);
|
|
5218
4872
|
}
|
|
5219
|
-
var
|
|
4873
|
+
var import_node_module2, import_node_path, import_node_fs, import_node_util, import_meta2, cachedNativeBinding, cachedNativeBindingError, DEFAULT_IMAGE_NAME2;
|
|
5220
4874
|
var init_sandbox_image = __esm({
|
|
5221
4875
|
"src/sandbox-image.ts"() {
|
|
5222
4876
|
"use strict";
|
|
5223
|
-
|
|
4877
|
+
import_node_module2 = require("module");
|
|
5224
4878
|
import_node_path = __toESM(require("path"), 1);
|
|
5225
4879
|
import_node_fs = require("fs");
|
|
5226
4880
|
import_node_util = require("util");
|
|
5227
4881
|
init_image();
|
|
5228
|
-
|
|
4882
|
+
import_meta2 = {};
|
|
5229
4883
|
DEFAULT_IMAGE_NAME2 = "default";
|
|
5230
4884
|
}
|
|
5231
4885
|
});
|
|
@@ -5271,9 +4925,365 @@ init_tunnel();
|
|
|
5271
4925
|
|
|
5272
4926
|
// src/cloud-client.ts
|
|
5273
4927
|
init_defaults();
|
|
5274
|
-
|
|
4928
|
+
|
|
4929
|
+
// src/http.ts
|
|
4930
|
+
var import_undici = require("undici");
|
|
4931
|
+
init_defaults();
|
|
4932
|
+
init_errors();
|
|
4933
|
+
init_sdk_timings();
|
|
4934
|
+
var REQUEST_TIMEOUT_HEADER = "X-Tensorlake-Request-Timeout-Ms";
|
|
4935
|
+
(0, import_undici.setGlobalDispatcher)(
|
|
4936
|
+
new import_undici.Agent({
|
|
4937
|
+
keepAliveTimeout: 6e4,
|
|
4938
|
+
allowH2: true
|
|
4939
|
+
})
|
|
4940
|
+
);
|
|
4941
|
+
function withTraceId(value, traceId) {
|
|
4942
|
+
if (value == null) {
|
|
4943
|
+
return { traceId };
|
|
4944
|
+
}
|
|
4945
|
+
return Object.assign(value, { traceId });
|
|
4946
|
+
}
|
|
4947
|
+
var HttpClient = class _HttpClient {
|
|
4948
|
+
baseUrl;
|
|
4949
|
+
headers;
|
|
4950
|
+
maxRetries;
|
|
4951
|
+
retryBackoffMs;
|
|
4952
|
+
timeoutMs;
|
|
4953
|
+
abortController = null;
|
|
4954
|
+
constructor(options) {
|
|
4955
|
+
const url = options.baseUrl;
|
|
4956
|
+
this.baseUrl = url.endsWith("/") ? url.slice(0, -1) : url;
|
|
4957
|
+
this.maxRetries = options.maxRetries ?? MAX_RETRIES;
|
|
4958
|
+
this.retryBackoffMs = options.retryBackoffMs ?? RETRY_BACKOFF_MS;
|
|
4959
|
+
this.timeoutMs = options.timeoutMs === void 0 ? DEFAULT_HTTP_TIMEOUT_MS : options.timeoutMs;
|
|
4960
|
+
this.headers = {
|
|
4961
|
+
"User-Agent": `tensorlake-typescript-sdk/${SDK_VERSION}`
|
|
4962
|
+
};
|
|
4963
|
+
if (this.timeoutMs != null) {
|
|
4964
|
+
this.headers[REQUEST_TIMEOUT_HEADER] = String(this.timeoutMs);
|
|
4965
|
+
}
|
|
4966
|
+
if (options.apiKey) {
|
|
4967
|
+
this.headers["Authorization"] = `Bearer ${options.apiKey}`;
|
|
4968
|
+
}
|
|
4969
|
+
if (options.organizationId) {
|
|
4970
|
+
this.headers["X-Forwarded-Organization-Id"] = options.organizationId;
|
|
4971
|
+
}
|
|
4972
|
+
if (options.projectId) {
|
|
4973
|
+
this.headers["X-Forwarded-Project-Id"] = options.projectId;
|
|
4974
|
+
}
|
|
4975
|
+
if (options.hostHeader) {
|
|
4976
|
+
this.headers["Host"] = options.hostHeader;
|
|
4977
|
+
}
|
|
4978
|
+
if (options.sandboxIdHeader) {
|
|
4979
|
+
this.headers["X-Tensorlake-Sandbox-Id"] = options.sandboxIdHeader;
|
|
4980
|
+
}
|
|
4981
|
+
if (options.routingHint) {
|
|
4982
|
+
this.headers["X-Tensorlake-Route-Hint"] = options.routingHint;
|
|
4983
|
+
}
|
|
4984
|
+
}
|
|
4985
|
+
close() {
|
|
4986
|
+
this.abortController?.abort();
|
|
4987
|
+
this.abortController = null;
|
|
4988
|
+
}
|
|
4989
|
+
/** Make a JSON request, returning the parsed response body. */
|
|
4990
|
+
async requestJson(method, path2, options) {
|
|
4991
|
+
const response = await this.requestResponse(method, path2, {
|
|
4992
|
+
json: options?.body,
|
|
4993
|
+
headers: options?.headers,
|
|
4994
|
+
signal: options?.signal,
|
|
4995
|
+
retryableStatusCodes: options?.retryableStatusCodes,
|
|
4996
|
+
allowedErrorStatusCodes: options?.allowedErrorStatusCodes,
|
|
4997
|
+
allowHttpErrors: options?.allowHttpErrors
|
|
4998
|
+
});
|
|
4999
|
+
const text = await response.text();
|
|
5000
|
+
const data = text ? JSON.parse(text) : void 0;
|
|
5001
|
+
return withTraceId(data, response.traceId);
|
|
5002
|
+
}
|
|
5003
|
+
/** Make a request returning raw bytes. */
|
|
5004
|
+
async requestBytes(method, path2, options) {
|
|
5005
|
+
const headers = { ...options?.headers ?? {} };
|
|
5006
|
+
if (options?.contentType) {
|
|
5007
|
+
headers["Content-Type"] = options.contentType;
|
|
5008
|
+
}
|
|
5009
|
+
const response = await this.requestResponse(method, path2, {
|
|
5010
|
+
body: options?.body,
|
|
5011
|
+
headers,
|
|
5012
|
+
signal: options?.signal
|
|
5013
|
+
});
|
|
5014
|
+
const buffer = await response.arrayBuffer();
|
|
5015
|
+
return withTraceId(new Uint8Array(buffer), response.traceId);
|
|
5016
|
+
}
|
|
5017
|
+
/** Make a request and return the response body as an SSE stream. */
|
|
5018
|
+
async requestStream(method, path2, options) {
|
|
5019
|
+
const response = await this.requestResponse(method, path2, {
|
|
5020
|
+
json: options?.json,
|
|
5021
|
+
headers: { Accept: "text/event-stream" },
|
|
5022
|
+
signal: options?.signal
|
|
5023
|
+
});
|
|
5024
|
+
if (!response.body) {
|
|
5025
|
+
throw new RemoteAPIError(
|
|
5026
|
+
response.status,
|
|
5027
|
+
"No response body for SSE stream"
|
|
5028
|
+
);
|
|
5029
|
+
}
|
|
5030
|
+
return withTraceId(response.body, response.traceId);
|
|
5031
|
+
}
|
|
5032
|
+
/** Make a request and return the raw Response. */
|
|
5033
|
+
async requestResponse(method, path2, options) {
|
|
5034
|
+
const headers = {
|
|
5035
|
+
...this.headers,
|
|
5036
|
+
...options?.headers ?? {}
|
|
5037
|
+
};
|
|
5038
|
+
const hasJsonBody = options?.json !== void 0;
|
|
5039
|
+
if (hasJsonBody && !hasHeader(headers, "Content-Type")) {
|
|
5040
|
+
headers["Content-Type"] = "application/json";
|
|
5041
|
+
}
|
|
5042
|
+
const body = hasJsonBody ? JSON.stringify(options?.json) : normalizeRequestBody(options?.body);
|
|
5043
|
+
const { response, traceId } = await this.doFetch(
|
|
5044
|
+
method,
|
|
5045
|
+
path2,
|
|
5046
|
+
body,
|
|
5047
|
+
headers,
|
|
5048
|
+
options?.signal,
|
|
5049
|
+
options?.allowHttpErrors ?? false,
|
|
5050
|
+
options?.retryableStatusCodes ?? RETRYABLE_STATUS_CODES,
|
|
5051
|
+
options?.allowedErrorStatusCodes ?? /* @__PURE__ */ new Set()
|
|
5052
|
+
);
|
|
5053
|
+
return withTraceId(response, traceId);
|
|
5054
|
+
}
|
|
5055
|
+
static makeTraceparent() {
|
|
5056
|
+
const randomHex = (bytes) => Array.from(crypto.getRandomValues(new Uint8Array(bytes))).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
5057
|
+
const traceId = randomHex(16);
|
|
5058
|
+
const spanId = randomHex(8);
|
|
5059
|
+
return { traceparent: `00-${traceId}-${spanId}-01`, traceId };
|
|
5060
|
+
}
|
|
5061
|
+
async doFetch(method, path2, body, headers, signal, allowHttpErrors = false, retryableStatusCodes = RETRYABLE_STATUS_CODES, allowedErrorStatusCodes = /* @__PURE__ */ new Set()) {
|
|
5062
|
+
const url = `${this.baseUrl}${path2}`;
|
|
5063
|
+
const { traceparent, traceId } = _HttpClient.makeTraceparent();
|
|
5064
|
+
headers["traceparent"] = traceparent;
|
|
5065
|
+
let lastError;
|
|
5066
|
+
const operationStart = nowMs();
|
|
5067
|
+
const timingPath = sdkTimingPayloadsEnabled() ? path2 : stripPathPayload(path2);
|
|
5068
|
+
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
5069
|
+
if (attempt > 0) {
|
|
5070
|
+
const delay = this.retryBackoffMs * Math.pow(2, attempt - 1);
|
|
5071
|
+
logSdkTimingEvent("http.request", "retry_sleep_start", {
|
|
5072
|
+
method,
|
|
5073
|
+
path: timingPath,
|
|
5074
|
+
attempt,
|
|
5075
|
+
delay_ms: delay,
|
|
5076
|
+
server_trace_id: traceId
|
|
5077
|
+
});
|
|
5078
|
+
await sleep2(delay);
|
|
5079
|
+
}
|
|
5080
|
+
this.abortController = new AbortController();
|
|
5081
|
+
let timedOut = false;
|
|
5082
|
+
const timeoutId = this.timeoutMs == null ? null : setTimeout(() => {
|
|
5083
|
+
timedOut = true;
|
|
5084
|
+
this.abortController?.abort();
|
|
5085
|
+
}, this.timeoutMs);
|
|
5086
|
+
const combinedSignal = signal ? anySignal([signal, this.abortController.signal]) : this.abortController.signal;
|
|
5087
|
+
const attemptStart = nowMs();
|
|
5088
|
+
try {
|
|
5089
|
+
const response = await (0, import_undici.fetch)(url, {
|
|
5090
|
+
method,
|
|
5091
|
+
headers,
|
|
5092
|
+
body,
|
|
5093
|
+
signal: combinedSignal
|
|
5094
|
+
});
|
|
5095
|
+
if (timeoutId != null) clearTimeout(timeoutId);
|
|
5096
|
+
logSdkTiming("http.request", "headers", attemptStart, {
|
|
5097
|
+
method,
|
|
5098
|
+
path: timingPath,
|
|
5099
|
+
status: response.status,
|
|
5100
|
+
attempt,
|
|
5101
|
+
server_trace_id: traceId
|
|
5102
|
+
});
|
|
5103
|
+
if (response.ok) {
|
|
5104
|
+
logSdkTiming("http.request", "complete", operationStart, {
|
|
5105
|
+
method,
|
|
5106
|
+
path: timingPath,
|
|
5107
|
+
status: response.status,
|
|
5108
|
+
attempts: attempt + 1,
|
|
5109
|
+
server_trace_id: traceId
|
|
5110
|
+
});
|
|
5111
|
+
return { response, traceId };
|
|
5112
|
+
}
|
|
5113
|
+
if (retryableStatusCodes.has(response.status) && attempt < this.maxRetries) {
|
|
5114
|
+
lastError = new RemoteAPIError(
|
|
5115
|
+
response.status,
|
|
5116
|
+
await response.text().catch(() => "")
|
|
5117
|
+
);
|
|
5118
|
+
logSdkTimingEvent("http.request", "retryable_status", {
|
|
5119
|
+
method,
|
|
5120
|
+
path: timingPath,
|
|
5121
|
+
status: response.status,
|
|
5122
|
+
attempt,
|
|
5123
|
+
server_trace_id: traceId
|
|
5124
|
+
});
|
|
5125
|
+
continue;
|
|
5126
|
+
}
|
|
5127
|
+
if (allowHttpErrors || allowedErrorStatusCodes.has(response.status)) {
|
|
5128
|
+
logSdkTiming("http.request", "complete", operationStart, {
|
|
5129
|
+
method,
|
|
5130
|
+
path: timingPath,
|
|
5131
|
+
status: response.status,
|
|
5132
|
+
attempts: attempt + 1,
|
|
5133
|
+
server_trace_id: traceId
|
|
5134
|
+
});
|
|
5135
|
+
return { response, traceId };
|
|
5136
|
+
}
|
|
5137
|
+
const errorBody = await response.text().catch(() => "");
|
|
5138
|
+
throwMappedError(response.status, errorBody, path2);
|
|
5139
|
+
} catch (err) {
|
|
5140
|
+
if (timeoutId != null) clearTimeout(timeoutId);
|
|
5141
|
+
if (err instanceof RemoteAPIError || err instanceof SandboxNotFoundError || err instanceof PoolNotFoundError || err instanceof PoolInUseError) {
|
|
5142
|
+
throw err;
|
|
5143
|
+
}
|
|
5144
|
+
if (signal?.aborted && !timedOut) {
|
|
5145
|
+
throw new SandboxConnectionError("request aborted by caller", {
|
|
5146
|
+
cause: err
|
|
5147
|
+
});
|
|
5148
|
+
}
|
|
5149
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
5150
|
+
logSdkTiming("http.request", "error", attemptStart, {
|
|
5151
|
+
method,
|
|
5152
|
+
path: timingPath,
|
|
5153
|
+
attempt,
|
|
5154
|
+
server_trace_id: traceId,
|
|
5155
|
+
error: timedOut ? `request timed out after ${this.timeoutMs}ms` : describeError(err)
|
|
5156
|
+
});
|
|
5157
|
+
if (attempt >= this.maxRetries) {
|
|
5158
|
+
const detail = timedOut ? `request timed out after ${this.timeoutMs}ms` : describeError(err);
|
|
5159
|
+
throw new SandboxConnectionError(detail, { cause: err });
|
|
5160
|
+
}
|
|
5161
|
+
}
|
|
5162
|
+
}
|
|
5163
|
+
throw new SandboxConnectionError(
|
|
5164
|
+
lastError ? describeError(lastError) : "request failed",
|
|
5165
|
+
{ cause: lastError }
|
|
5166
|
+
);
|
|
5167
|
+
}
|
|
5168
|
+
};
|
|
5169
|
+
function hasHeader(headers, name) {
|
|
5170
|
+
const lowered = name.toLowerCase();
|
|
5171
|
+
return Object.keys(headers).some((key) => key.toLowerCase() === lowered);
|
|
5172
|
+
}
|
|
5173
|
+
function normalizeRequestBody(body) {
|
|
5174
|
+
if (body == null) {
|
|
5175
|
+
return void 0;
|
|
5176
|
+
}
|
|
5177
|
+
if (body instanceof Uint8Array) {
|
|
5178
|
+
return Uint8Array.from(body).buffer;
|
|
5179
|
+
}
|
|
5180
|
+
return body;
|
|
5181
|
+
}
|
|
5182
|
+
function stripPathPayload(path2) {
|
|
5183
|
+
const queryStart = path2.search(/[?#]/);
|
|
5184
|
+
return queryStart === -1 ? path2 : path2.slice(0, queryStart);
|
|
5185
|
+
}
|
|
5186
|
+
function throwMappedError(status, body, path2) {
|
|
5187
|
+
let message = body;
|
|
5188
|
+
try {
|
|
5189
|
+
const parsed = JSON.parse(body);
|
|
5190
|
+
if (parsed.message) message = parsed.message;
|
|
5191
|
+
else if (parsed.error) message = parsed.error;
|
|
5192
|
+
} catch {
|
|
5193
|
+
}
|
|
5194
|
+
if (status === 404) {
|
|
5195
|
+
if (path2.includes("sandbox-pools") || path2.includes("pools")) {
|
|
5196
|
+
const match = path2.match(/sandbox-pools\/([^/]+)/);
|
|
5197
|
+
if (match) throw new PoolNotFoundError(match[1]);
|
|
5198
|
+
}
|
|
5199
|
+
if (path2.includes("sandboxes")) {
|
|
5200
|
+
const match = path2.match(/sandboxes\/([^/]+)/);
|
|
5201
|
+
if (match) throw new SandboxNotFoundError(match[1]);
|
|
5202
|
+
}
|
|
5203
|
+
throw new RemoteAPIError(404, message);
|
|
5204
|
+
}
|
|
5205
|
+
if (status === 409) {
|
|
5206
|
+
if (path2.includes("sandbox-pools") || path2.includes("pools")) {
|
|
5207
|
+
const match = path2.match(/sandbox-pools\/([^/]+)/);
|
|
5208
|
+
if (match) throw new PoolInUseError(match[1], message);
|
|
5209
|
+
}
|
|
5210
|
+
}
|
|
5211
|
+
throw new RemoteAPIError(status, message);
|
|
5212
|
+
}
|
|
5213
|
+
function anySignal(signals) {
|
|
5214
|
+
const controller = new AbortController();
|
|
5215
|
+
for (const signal of signals) {
|
|
5216
|
+
if (signal.aborted) {
|
|
5217
|
+
controller.abort(signal.reason);
|
|
5218
|
+
return controller.signal;
|
|
5219
|
+
}
|
|
5220
|
+
signal.addEventListener("abort", () => controller.abort(signal.reason), {
|
|
5221
|
+
once: true
|
|
5222
|
+
});
|
|
5223
|
+
}
|
|
5224
|
+
return controller.signal;
|
|
5225
|
+
}
|
|
5226
|
+
function sleep2(ms) {
|
|
5227
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
5228
|
+
}
|
|
5229
|
+
|
|
5230
|
+
// src/cloud-client.ts
|
|
5275
5231
|
init_models();
|
|
5276
|
-
|
|
5232
|
+
|
|
5233
|
+
// src/sse.ts
|
|
5234
|
+
async function* parseSSEMessages(stream, signal) {
|
|
5235
|
+
const reader = stream.getReader();
|
|
5236
|
+
const decoder = new TextDecoder();
|
|
5237
|
+
let buffer = "";
|
|
5238
|
+
try {
|
|
5239
|
+
while (true) {
|
|
5240
|
+
if (signal?.aborted) break;
|
|
5241
|
+
const { done, value } = await reader.read();
|
|
5242
|
+
if (done) break;
|
|
5243
|
+
buffer += decoder.decode(value, { stream: true });
|
|
5244
|
+
const parts = buffer.split(/\r?\n\r?\n/);
|
|
5245
|
+
buffer = parts.pop() ?? "";
|
|
5246
|
+
for (const part of parts) {
|
|
5247
|
+
const lines = part.split(/\r?\n/);
|
|
5248
|
+
const dataLines = [];
|
|
5249
|
+
let event;
|
|
5250
|
+
let id;
|
|
5251
|
+
for (const line of lines) {
|
|
5252
|
+
if (!line || line.startsWith(":")) continue;
|
|
5253
|
+
const separator = line.indexOf(":");
|
|
5254
|
+
const field = separator === -1 ? line : line.slice(0, separator);
|
|
5255
|
+
let value2 = separator === -1 ? "" : line.slice(separator + 1);
|
|
5256
|
+
if (value2.startsWith(" ")) {
|
|
5257
|
+
value2 = value2.slice(1);
|
|
5258
|
+
}
|
|
5259
|
+
if (field === "data") {
|
|
5260
|
+
dataLines.push(value2);
|
|
5261
|
+
} else if (field === "event") {
|
|
5262
|
+
event = value2;
|
|
5263
|
+
} else if (field === "id") {
|
|
5264
|
+
id = value2;
|
|
5265
|
+
}
|
|
5266
|
+
}
|
|
5267
|
+
if (dataLines.length > 0 || event || id) {
|
|
5268
|
+
yield { data: dataLines.join("\n"), event, id };
|
|
5269
|
+
}
|
|
5270
|
+
}
|
|
5271
|
+
}
|
|
5272
|
+
} finally {
|
|
5273
|
+
reader.releaseLock();
|
|
5274
|
+
}
|
|
5275
|
+
}
|
|
5276
|
+
async function* parseSSEStream(stream, signal) {
|
|
5277
|
+
for await (const message of parseSSEMessages(stream, signal)) {
|
|
5278
|
+
if (!message.data) continue;
|
|
5279
|
+
try {
|
|
5280
|
+
yield JSON.parse(message.data);
|
|
5281
|
+
} catch {
|
|
5282
|
+
}
|
|
5283
|
+
}
|
|
5284
|
+
}
|
|
5285
|
+
|
|
5286
|
+
// src/cloud-client.ts
|
|
5277
5287
|
var CloudClient = class _CloudClient {
|
|
5278
5288
|
http;
|
|
5279
5289
|
organizationId;
|