tensorlake 0.5.89 → 0.5.92

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/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.89";
38
+ SDK_VERSION = "0.5.92";
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";
@@ -339,7 +339,8 @@ function parseTimestamp(v) {
339
339
  return new Date(ts * 1e3);
340
340
  }
341
341
  function fromSnakeKeys(obj, idField) {
342
- if (Array.isArray(obj)) return obj.map((item) => fromSnakeKeys(item, idField));
342
+ if (Array.isArray(obj))
343
+ return obj.map((item) => fromSnakeKeys(item, idField));
343
344
  if (obj !== null && typeof obj === "object" && !(obj instanceof Date)) {
344
345
  const result = {};
345
346
  for (const [k, v] of Object.entries(obj)) {
@@ -4031,13 +4032,17 @@ function resolveRequestTimeoutMs(options) {
4031
4032
  }
4032
4033
  function secondsToMillis3(seconds) {
4033
4034
  if (!Number.isFinite(seconds) || seconds <= 0) {
4034
- throw new SandboxError("requestTimeout must be a positive number of seconds");
4035
+ throw new SandboxError(
4036
+ "requestTimeout must be a positive number of seconds"
4037
+ );
4035
4038
  }
4036
4039
  return Math.ceil(seconds * 1e3);
4037
4040
  }
4038
4041
  function validateTimeoutMs(timeoutMs) {
4039
4042
  if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
4040
- throw new SandboxError("timeoutMs must be a positive number of milliseconds");
4043
+ throw new SandboxError(
4044
+ "timeoutMs must be a positive number of milliseconds"
4045
+ );
4041
4046
  }
4042
4047
  }
4043
4048
  function sleep2(ms) {
@@ -4240,7 +4245,9 @@ var init_client = __esm({
4240
4245
  }
4241
4246
  /** List all sandboxes in the namespace. */
4242
4247
  async list() {
4243
- const { traceId, json } = await callNative(() => this.native.listSandboxes());
4248
+ const { traceId, json } = await callNative(
4249
+ () => this.native.listSandboxes()
4250
+ );
4244
4251
  const parsed = JSON.parse(json);
4245
4252
  const sandboxes = (parsed.sandboxes ?? []).map(
4246
4253
  (s) => fromSnakeKeys(s, "sandboxId")
@@ -4318,7 +4325,9 @@ var init_client = __esm({
4318
4325
  body.exposed_ports = normalizeUserPorts(options.exposedPorts);
4319
4326
  }
4320
4327
  if (Object.keys(body).length === 0) {
4321
- throw new SandboxError("At least one sandbox update field must be provided.");
4328
+ throw new SandboxError(
4329
+ "At least one sandbox update field must be provided."
4330
+ );
4322
4331
  }
4323
4332
  return this.tracedJson(
4324
4333
  () => this.native.updateSandbox(sandboxId, JSON.stringify(body)),
@@ -4354,7 +4363,9 @@ var init_client = __esm({
4354
4363
  const requestedPorts = normalizeUserPorts(ports);
4355
4364
  const current = await this.getPortAccess(sandboxId);
4356
4365
  const toRemove = new Set(requestedPorts);
4357
- const desiredPorts = current.exposedPorts.filter((port) => !toRemove.has(port));
4366
+ const desiredPorts = current.exposedPorts.filter(
4367
+ (port) => !toRemove.has(port)
4368
+ );
4358
4369
  return this.update(sandboxId, {
4359
4370
  allowUnauthenticatedAccess: desiredPorts.length ? current.allowUnauthenticatedAccess : false,
4360
4371
  exposedPorts: desiredPorts
@@ -4362,7 +4373,10 @@ var init_client = __esm({
4362
4373
  }
4363
4374
  /** Terminate and delete a sandbox. */
4364
4375
  async delete(sandboxId) {
4365
- await callNative(() => this.native.deleteSandbox(sandboxId), { sandboxId, notFoundKind: "sandbox" });
4376
+ await callNative(() => this.native.deleteSandbox(sandboxId), {
4377
+ sandboxId,
4378
+ notFoundKind: "sandbox"
4379
+ });
4366
4380
  }
4367
4381
  /**
4368
4382
  * Suspend a named sandbox, preserving its state for later resume.
@@ -4373,7 +4387,10 @@ var init_client = __esm({
4373
4387
  * (fire-and-return); the server processes the suspend asynchronously.
4374
4388
  */
4375
4389
  async suspend(sandboxId, options) {
4376
- await callNative(() => this.native.suspendSandbox(sandboxId), { sandboxId, notFoundKind: "sandbox" });
4390
+ await callNative(() => this.native.suspendSandbox(sandboxId), {
4391
+ sandboxId,
4392
+ notFoundKind: "sandbox"
4393
+ });
4377
4394
  if (options?.wait === false) return;
4378
4395
  const timeout = options?.timeout ?? 300;
4379
4396
  const pollInterval = options?.pollInterval ?? 1;
@@ -4382,11 +4399,15 @@ var init_client = __esm({
4382
4399
  const info = await this.get(sandboxId);
4383
4400
  if (info.status === "suspended" /* SUSPENDED */) return;
4384
4401
  if (info.status === "terminated" /* TERMINATED */) {
4385
- throw new SandboxError(`Sandbox ${sandboxId} terminated while waiting for suspend`);
4402
+ throw new SandboxError(
4403
+ `Sandbox ${sandboxId} terminated while waiting for suspend`
4404
+ );
4386
4405
  }
4387
4406
  await sleep2(pollInterval * 1e3);
4388
4407
  }
4389
- throw new SandboxError(`Sandbox ${sandboxId} did not suspend within ${timeout}s`);
4408
+ throw new SandboxError(
4409
+ `Sandbox ${sandboxId} did not suspend within ${timeout}s`
4410
+ );
4390
4411
  }
4391
4412
  /**
4392
4413
  * Resume a suspended sandbox and bring it back to `Running`.
@@ -4396,7 +4417,10 @@ var init_client = __esm({
4396
4417
  * (fire-and-return); the server processes the resume asynchronously.
4397
4418
  */
4398
4419
  async resume(sandboxId, options) {
4399
- await callNative(() => this.native.resumeSandbox(sandboxId), { sandboxId, notFoundKind: "sandbox" });
4420
+ await callNative(() => this.native.resumeSandbox(sandboxId), {
4421
+ sandboxId,
4422
+ notFoundKind: "sandbox"
4423
+ });
4400
4424
  if (options?.wait === false) return;
4401
4425
  const timeout = options?.timeout ?? 300;
4402
4426
  const pollInterval = options?.pollInterval ?? 1;
@@ -4405,11 +4429,15 @@ var init_client = __esm({
4405
4429
  const info = await this.get(sandboxId);
4406
4430
  if (info.status === "running" /* RUNNING */) return;
4407
4431
  if (info.status === "terminated" /* TERMINATED */) {
4408
- throw new SandboxError(`Sandbox ${sandboxId} terminated while waiting for resume`);
4432
+ throw new SandboxError(
4433
+ `Sandbox ${sandboxId} terminated while waiting for resume`
4434
+ );
4409
4435
  }
4410
4436
  await sleep2(pollInterval * 1e3);
4411
4437
  }
4412
- throw new SandboxError(`Sandbox ${sandboxId} did not resume within ${timeout}s`);
4438
+ throw new SandboxError(
4439
+ `Sandbox ${sandboxId} did not resume within ${timeout}s`
4440
+ );
4413
4441
  }
4414
4442
  /**
4415
4443
  * Attach a registered file system to a running sandbox at `mountPath`.
@@ -4489,7 +4517,9 @@ var init_client = __esm({
4489
4517
  }
4490
4518
  /** List all snapshots in the namespace. */
4491
4519
  async listSnapshots() {
4492
- const { traceId, json } = await callNative(() => this.native.listSnapshots());
4520
+ const { traceId, json } = await callNative(
4521
+ () => this.native.listSnapshots()
4522
+ );
4493
4523
  const parsed = JSON.parse(json);
4494
4524
  const snapshots = (parsed.snapshots ?? []).map(
4495
4525
  (s) => fromSnakeKeys(s, "snapshotId")
@@ -4517,7 +4547,8 @@ var init_client = __esm({
4517
4547
  const deadline = Date.now() + timeout * 1e3;
4518
4548
  while (Date.now() < deadline) {
4519
4549
  const info = await this.getSnapshot(result.snapshotId);
4520
- if (snapshotStatusSatisfiesWaitCondition(info.status, waitUntil)) return info;
4550
+ if (snapshotStatusSatisfiesWaitCondition(info.status, waitUntil))
4551
+ return info;
4521
4552
  if (info.status === "failed" /* FAILED */) {
4522
4553
  throw new SandboxError(
4523
4554
  `Snapshot ${result.snapshotId} failed: ${info.error}`
@@ -4542,8 +4573,11 @@ var init_client = __esm({
4542
4573
  timeout_secs: options.timeoutSecs ?? 0
4543
4574
  };
4544
4575
  if (options.entrypoint != null) body.entrypoint = options.entrypoint;
4545
- if (options.maxContainers != null) body.max_containers = options.maxContainers;
4546
- if (options.warmContainers != null) body.warm_containers = options.warmContainers;
4576
+ if (options.maxContainers != null)
4577
+ body.max_containers = options.maxContainers;
4578
+ if (options.warmContainers != null)
4579
+ body.warm_containers = options.warmContainers;
4580
+ if (options.network != null) body.network = toSnakeKeys(options.network);
4547
4581
  return this.plainJson(
4548
4582
  () => this.native.createPool(JSON.stringify(body)),
4549
4583
  "poolId"
@@ -4566,7 +4600,13 @@ var init_client = __esm({
4566
4600
  );
4567
4601
  return Object.assign(pools, { traceId });
4568
4602
  }
4569
- /** Replace the configuration of an existing sandbox pool. */
4603
+ /**
4604
+ * Replace a pool configuration. Omit `network` to keep the pool's current
4605
+ * network policy, set it to replace the policy, or pass `null` to remove the
4606
+ * policy entirely. On a change the service recycles the pool's unclaimed
4607
+ * warm containers onto the new policy, while containers already claimed by
4608
+ * sandboxes keep the policy they booted with.
4609
+ */
4570
4610
  async updatePool(poolId, options) {
4571
4611
  const body = {
4572
4612
  image: options.image,
@@ -4578,8 +4618,13 @@ var init_client = __esm({
4578
4618
  timeout_secs: options.timeoutSecs ?? 0
4579
4619
  };
4580
4620
  if (options.entrypoint != null) body.entrypoint = options.entrypoint;
4581
- if (options.maxContainers != null) body.max_containers = options.maxContainers;
4582
- if (options.warmContainers != null) body.warm_containers = options.warmContainers;
4621
+ if (options.maxContainers != null)
4622
+ body.max_containers = options.maxContainers;
4623
+ if (options.warmContainers != null)
4624
+ body.warm_containers = options.warmContainers;
4625
+ if (options.network !== void 0) {
4626
+ body.network = options.network === null ? null : toSnakeKeys(options.network);
4627
+ }
4583
4628
  return this.plainJson(
4584
4629
  () => this.native.updatePool(poolId, JSON.stringify(body)),
4585
4630
  "poolId",
@@ -4588,7 +4633,10 @@ var init_client = __esm({
4588
4633
  }
4589
4634
  /** Delete a sandbox pool. Fails if the pool has active containers. */
4590
4635
  async deletePool(poolId) {
4591
- await callNative(() => this.native.deletePool(poolId), { poolId, notFoundKind: "pool" });
4636
+ await callNative(() => this.native.deletePool(poolId), {
4637
+ poolId,
4638
+ notFoundKind: "pool"
4639
+ });
4592
4640
  }
4593
4641
  // --- Connect ---
4594
4642
  /** Return a `Sandbox` handle for an existing running sandbox without verifying it exists. */
@@ -4625,11 +4673,16 @@ var init_client = __esm({
4625
4673
  });
4626
4674
  const createStart = nowMs();
4627
4675
  const result = options?.poolId != null ? await requestClient.claim(options.poolId) : await requestClient.create(options);
4628
- logSdkTiming("sandbox.create", options?.poolId != null ? "claim_response" : "create_response", createStart, {
4629
- sandbox_id: result.sandboxId,
4630
- status: result.status,
4631
- server_trace_id: result.traceId
4632
- });
4676
+ logSdkTiming(
4677
+ "sandbox.create",
4678
+ options?.poolId != null ? "claim_response" : "create_response",
4679
+ createStart,
4680
+ {
4681
+ sandbox_id: result.sandboxId,
4682
+ status: result.status,
4683
+ server_trace_id: result.traceId
4684
+ }
4685
+ );
4633
4686
  const requestedName = options?.poolId != null ? null : options?.name ?? null;
4634
4687
  const finishConnect = (sandboxId, routingHint, name, ingressEndpoint, sandboxUrl) => {
4635
4688
  const explicitProxyUrl = options?.proxyUrl ?? explicitProxyUrlOverride() ?? void 0;
@@ -5093,6 +5146,21 @@ var init_sse = __esm({
5093
5146
  });
5094
5147
 
5095
5148
  // src/cloud-client.ts
5149
+ function applicationAllowsUnauthenticatedRequests(manifest) {
5150
+ return Array.isArray(manifest.allow) && manifest.allow.includes(UNAUTHENTICATED_REQUESTS);
5151
+ }
5152
+ function publicEndpointIdFromManifest(manifest) {
5153
+ for (const key of ["public_endpoint_id", "publicEndpointId"]) {
5154
+ const value = manifest[key];
5155
+ if (typeof value === "string" && value.length > 0) {
5156
+ return value;
5157
+ }
5158
+ }
5159
+ return void 0;
5160
+ }
5161
+ function generatePublicEndpointId() {
5162
+ return `endpoint_${(0, import_nanoid.nanoid)()}`;
5163
+ }
5096
5164
  function createApplicationBuildForm(request, imageContexts) {
5097
5165
  const contextsByPartName = /* @__PURE__ */ new Map();
5098
5166
  for (const context of imageContexts) {
@@ -5162,10 +5230,11 @@ async function parseJsonResponse(response) {
5162
5230
  }
5163
5231
  return JSON.parse(text);
5164
5232
  }
5165
- var CloudClient;
5233
+ var import_nanoid, CloudClient, UNAUTHENTICATED_REQUESTS;
5166
5234
  var init_cloud_client = __esm({
5167
5235
  "src/cloud-client.ts"() {
5168
5236
  "use strict";
5237
+ import_nanoid = require("nanoid");
5169
5238
  init_defaults();
5170
5239
  init_http();
5171
5240
  init_models();
@@ -5195,6 +5264,19 @@ var init_cloud_client = __esm({
5195
5264
  this.http.close();
5196
5265
  }
5197
5266
  async upsertApplication(manifest, codeZip, upgradeRunningRequests = false) {
5267
+ const applicationManifest = { ...manifest };
5268
+ let publicEndpointId = publicEndpointIdFromManifest(applicationManifest);
5269
+ if (applicationAllowsUnauthenticatedRequests(applicationManifest) && publicEndpointId === void 0) {
5270
+ const applicationName = applicationManifest.name;
5271
+ if (typeof applicationName === "string" && applicationName.length > 0) {
5272
+ publicEndpointId = await this.existingApplicationPublicEndpointId(applicationName);
5273
+ }
5274
+ publicEndpointId ??= generatePublicEndpointId();
5275
+ }
5276
+ if (publicEndpointId !== void 0) {
5277
+ applicationManifest.public_endpoint_id = publicEndpointId;
5278
+ delete applicationManifest.publicEndpointId;
5279
+ }
5198
5280
  const form = new FormData();
5199
5281
  form.append(
5200
5282
  "code",
@@ -5202,7 +5284,7 @@ var init_cloud_client = __esm({
5202
5284
  "code.zip"
5203
5285
  );
5204
5286
  form.append("code_content_type", "application/zip");
5205
- form.append("application", JSON.stringify(manifest));
5287
+ form.append("application", JSON.stringify(applicationManifest));
5206
5288
  form.append(
5207
5289
  "upgrade_requests_to_latest_code",
5208
5290
  String(upgradeRunningRequests)
@@ -5515,6 +5597,18 @@ var init_cloud_client = __esm({
5515
5597
  namespacePath(subpath) {
5516
5598
  return `/v1/namespaces/${encodeURIComponent(this.namespace)}/${subpath.replace(/^\/+/, "")}`;
5517
5599
  }
5600
+ async existingApplicationPublicEndpointId(applicationName) {
5601
+ const response = await this.http.requestResponse(
5602
+ "GET",
5603
+ this.namespacePath(`applications/${encodeURIComponent(applicationName)}`),
5604
+ { allowedErrorStatusCodes: /* @__PURE__ */ new Set([404]) }
5605
+ );
5606
+ if (response.status === 404) {
5607
+ return void 0;
5608
+ }
5609
+ const application = await parseJsonResponse(response);
5610
+ return publicEndpointIdFromManifest(application);
5611
+ }
5518
5612
  resolveScope(organizationId, projectId) {
5519
5613
  const resolvedOrganizationId = organizationId ?? this.organizationId;
5520
5614
  const resolvedProjectId = projectId ?? this.projectId;
@@ -5529,6 +5623,7 @@ var init_cloud_client = __esm({
5529
5623
  };
5530
5624
  }
5531
5625
  };
5626
+ UNAUTHENTICATED_REQUESTS = "unauthenticated_requests";
5532
5627
  }
5533
5628
  });
5534
5629