tensorlake 0.5.34 → 0.5.36
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 +222 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +222 -4
- 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
|
@@ -97,6 +97,11 @@ interface CreateSandboxOptions {
|
|
|
97
97
|
snapshotId?: string;
|
|
98
98
|
/** Optional name for the sandbox. Named sandboxes support suspend/resume. When absent the sandbox is ephemeral. */
|
|
99
99
|
name?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Local cloud-init file path or HTTP(S) URL for the sandbox. Supported for
|
|
102
|
+
* fresh sandboxes and filesystem-only snapshot restores.
|
|
103
|
+
*/
|
|
104
|
+
cloudInit?: string | URL;
|
|
100
105
|
}
|
|
101
106
|
interface UpdateSandboxOptions {
|
|
102
107
|
/** New name for the sandbox. Naming an ephemeral sandbox enables suspend/resume. */
|
package/dist/index.d.ts
CHANGED
|
@@ -97,6 +97,11 @@ interface CreateSandboxOptions {
|
|
|
97
97
|
snapshotId?: string;
|
|
98
98
|
/** Optional name for the sandbox. Named sandboxes support suspend/resume. When absent the sandbox is ephemeral. */
|
|
99
99
|
name?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Local cloud-init file path or HTTP(S) URL for the sandbox. Supported for
|
|
102
|
+
* fresh sandboxes and filesystem-only snapshot restores.
|
|
103
|
+
*/
|
|
104
|
+
cloudInit?: string | URL;
|
|
100
105
|
}
|
|
101
106
|
interface UpdateSandboxOptions {
|
|
102
107
|
/** New name for the sandbox. Naming an ephemeral sandbox enables suspend/resume. */
|
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.36";
|
|
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";
|
|
@@ -139,6 +139,56 @@ var init_errors = __esm({
|
|
|
139
139
|
}
|
|
140
140
|
});
|
|
141
141
|
|
|
142
|
+
// src/sdk-timings.ts
|
|
143
|
+
function sdkTimingsEnabled() {
|
|
144
|
+
const value = process.env[SDK_TIMINGS_ENV_VAR];
|
|
145
|
+
return value === "1" || value === "true" || value === "yes";
|
|
146
|
+
}
|
|
147
|
+
function sdkTimingPayloadsEnabled() {
|
|
148
|
+
const value = process.env[SDK_TIMING_PAYLOADS_ENV_VAR];
|
|
149
|
+
return value === "1" || value === "true" || value === "yes";
|
|
150
|
+
}
|
|
151
|
+
function nowMs() {
|
|
152
|
+
return performance.now();
|
|
153
|
+
}
|
|
154
|
+
function logSdkTiming(op, phase, startedAt, fields = {}) {
|
|
155
|
+
if (!sdkTimingsEnabled()) return;
|
|
156
|
+
logSdkTimingEvent(op, phase, {
|
|
157
|
+
...fields,
|
|
158
|
+
duration_ms: Math.round((nowMs() - startedAt) * 100) / 100
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
function logSdkTimingEvent(op, phase, fields = {}) {
|
|
162
|
+
if (!sdkTimingsEnabled()) return;
|
|
163
|
+
const parts = [
|
|
164
|
+
"[tensorlake:sdk-timing]",
|
|
165
|
+
`op=${op}`,
|
|
166
|
+
`phase=${phase}`
|
|
167
|
+
];
|
|
168
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
169
|
+
if (value == null) continue;
|
|
170
|
+
parts.push(`${key}=${formatSdkTimingValue(value)}`);
|
|
171
|
+
}
|
|
172
|
+
console.error(parts.join(" "));
|
|
173
|
+
}
|
|
174
|
+
function formatSdkTimingValue(value) {
|
|
175
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
176
|
+
return String(value);
|
|
177
|
+
}
|
|
178
|
+
if (/^[A-Za-z0-9_./:@-]+$/.test(value)) {
|
|
179
|
+
return value;
|
|
180
|
+
}
|
|
181
|
+
return JSON.stringify(value);
|
|
182
|
+
}
|
|
183
|
+
var SDK_TIMINGS_ENV_VAR, SDK_TIMING_PAYLOADS_ENV_VAR;
|
|
184
|
+
var init_sdk_timings = __esm({
|
|
185
|
+
"src/sdk-timings.ts"() {
|
|
186
|
+
"use strict";
|
|
187
|
+
SDK_TIMINGS_ENV_VAR = "TENSORLAKE_SDK_TIMINGS";
|
|
188
|
+
SDK_TIMING_PAYLOADS_ENV_VAR = "TENSORLAKE_SDK_TIMING_PAYLOADS";
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
|
|
142
192
|
// src/http.ts
|
|
143
193
|
import {
|
|
144
194
|
Agent,
|
|
@@ -164,6 +214,10 @@ function normalizeRequestBody(body) {
|
|
|
164
214
|
}
|
|
165
215
|
return body;
|
|
166
216
|
}
|
|
217
|
+
function stripPathPayload(path2) {
|
|
218
|
+
const queryStart = path2.search(/[?#]/);
|
|
219
|
+
return queryStart === -1 ? path2 : path2.slice(0, queryStart);
|
|
220
|
+
}
|
|
167
221
|
function throwMappedError(status, body, path2) {
|
|
168
222
|
let message = body;
|
|
169
223
|
try {
|
|
@@ -213,6 +267,7 @@ var init_http = __esm({
|
|
|
213
267
|
"use strict";
|
|
214
268
|
init_defaults();
|
|
215
269
|
init_errors();
|
|
270
|
+
init_sdk_timings();
|
|
216
271
|
REQUEST_TIMEOUT_HEADER = "X-Tensorlake-Request-Timeout-Ms";
|
|
217
272
|
setGlobalDispatcher(
|
|
218
273
|
new Agent({
|
|
@@ -339,9 +394,18 @@ var init_http = __esm({
|
|
|
339
394
|
const { traceparent, traceId } = _HttpClient.makeTraceparent();
|
|
340
395
|
headers["traceparent"] = traceparent;
|
|
341
396
|
let lastError;
|
|
397
|
+
const operationStart = nowMs();
|
|
398
|
+
const timingPath = sdkTimingPayloadsEnabled() ? path2 : stripPathPayload(path2);
|
|
342
399
|
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
343
400
|
if (attempt > 0) {
|
|
344
401
|
const delay = this.retryBackoffMs * Math.pow(2, attempt - 1);
|
|
402
|
+
logSdkTimingEvent("http.request", "retry_sleep_start", {
|
|
403
|
+
method,
|
|
404
|
+
path: timingPath,
|
|
405
|
+
attempt,
|
|
406
|
+
delay_ms: delay,
|
|
407
|
+
server_trace_id: traceId
|
|
408
|
+
});
|
|
345
409
|
await sleep(delay);
|
|
346
410
|
}
|
|
347
411
|
this.abortController = new AbortController();
|
|
@@ -351,6 +415,7 @@ var init_http = __esm({
|
|
|
351
415
|
this.abortController?.abort();
|
|
352
416
|
}, this.timeoutMs);
|
|
353
417
|
const combinedSignal = signal ? anySignal([signal, this.abortController.signal]) : this.abortController.signal;
|
|
418
|
+
const attemptStart = nowMs();
|
|
354
419
|
try {
|
|
355
420
|
const response = await undiciFetch(url, {
|
|
356
421
|
method,
|
|
@@ -359,15 +424,45 @@ var init_http = __esm({
|
|
|
359
424
|
signal: combinedSignal
|
|
360
425
|
});
|
|
361
426
|
if (timeoutId != null) clearTimeout(timeoutId);
|
|
362
|
-
|
|
427
|
+
logSdkTiming("http.request", "headers", attemptStart, {
|
|
428
|
+
method,
|
|
429
|
+
path: timingPath,
|
|
430
|
+
status: response.status,
|
|
431
|
+
attempt,
|
|
432
|
+
server_trace_id: traceId
|
|
433
|
+
});
|
|
434
|
+
if (response.ok) {
|
|
435
|
+
logSdkTiming("http.request", "complete", operationStart, {
|
|
436
|
+
method,
|
|
437
|
+
path: timingPath,
|
|
438
|
+
status: response.status,
|
|
439
|
+
attempts: attempt + 1,
|
|
440
|
+
server_trace_id: traceId
|
|
441
|
+
});
|
|
442
|
+
return { response, traceId };
|
|
443
|
+
}
|
|
363
444
|
if (retryableStatusCodes.has(response.status) && attempt < this.maxRetries) {
|
|
364
445
|
lastError = new RemoteAPIError(
|
|
365
446
|
response.status,
|
|
366
447
|
await response.text().catch(() => "")
|
|
367
448
|
);
|
|
449
|
+
logSdkTimingEvent("http.request", "retryable_status", {
|
|
450
|
+
method,
|
|
451
|
+
path: timingPath,
|
|
452
|
+
status: response.status,
|
|
453
|
+
attempt,
|
|
454
|
+
server_trace_id: traceId
|
|
455
|
+
});
|
|
368
456
|
continue;
|
|
369
457
|
}
|
|
370
458
|
if (allowHttpErrors || allowedErrorStatusCodes.has(response.status)) {
|
|
459
|
+
logSdkTiming("http.request", "complete", operationStart, {
|
|
460
|
+
method,
|
|
461
|
+
path: timingPath,
|
|
462
|
+
status: response.status,
|
|
463
|
+
attempts: attempt + 1,
|
|
464
|
+
server_trace_id: traceId
|
|
465
|
+
});
|
|
371
466
|
return { response, traceId };
|
|
372
467
|
}
|
|
373
468
|
const errorBody = await response.text().catch(() => "");
|
|
@@ -383,6 +478,13 @@ var init_http = __esm({
|
|
|
383
478
|
});
|
|
384
479
|
}
|
|
385
480
|
lastError = err instanceof Error ? err : new Error(String(err));
|
|
481
|
+
logSdkTiming("http.request", "error", attemptStart, {
|
|
482
|
+
method,
|
|
483
|
+
path: timingPath,
|
|
484
|
+
attempt,
|
|
485
|
+
server_trace_id: traceId,
|
|
486
|
+
error: timedOut ? `request timed out after ${this.timeoutMs}ms` : describeError(err)
|
|
487
|
+
});
|
|
386
488
|
if (attempt >= this.maxRetries) {
|
|
387
489
|
const detail = timedOut ? `request timed out after ${this.timeoutMs}ms` : describeError(err);
|
|
388
490
|
throw new SandboxConnectionError(detail, { cause: err });
|
|
@@ -3097,6 +3199,7 @@ var init_sandbox = __esm({
|
|
|
3097
3199
|
init_models();
|
|
3098
3200
|
init_tunnel();
|
|
3099
3201
|
init_sse();
|
|
3202
|
+
init_sdk_timings();
|
|
3100
3203
|
init_url();
|
|
3101
3204
|
DEFAULT_PROCESS_USER = "tl-user";
|
|
3102
3205
|
SandboxProxyConnection = class {
|
|
@@ -3124,7 +3227,12 @@ var init_sandbox = __esm({
|
|
|
3124
3227
|
if (this.resolvePromise != null) {
|
|
3125
3228
|
return this.resolvePromise;
|
|
3126
3229
|
}
|
|
3127
|
-
|
|
3230
|
+
const identifier = this.sandbox._getLifecycleIdentifier();
|
|
3231
|
+
const resolveStart = nowMs();
|
|
3232
|
+
logSdkTimingEvent("sandbox.proxy", "resolve_start", {
|
|
3233
|
+
sandbox_id: identifier
|
|
3234
|
+
});
|
|
3235
|
+
this.resolvePromise = this.resolveProxyInfo(identifier).then((info) => {
|
|
3128
3236
|
this.resolveProxyInfo = void 0;
|
|
3129
3237
|
this.sandbox.traceId = info.traceId;
|
|
3130
3238
|
this.sandbox._setLifecycleIdentifier(info.sandboxId);
|
|
@@ -3134,6 +3242,12 @@ var init_sandbox = __esm({
|
|
|
3134
3242
|
const nextHttp = this.configureProxy(proxyUrl, info.sandboxId, this.routingHint);
|
|
3135
3243
|
this.http.close();
|
|
3136
3244
|
this.http = nextHttp;
|
|
3245
|
+
logSdkTiming("sandbox.proxy", "resolve_complete", resolveStart, {
|
|
3246
|
+
sandbox_id: info.sandboxId,
|
|
3247
|
+
server_trace_id: info.traceId,
|
|
3248
|
+
routing_hint: this.routingHint,
|
|
3249
|
+
ingress_endpoint: info.ingressEndpoint
|
|
3250
|
+
});
|
|
3137
3251
|
}).finally(() => {
|
|
3138
3252
|
this.resolvePromise = null;
|
|
3139
3253
|
});
|
|
@@ -3594,6 +3708,7 @@ var init_sandbox = __esm({
|
|
|
3594
3708
|
* the process, streams output, and delivers the exit code over one connection.
|
|
3595
3709
|
*/
|
|
3596
3710
|
async run(command, options) {
|
|
3711
|
+
const opStart = nowMs();
|
|
3597
3712
|
const body = { command };
|
|
3598
3713
|
if (options?.args) body.args = options.args;
|
|
3599
3714
|
if (options?.env) body.env = options.env;
|
|
@@ -3601,15 +3716,28 @@ var init_sandbox = __esm({
|
|
|
3601
3716
|
if (options?.timeout != null) body.timeout = options.timeout;
|
|
3602
3717
|
const user = processUserPayload(options?.user);
|
|
3603
3718
|
body.user = user;
|
|
3719
|
+
logSdkTimingEvent("sandbox.run", "start", {
|
|
3720
|
+
sandbox_id: this.sandboxId,
|
|
3721
|
+
command: sdkTimingPayloadsEnabled() ? command : void 0,
|
|
3722
|
+
command_length: command.length
|
|
3723
|
+
});
|
|
3724
|
+
const requestStart = nowMs();
|
|
3604
3725
|
const sseStream = await this.http.requestStream(
|
|
3605
3726
|
"POST",
|
|
3606
3727
|
"/api/v1/processes/run",
|
|
3607
3728
|
{ json: body }
|
|
3608
3729
|
);
|
|
3609
3730
|
const traceId = sseStream.traceId;
|
|
3731
|
+
logSdkTiming("sandbox.run", "stream_headers", requestStart, {
|
|
3732
|
+
sandbox_id: this.sandboxId,
|
|
3733
|
+
server_trace_id: traceId,
|
|
3734
|
+
command: sdkTimingPayloadsEnabled() ? command : void 0,
|
|
3735
|
+
command_length: command.length
|
|
3736
|
+
});
|
|
3610
3737
|
const stdoutLines = [];
|
|
3611
3738
|
const stderrLines = [];
|
|
3612
3739
|
let exitCode = -1;
|
|
3740
|
+
const streamStart = nowMs();
|
|
3613
3741
|
for await (const raw of parseSSEStream(sseStream)) {
|
|
3614
3742
|
if (typeof raw.line === "string") {
|
|
3615
3743
|
if (raw.stream === "stderr") {
|
|
@@ -3625,6 +3753,20 @@ var init_sandbox = __esm({
|
|
|
3625
3753
|
}
|
|
3626
3754
|
}
|
|
3627
3755
|
}
|
|
3756
|
+
logSdkTiming("sandbox.run", "stream_complete", streamStart, {
|
|
3757
|
+
sandbox_id: this.sandboxId,
|
|
3758
|
+
server_trace_id: traceId,
|
|
3759
|
+
command: sdkTimingPayloadsEnabled() ? command : void 0,
|
|
3760
|
+
command_length: command.length,
|
|
3761
|
+
exit_code: exitCode
|
|
3762
|
+
});
|
|
3763
|
+
logSdkTiming("sandbox.run", "complete", opStart, {
|
|
3764
|
+
sandbox_id: this.sandboxId,
|
|
3765
|
+
server_trace_id: traceId,
|
|
3766
|
+
command: sdkTimingPayloadsEnabled() ? command : void 0,
|
|
3767
|
+
command_length: command.length,
|
|
3768
|
+
exit_code: exitCode
|
|
3769
|
+
});
|
|
3628
3770
|
return Object.assign(
|
|
3629
3771
|
{ exitCode, stdout: stdoutLines.join("\n"), stderr: stderrLines.join("\n") },
|
|
3630
3772
|
{ traceId }
|
|
@@ -3972,6 +4114,50 @@ var client_exports = {};
|
|
|
3972
4114
|
__export(client_exports, {
|
|
3973
4115
|
SandboxClient: () => SandboxClient
|
|
3974
4116
|
});
|
|
4117
|
+
import { readFile } from "fs/promises";
|
|
4118
|
+
function cloudInitIncludeData(source) {
|
|
4119
|
+
const isWindowsPath = /^[A-Za-z]:[\\/]/.test(source);
|
|
4120
|
+
try {
|
|
4121
|
+
const url = new URL(source);
|
|
4122
|
+
if ((url.protocol === "http:" || url.protocol === "https:") && url.hostname.length > 0) {
|
|
4123
|
+
return Buffer.from(`#include
|
|
4124
|
+
${url.toString()}
|
|
4125
|
+
`, "utf8");
|
|
4126
|
+
}
|
|
4127
|
+
if (!isWindowsPath) {
|
|
4128
|
+
throw new SandboxError(
|
|
4129
|
+
"cloud-init URL must be an absolute HTTP(S) URL with a host"
|
|
4130
|
+
);
|
|
4131
|
+
}
|
|
4132
|
+
} catch (error) {
|
|
4133
|
+
if (error instanceof SandboxError) throw error;
|
|
4134
|
+
if (!isWindowsPath && /^[A-Za-z][A-Za-z0-9+.-]*:/.test(source)) {
|
|
4135
|
+
throw new SandboxError(
|
|
4136
|
+
"cloud-init URL must be an absolute HTTP(S) URL with a host"
|
|
4137
|
+
);
|
|
4138
|
+
}
|
|
4139
|
+
}
|
|
4140
|
+
return void 0;
|
|
4141
|
+
}
|
|
4142
|
+
async function readCloudInitBase64(cloudInit) {
|
|
4143
|
+
if (cloudInit == null) return void 0;
|
|
4144
|
+
const sourceText = cloudInit instanceof URL ? cloudInit.toString() : cloudInit;
|
|
4145
|
+
const includeData = cloudInitIncludeData(sourceText);
|
|
4146
|
+
const data = includeData ?? await readFile(sourceText).catch((error) => {
|
|
4147
|
+
throw new SandboxError(
|
|
4148
|
+
`failed to read cloud-init file ${JSON.stringify(sourceText)}: ${error}`
|
|
4149
|
+
);
|
|
4150
|
+
});
|
|
4151
|
+
if (data.length === 0) {
|
|
4152
|
+
throw new SandboxError("cloud-init user data must not be empty");
|
|
4153
|
+
}
|
|
4154
|
+
if (data.length > MAX_CLOUD_INIT_USER_DATA_BYTES) {
|
|
4155
|
+
throw new SandboxError(
|
|
4156
|
+
`cloud-init user data exceeds ${MAX_CLOUD_INIT_USER_DATA_BYTES} byte limit`
|
|
4157
|
+
);
|
|
4158
|
+
}
|
|
4159
|
+
return data.toString("base64");
|
|
4160
|
+
}
|
|
3975
4161
|
function resolveRequestTimeoutMs(options) {
|
|
3976
4162
|
if (options?.requestTimeout != null) {
|
|
3977
4163
|
return secondsToMillis4(options.requestTimeout);
|
|
@@ -4049,7 +4235,7 @@ function validateUserPort(port) {
|
|
|
4049
4235
|
function dedupeAndSortPorts(ports) {
|
|
4050
4236
|
return [...new Set(ports)].sort((a, b) => a - b);
|
|
4051
4237
|
}
|
|
4052
|
-
var CREATE_SANDBOX_RETRYABLE_STATUS_CODES, CREATE_SANDBOX_ALLOWED_ERROR_STATUS_CODES, COPY_SANDBOX_ALLOWED_ERROR_STATUS_CODES, SandboxClient, RESERVED_SANDBOX_MANAGEMENT_PORT;
|
|
4238
|
+
var CREATE_SANDBOX_RETRYABLE_STATUS_CODES, CREATE_SANDBOX_ALLOWED_ERROR_STATUS_CODES, COPY_SANDBOX_ALLOWED_ERROR_STATUS_CODES, MAX_CLOUD_INIT_USER_DATA_BYTES, SandboxClient, RESERVED_SANDBOX_MANAGEMENT_PORT;
|
|
4053
4239
|
var init_client = __esm({
|
|
4054
4240
|
"src/client.ts"() {
|
|
4055
4241
|
"use strict";
|
|
@@ -4058,10 +4244,12 @@ var init_client = __esm({
|
|
|
4058
4244
|
init_http();
|
|
4059
4245
|
init_models();
|
|
4060
4246
|
init_sandbox();
|
|
4247
|
+
init_sdk_timings();
|
|
4061
4248
|
init_url();
|
|
4062
4249
|
CREATE_SANDBOX_RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([502, 503]);
|
|
4063
4250
|
CREATE_SANDBOX_ALLOWED_ERROR_STATUS_CODES = /* @__PURE__ */ new Set([504]);
|
|
4064
4251
|
COPY_SANDBOX_ALLOWED_ERROR_STATUS_CODES = /* @__PURE__ */ new Set([422, 504]);
|
|
4252
|
+
MAX_CLOUD_INIT_USER_DATA_BYTES = 16 * 1024;
|
|
4065
4253
|
SandboxClient = class _SandboxClient {
|
|
4066
4254
|
http;
|
|
4067
4255
|
apiUrl;
|
|
@@ -4152,6 +4340,7 @@ var init_client = __esm({
|
|
|
4152
4340
|
// --- Sandbox CRUD ---
|
|
4153
4341
|
/** Create a new sandbox. Returns immediately; the sandbox may still be starting. Use `createAndConnect()` for a blocking, ready-to-use handle. */
|
|
4154
4342
|
async create(options) {
|
|
4343
|
+
const cloudInitBase64 = await readCloudInitBase64(options?.cloudInit);
|
|
4155
4344
|
const body = {
|
|
4156
4345
|
resources: {
|
|
4157
4346
|
cpus: options?.cpus ?? 1,
|
|
@@ -4164,6 +4353,7 @@ var init_client = __esm({
|
|
|
4164
4353
|
if (options?.entrypoint != null) body.entrypoint = options.entrypoint;
|
|
4165
4354
|
if (options?.snapshotId != null) body.snapshot_id = options.snapshotId;
|
|
4166
4355
|
if (options?.name != null) body.name = options.name;
|
|
4356
|
+
if (cloudInitBase64 != null) body.cloud_init_base64 = cloudInitBase64;
|
|
4167
4357
|
if (options?.allowInternetAccess === false || options?.allowOut != null || options?.denyOut != null) {
|
|
4168
4358
|
body.network = {
|
|
4169
4359
|
allow_internet_access: options?.allowInternetAccess ?? true,
|
|
@@ -4581,9 +4771,24 @@ var init_client = __esm({
|
|
|
4581
4771
|
* @throws {SandboxError} If the sandbox terminates during startup or the timeout elapses.
|
|
4582
4772
|
*/
|
|
4583
4773
|
async createAndConnect(options) {
|
|
4774
|
+
if (options?.poolId != null && options?.cloudInit != null) {
|
|
4775
|
+
throw new SandboxError("cloud-init cannot be used with poolId");
|
|
4776
|
+
}
|
|
4777
|
+
const opStart = nowMs();
|
|
4584
4778
|
const requestTimeout = options?.requestTimeout ?? options?.startupTimeout ?? this.requestTimeoutMs / 1e3;
|
|
4585
4779
|
const requestClient = this.withRequestTimeout(requestTimeout);
|
|
4780
|
+
logSdkTimingEvent("sandbox.create", "start", {
|
|
4781
|
+
request_timeout_s: requestTimeout,
|
|
4782
|
+
image: options?.image,
|
|
4783
|
+
pool_id: options?.poolId
|
|
4784
|
+
});
|
|
4785
|
+
const createStart = nowMs();
|
|
4586
4786
|
const result = options?.poolId != null ? await requestClient.claim(options.poolId) : await requestClient.create(options);
|
|
4787
|
+
logSdkTiming("sandbox.create", options?.poolId != null ? "claim_response" : "create_response", createStart, {
|
|
4788
|
+
sandbox_id: result.sandboxId,
|
|
4789
|
+
status: result.status,
|
|
4790
|
+
server_trace_id: result.traceId
|
|
4791
|
+
});
|
|
4587
4792
|
const requestedName = options?.poolId != null ? null : options?.name ?? null;
|
|
4588
4793
|
const finishConnect = (routingHint, name, ingressEndpoint) => {
|
|
4589
4794
|
const sandbox = requestClient.connect(
|
|
@@ -4596,6 +4801,13 @@ var init_client = __esm({
|
|
|
4596
4801
|
sandbox.traceId = result.traceId;
|
|
4597
4802
|
sandbox._setLifecycleIdentifier(result.sandboxId);
|
|
4598
4803
|
sandbox._setName(name ?? requestedName);
|
|
4804
|
+
logSdkTiming("sandbox.create", "complete", opStart, {
|
|
4805
|
+
sandbox_id: result.sandboxId,
|
|
4806
|
+
status: "running" /* RUNNING */,
|
|
4807
|
+
server_trace_id: result.traceId,
|
|
4808
|
+
routing_hint: routingHint,
|
|
4809
|
+
ingress_endpoint: ingressEndpoint
|
|
4810
|
+
});
|
|
4599
4811
|
return sandbox;
|
|
4600
4812
|
};
|
|
4601
4813
|
if (result.status === "running" /* RUNNING */) {
|
|
@@ -4620,7 +4832,13 @@ var init_client = __esm({
|
|
|
4620
4832
|
}
|
|
4621
4833
|
const deadline = Date.now() + secondsToMillis4(requestTimeout);
|
|
4622
4834
|
while (Date.now() < deadline) {
|
|
4835
|
+
const pollStart = nowMs();
|
|
4623
4836
|
const info = await requestClient.get(result.sandboxId);
|
|
4837
|
+
logSdkTiming("sandbox.create", "poll_response", pollStart, {
|
|
4838
|
+
sandbox_id: result.sandboxId,
|
|
4839
|
+
status: info.status,
|
|
4840
|
+
server_trace_id: info.traceId
|
|
4841
|
+
});
|
|
4624
4842
|
if (info.status === "running" /* RUNNING */) {
|
|
4625
4843
|
return finishConnect(info.routingHint, info.name, info.ingressEndpoint);
|
|
4626
4844
|
}
|