tensorlake 0.5.34 → 0.5.35

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.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.34";
22
+ SDK_VERSION = "0.5.35";
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";
@@ -3972,6 +3972,50 @@ var client_exports = {};
3972
3972
  __export(client_exports, {
3973
3973
  SandboxClient: () => SandboxClient
3974
3974
  });
3975
+ import { readFile } from "fs/promises";
3976
+ function cloudInitIncludeData(source) {
3977
+ const isWindowsPath = /^[A-Za-z]:[\\/]/.test(source);
3978
+ try {
3979
+ const url = new URL(source);
3980
+ if ((url.protocol === "http:" || url.protocol === "https:") && url.hostname.length > 0) {
3981
+ return Buffer.from(`#include
3982
+ ${url.toString()}
3983
+ `, "utf8");
3984
+ }
3985
+ if (!isWindowsPath) {
3986
+ throw new SandboxError(
3987
+ "cloud-init URL must be an absolute HTTP(S) URL with a host"
3988
+ );
3989
+ }
3990
+ } catch (error) {
3991
+ if (error instanceof SandboxError) throw error;
3992
+ if (!isWindowsPath && /^[A-Za-z][A-Za-z0-9+.-]*:/.test(source)) {
3993
+ throw new SandboxError(
3994
+ "cloud-init URL must be an absolute HTTP(S) URL with a host"
3995
+ );
3996
+ }
3997
+ }
3998
+ return void 0;
3999
+ }
4000
+ async function readCloudInitBase64(cloudInit) {
4001
+ if (cloudInit == null) return void 0;
4002
+ const sourceText = cloudInit instanceof URL ? cloudInit.toString() : cloudInit;
4003
+ const includeData = cloudInitIncludeData(sourceText);
4004
+ const data = includeData ?? await readFile(sourceText).catch((error) => {
4005
+ throw new SandboxError(
4006
+ `failed to read cloud-init file ${JSON.stringify(sourceText)}: ${error}`
4007
+ );
4008
+ });
4009
+ if (data.length === 0) {
4010
+ throw new SandboxError("cloud-init user data must not be empty");
4011
+ }
4012
+ if (data.length > MAX_CLOUD_INIT_USER_DATA_BYTES) {
4013
+ throw new SandboxError(
4014
+ `cloud-init user data exceeds ${MAX_CLOUD_INIT_USER_DATA_BYTES} byte limit`
4015
+ );
4016
+ }
4017
+ return data.toString("base64");
4018
+ }
3975
4019
  function resolveRequestTimeoutMs(options) {
3976
4020
  if (options?.requestTimeout != null) {
3977
4021
  return secondsToMillis4(options.requestTimeout);
@@ -4049,7 +4093,7 @@ function validateUserPort(port) {
4049
4093
  function dedupeAndSortPorts(ports) {
4050
4094
  return [...new Set(ports)].sort((a, b) => a - b);
4051
4095
  }
4052
- var CREATE_SANDBOX_RETRYABLE_STATUS_CODES, CREATE_SANDBOX_ALLOWED_ERROR_STATUS_CODES, COPY_SANDBOX_ALLOWED_ERROR_STATUS_CODES, SandboxClient, RESERVED_SANDBOX_MANAGEMENT_PORT;
4096
+ 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
4097
  var init_client = __esm({
4054
4098
  "src/client.ts"() {
4055
4099
  "use strict";
@@ -4062,6 +4106,7 @@ var init_client = __esm({
4062
4106
  CREATE_SANDBOX_RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([502, 503]);
4063
4107
  CREATE_SANDBOX_ALLOWED_ERROR_STATUS_CODES = /* @__PURE__ */ new Set([504]);
4064
4108
  COPY_SANDBOX_ALLOWED_ERROR_STATUS_CODES = /* @__PURE__ */ new Set([422, 504]);
4109
+ MAX_CLOUD_INIT_USER_DATA_BYTES = 16 * 1024;
4065
4110
  SandboxClient = class _SandboxClient {
4066
4111
  http;
4067
4112
  apiUrl;
@@ -4152,6 +4197,7 @@ var init_client = __esm({
4152
4197
  // --- Sandbox CRUD ---
4153
4198
  /** Create a new sandbox. Returns immediately; the sandbox may still be starting. Use `createAndConnect()` for a blocking, ready-to-use handle. */
4154
4199
  async create(options) {
4200
+ const cloudInitBase64 = await readCloudInitBase64(options?.cloudInit);
4155
4201
  const body = {
4156
4202
  resources: {
4157
4203
  cpus: options?.cpus ?? 1,
@@ -4164,6 +4210,7 @@ var init_client = __esm({
4164
4210
  if (options?.entrypoint != null) body.entrypoint = options.entrypoint;
4165
4211
  if (options?.snapshotId != null) body.snapshot_id = options.snapshotId;
4166
4212
  if (options?.name != null) body.name = options.name;
4213
+ if (cloudInitBase64 != null) body.cloud_init_base64 = cloudInitBase64;
4167
4214
  if (options?.allowInternetAccess === false || options?.allowOut != null || options?.denyOut != null) {
4168
4215
  body.network = {
4169
4216
  allow_internet_access: options?.allowInternetAccess ?? true,
@@ -4581,6 +4628,9 @@ var init_client = __esm({
4581
4628
  * @throws {SandboxError} If the sandbox terminates during startup or the timeout elapses.
4582
4629
  */
4583
4630
  async createAndConnect(options) {
4631
+ if (options?.poolId != null && options?.cloudInit != null) {
4632
+ throw new SandboxError("cloud-init cannot be used with poolId");
4633
+ }
4584
4634
  const requestTimeout = options?.requestTimeout ?? options?.startupTimeout ?? this.requestTimeoutMs / 1e3;
4585
4635
  const requestClient = this.withRequestTimeout(requestTimeout);
4586
4636
  const result = options?.poolId != null ? await requestClient.claim(options.poolId) : await requestClient.create(options);