tensorlake 0.5.33 → 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
@@ -57,7 +57,8 @@ type SnapshotWaitCondition = "local_ready" | "completed";
57
57
  declare enum ProcessStatus {
58
58
  RUNNING = "running",
59
59
  EXITED = "exited",
60
- SIGNALED = "signaled"
60
+ SIGNALED = "signaled",
61
+ OOM_KILLED = "oom_killed"
61
62
  }
62
63
  declare enum StdinMode {
63
64
  CLOSED = "closed",
@@ -96,6 +97,11 @@ interface CreateSandboxOptions {
96
97
  snapshotId?: string;
97
98
  /** Optional name for the sandbox. Named sandboxes support suspend/resume. When absent the sandbox is ephemeral. */
98
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;
99
105
  }
100
106
  interface UpdateSandboxOptions {
101
107
  /** New name for the sandbox. Naming an ephemeral sandbox enables suspend/resume. */
@@ -266,6 +272,44 @@ interface ProcessUserSpec {
266
272
  gid?: number;
267
273
  }
268
274
  type ProcessUser = string | ProcessUserSpec;
275
+ type RestartPolicy = "never" | "on_failure" | "always";
276
+ interface RestartPolicyConfig {
277
+ policy?: RestartPolicy;
278
+ maxRestarts?: number;
279
+ initialBackoffMs?: number;
280
+ maxBackoffMs?: number;
281
+ }
282
+ type ProcessHealthCheckType = "http" | "tcp";
283
+ interface ProcessHealthCheck {
284
+ type: ProcessHealthCheckType;
285
+ port: number;
286
+ path?: string;
287
+ initialDelayMs?: number;
288
+ intervalMs?: number;
289
+ timeoutMs?: number;
290
+ failureThreshold?: number;
291
+ }
292
+ type ManagedProcessStatus = "starting" | "running" | "backing_off" | "stopped";
293
+ type ManagedProcessHealthStatus = "disabled" | "starting" | "healthy" | "unhealthy";
294
+ interface ManagedProcessExit {
295
+ exitCode?: number;
296
+ signal?: number;
297
+ oomKilled: boolean;
298
+ endedAt: Date;
299
+ }
300
+ interface ManagedProcessInfo {
301
+ id: string;
302
+ name?: string;
303
+ status: ManagedProcessStatus;
304
+ restartCount: number;
305
+ restart: RestartPolicyConfig;
306
+ healthCheck?: ProcessHealthCheck;
307
+ healthStatus: ManagedProcessHealthStatus;
308
+ consecutiveHealthFailures: number;
309
+ lastExit?: ManagedProcessExit;
310
+ lastError?: string;
311
+ nextRestartAt?: Date;
312
+ }
269
313
  interface StartProcessOptions {
270
314
  args?: string[];
271
315
  env?: Record<string, string>;
@@ -274,8 +318,15 @@ interface StartProcessOptions {
274
318
  stdoutMode?: OutputMode;
275
319
  stderrMode?: OutputMode;
276
320
  user?: ProcessUser;
321
+ /** Optional managed-process name. Supplying this opts into managed process behavior. */
322
+ name?: string;
323
+ /** Optional restart behavior. Supplying this opts into managed process behavior. */
324
+ restart?: RestartPolicyConfig;
325
+ /** Optional HTTP/TCP health check. Supplying this opts into managed process behavior. */
326
+ healthCheck?: ProcessHealthCheck;
277
327
  }
278
328
  interface ProcessInfo {
329
+ handle?: number;
279
330
  pid: number;
280
331
  status: ProcessStatus;
281
332
  exitCode?: number;
@@ -285,6 +336,7 @@ interface ProcessInfo {
285
336
  args: string[];
286
337
  startedAt: Date;
287
338
  endedAt?: Date;
339
+ managed?: ManagedProcessInfo;
288
340
  }
289
341
  interface SendSignalResponse {
290
342
  success: boolean;
@@ -656,6 +708,8 @@ declare class Sandbox {
656
708
  getProcess(pid: number): Promise<Traced<ProcessInfo>>;
657
709
  /** Send SIGKILL to a process. */
658
710
  killProcess(pid: number): Promise<void>;
711
+ /** Restart a managed process by PID. */
712
+ restartProcess(pid: number): Promise<Traced<ProcessInfo>>;
659
713
  /** Send an arbitrary signal to a process (e.g. `15` for SIGTERM, `9` for SIGKILL). */
660
714
  sendSignal(pid: number, signal: number): Promise<Traced<SendSignalResponse>>;
661
715
  /** Write bytes to a process's stdin. The process must have been started with `stdinMode: StdinMode.PIPE`. */
@@ -1140,4 +1194,4 @@ declare class RequestExecutionError extends Error {
1140
1194
  constructor(message: string, functionName?: string);
1141
1195
  }
1142
1196
 
1143
- export { APIClient, type ApiKeyIntrospection, type ApplicationBuildContext, type ApplicationBuildImageResult, type ApplicationBuildResponse, type ApplicationManifest, type ApplicationSummary, type ArchivedSandboxInfo, type BinaryPayload, type BuildInfo, type BuildLogEntry, type CheckpointOptions, type CheckpointType, CloudClient, type CloudClientOptions, type CommandResult, type ConnectDesktopOptions, type ConnectOptions, type ContainerResourcesInfo, ContainerState, type CopiedSandboxResponse, type CopySandboxOptions, type CopySandboxResponse, type CreateAndConnectOptions, type CreateApplicationBuildImageRequest, type CreateApplicationBuildRequest, type CreatePoolOptions, type CreatePtyOptions, type CreatePtySessionOptions, type CreateSandboxOptions, type CreateSandboxPoolResponse, type CreateSandboxResponse, type CreateSnapshotResponse, type CreateTunnelOptions, type DaemonInfo, Desktop, type DesktopDoubleClickOptions, type DesktopPointerOptions, type DirectoryEntry, type HealthResponse, type ListArchivedSandboxesOptions, type ListArchivedSandboxesResponse, type ListDirectoryResponse, type MouseButton, type NetworkConfig, type NewSecret, type OutputEvent, OutputMode, type OutputResponse, type PoolContainerInfo, PoolInUseError, PoolNotFoundError, type ProcessInfo, ProcessStatus, type ProcessUser, type ProcessUserSpec, Pty, type PtyConnectionOptions, type PtyDataHandler, type PtyExitHandler, type PtySessionInfo, RemoteAPIError, type RequestErrorInfo, RequestExecutionError, RequestFailedError, type RequestInput, type RequestMetadata, RequestNotFinishedError, type RequestOutput, type RunOptions, Sandbox, SandboxClient, type SandboxClientOptions, SandboxConnectionError, SandboxError, SandboxException, type SandboxInfo, SandboxNotFoundError, type SandboxOptions, type SandboxPoolInfo, type SandboxPortAccess, SandboxStatus, type Secret, type SecretsList, type SecretsPagination, type SendSignalResponse, type SnapshotAndWaitOptions, type SnapshotInfo, type SnapshotOptions, SnapshotStatus, type SnapshotType, type SnapshotWaitCondition, type StartImageBuildRequest, type StartProcessOptions, StdinMode, type SuspendResumeOptions, TcpTunnel, type TunnelAddress, type UpdatePoolOptions, type UpsertSecretResponse, sandboxUrlFromIngressEndpoint };
1197
+ export { APIClient, type ApiKeyIntrospection, type ApplicationBuildContext, type ApplicationBuildImageResult, type ApplicationBuildResponse, type ApplicationManifest, type ApplicationSummary, type ArchivedSandboxInfo, type BinaryPayload, type BuildInfo, type BuildLogEntry, type CheckpointOptions, type CheckpointType, CloudClient, type CloudClientOptions, type CommandResult, type ConnectDesktopOptions, type ConnectOptions, type ContainerResourcesInfo, ContainerState, type CopiedSandboxResponse, type CopySandboxOptions, type CopySandboxResponse, type CreateAndConnectOptions, type CreateApplicationBuildImageRequest, type CreateApplicationBuildRequest, type CreatePoolOptions, type CreatePtyOptions, type CreatePtySessionOptions, type CreateSandboxOptions, type CreateSandboxPoolResponse, type CreateSandboxResponse, type CreateSnapshotResponse, type CreateTunnelOptions, type DaemonInfo, Desktop, type DesktopDoubleClickOptions, type DesktopPointerOptions, type DirectoryEntry, type HealthResponse, type ListArchivedSandboxesOptions, type ListArchivedSandboxesResponse, type ListDirectoryResponse, type ManagedProcessExit, type ManagedProcessHealthStatus, type ManagedProcessInfo, type ManagedProcessStatus, type MouseButton, type NetworkConfig, type NewSecret, type OutputEvent, OutputMode, type OutputResponse, type PoolContainerInfo, PoolInUseError, PoolNotFoundError, type ProcessHealthCheck, type ProcessHealthCheckType, type ProcessInfo, ProcessStatus, type ProcessUser, type ProcessUserSpec, Pty, type PtyConnectionOptions, type PtyDataHandler, type PtyExitHandler, type PtySessionInfo, RemoteAPIError, type RequestErrorInfo, RequestExecutionError, RequestFailedError, type RequestInput, type RequestMetadata, RequestNotFinishedError, type RequestOutput, type RestartPolicy, type RestartPolicyConfig, type RunOptions, Sandbox, SandboxClient, type SandboxClientOptions, SandboxConnectionError, SandboxError, SandboxException, type SandboxInfo, SandboxNotFoundError, type SandboxOptions, type SandboxPoolInfo, type SandboxPortAccess, SandboxStatus, type Secret, type SecretsList, type SecretsPagination, type SendSignalResponse, type SnapshotAndWaitOptions, type SnapshotInfo, type SnapshotOptions, SnapshotStatus, type SnapshotType, type SnapshotWaitCondition, type StartImageBuildRequest, type StartProcessOptions, StdinMode, type SuspendResumeOptions, TcpTunnel, type TunnelAddress, type UpdatePoolOptions, type UpsertSecretResponse, sandboxUrlFromIngressEndpoint };
package/dist/index.d.ts CHANGED
@@ -57,7 +57,8 @@ type SnapshotWaitCondition = "local_ready" | "completed";
57
57
  declare enum ProcessStatus {
58
58
  RUNNING = "running",
59
59
  EXITED = "exited",
60
- SIGNALED = "signaled"
60
+ SIGNALED = "signaled",
61
+ OOM_KILLED = "oom_killed"
61
62
  }
62
63
  declare enum StdinMode {
63
64
  CLOSED = "closed",
@@ -96,6 +97,11 @@ interface CreateSandboxOptions {
96
97
  snapshotId?: string;
97
98
  /** Optional name for the sandbox. Named sandboxes support suspend/resume. When absent the sandbox is ephemeral. */
98
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;
99
105
  }
100
106
  interface UpdateSandboxOptions {
101
107
  /** New name for the sandbox. Naming an ephemeral sandbox enables suspend/resume. */
@@ -266,6 +272,44 @@ interface ProcessUserSpec {
266
272
  gid?: number;
267
273
  }
268
274
  type ProcessUser = string | ProcessUserSpec;
275
+ type RestartPolicy = "never" | "on_failure" | "always";
276
+ interface RestartPolicyConfig {
277
+ policy?: RestartPolicy;
278
+ maxRestarts?: number;
279
+ initialBackoffMs?: number;
280
+ maxBackoffMs?: number;
281
+ }
282
+ type ProcessHealthCheckType = "http" | "tcp";
283
+ interface ProcessHealthCheck {
284
+ type: ProcessHealthCheckType;
285
+ port: number;
286
+ path?: string;
287
+ initialDelayMs?: number;
288
+ intervalMs?: number;
289
+ timeoutMs?: number;
290
+ failureThreshold?: number;
291
+ }
292
+ type ManagedProcessStatus = "starting" | "running" | "backing_off" | "stopped";
293
+ type ManagedProcessHealthStatus = "disabled" | "starting" | "healthy" | "unhealthy";
294
+ interface ManagedProcessExit {
295
+ exitCode?: number;
296
+ signal?: number;
297
+ oomKilled: boolean;
298
+ endedAt: Date;
299
+ }
300
+ interface ManagedProcessInfo {
301
+ id: string;
302
+ name?: string;
303
+ status: ManagedProcessStatus;
304
+ restartCount: number;
305
+ restart: RestartPolicyConfig;
306
+ healthCheck?: ProcessHealthCheck;
307
+ healthStatus: ManagedProcessHealthStatus;
308
+ consecutiveHealthFailures: number;
309
+ lastExit?: ManagedProcessExit;
310
+ lastError?: string;
311
+ nextRestartAt?: Date;
312
+ }
269
313
  interface StartProcessOptions {
270
314
  args?: string[];
271
315
  env?: Record<string, string>;
@@ -274,8 +318,15 @@ interface StartProcessOptions {
274
318
  stdoutMode?: OutputMode;
275
319
  stderrMode?: OutputMode;
276
320
  user?: ProcessUser;
321
+ /** Optional managed-process name. Supplying this opts into managed process behavior. */
322
+ name?: string;
323
+ /** Optional restart behavior. Supplying this opts into managed process behavior. */
324
+ restart?: RestartPolicyConfig;
325
+ /** Optional HTTP/TCP health check. Supplying this opts into managed process behavior. */
326
+ healthCheck?: ProcessHealthCheck;
277
327
  }
278
328
  interface ProcessInfo {
329
+ handle?: number;
279
330
  pid: number;
280
331
  status: ProcessStatus;
281
332
  exitCode?: number;
@@ -285,6 +336,7 @@ interface ProcessInfo {
285
336
  args: string[];
286
337
  startedAt: Date;
287
338
  endedAt?: Date;
339
+ managed?: ManagedProcessInfo;
288
340
  }
289
341
  interface SendSignalResponse {
290
342
  success: boolean;
@@ -656,6 +708,8 @@ declare class Sandbox {
656
708
  getProcess(pid: number): Promise<Traced<ProcessInfo>>;
657
709
  /** Send SIGKILL to a process. */
658
710
  killProcess(pid: number): Promise<void>;
711
+ /** Restart a managed process by PID. */
712
+ restartProcess(pid: number): Promise<Traced<ProcessInfo>>;
659
713
  /** Send an arbitrary signal to a process (e.g. `15` for SIGTERM, `9` for SIGKILL). */
660
714
  sendSignal(pid: number, signal: number): Promise<Traced<SendSignalResponse>>;
661
715
  /** Write bytes to a process's stdin. The process must have been started with `stdinMode: StdinMode.PIPE`. */
@@ -1140,4 +1194,4 @@ declare class RequestExecutionError extends Error {
1140
1194
  constructor(message: string, functionName?: string);
1141
1195
  }
1142
1196
 
1143
- export { APIClient, type ApiKeyIntrospection, type ApplicationBuildContext, type ApplicationBuildImageResult, type ApplicationBuildResponse, type ApplicationManifest, type ApplicationSummary, type ArchivedSandboxInfo, type BinaryPayload, type BuildInfo, type BuildLogEntry, type CheckpointOptions, type CheckpointType, CloudClient, type CloudClientOptions, type CommandResult, type ConnectDesktopOptions, type ConnectOptions, type ContainerResourcesInfo, ContainerState, type CopiedSandboxResponse, type CopySandboxOptions, type CopySandboxResponse, type CreateAndConnectOptions, type CreateApplicationBuildImageRequest, type CreateApplicationBuildRequest, type CreatePoolOptions, type CreatePtyOptions, type CreatePtySessionOptions, type CreateSandboxOptions, type CreateSandboxPoolResponse, type CreateSandboxResponse, type CreateSnapshotResponse, type CreateTunnelOptions, type DaemonInfo, Desktop, type DesktopDoubleClickOptions, type DesktopPointerOptions, type DirectoryEntry, type HealthResponse, type ListArchivedSandboxesOptions, type ListArchivedSandboxesResponse, type ListDirectoryResponse, type MouseButton, type NetworkConfig, type NewSecret, type OutputEvent, OutputMode, type OutputResponse, type PoolContainerInfo, PoolInUseError, PoolNotFoundError, type ProcessInfo, ProcessStatus, type ProcessUser, type ProcessUserSpec, Pty, type PtyConnectionOptions, type PtyDataHandler, type PtyExitHandler, type PtySessionInfo, RemoteAPIError, type RequestErrorInfo, RequestExecutionError, RequestFailedError, type RequestInput, type RequestMetadata, RequestNotFinishedError, type RequestOutput, type RunOptions, Sandbox, SandboxClient, type SandboxClientOptions, SandboxConnectionError, SandboxError, SandboxException, type SandboxInfo, SandboxNotFoundError, type SandboxOptions, type SandboxPoolInfo, type SandboxPortAccess, SandboxStatus, type Secret, type SecretsList, type SecretsPagination, type SendSignalResponse, type SnapshotAndWaitOptions, type SnapshotInfo, type SnapshotOptions, SnapshotStatus, type SnapshotType, type SnapshotWaitCondition, type StartImageBuildRequest, type StartProcessOptions, StdinMode, type SuspendResumeOptions, TcpTunnel, type TunnelAddress, type UpdatePoolOptions, type UpsertSecretResponse, sandboxUrlFromIngressEndpoint };
1197
+ export { APIClient, type ApiKeyIntrospection, type ApplicationBuildContext, type ApplicationBuildImageResult, type ApplicationBuildResponse, type ApplicationManifest, type ApplicationSummary, type ArchivedSandboxInfo, type BinaryPayload, type BuildInfo, type BuildLogEntry, type CheckpointOptions, type CheckpointType, CloudClient, type CloudClientOptions, type CommandResult, type ConnectDesktopOptions, type ConnectOptions, type ContainerResourcesInfo, ContainerState, type CopiedSandboxResponse, type CopySandboxOptions, type CopySandboxResponse, type CreateAndConnectOptions, type CreateApplicationBuildImageRequest, type CreateApplicationBuildRequest, type CreatePoolOptions, type CreatePtyOptions, type CreatePtySessionOptions, type CreateSandboxOptions, type CreateSandboxPoolResponse, type CreateSandboxResponse, type CreateSnapshotResponse, type CreateTunnelOptions, type DaemonInfo, Desktop, type DesktopDoubleClickOptions, type DesktopPointerOptions, type DirectoryEntry, type HealthResponse, type ListArchivedSandboxesOptions, type ListArchivedSandboxesResponse, type ListDirectoryResponse, type ManagedProcessExit, type ManagedProcessHealthStatus, type ManagedProcessInfo, type ManagedProcessStatus, type MouseButton, type NetworkConfig, type NewSecret, type OutputEvent, OutputMode, type OutputResponse, type PoolContainerInfo, PoolInUseError, PoolNotFoundError, type ProcessHealthCheck, type ProcessHealthCheckType, type ProcessInfo, ProcessStatus, type ProcessUser, type ProcessUserSpec, Pty, type PtyConnectionOptions, type PtyDataHandler, type PtyExitHandler, type PtySessionInfo, RemoteAPIError, type RequestErrorInfo, RequestExecutionError, RequestFailedError, type RequestInput, type RequestMetadata, RequestNotFinishedError, type RequestOutput, type RestartPolicy, type RestartPolicyConfig, type RunOptions, Sandbox, SandboxClient, type SandboxClientOptions, SandboxConnectionError, SandboxError, SandboxException, type SandboxInfo, SandboxNotFoundError, type SandboxOptions, type SandboxPoolInfo, type SandboxPortAccess, SandboxStatus, type Secret, type SecretsList, type SecretsPagination, type SendSignalResponse, type SnapshotAndWaitOptions, type SnapshotInfo, type SnapshotOptions, SnapshotStatus, type SnapshotType, type SnapshotWaitCondition, type StartImageBuildRequest, type StartProcessOptions, StdinMode, type SuspendResumeOptions, TcpTunnel, type TunnelAddress, type UpdatePoolOptions, type UpsertSecretResponse, sandboxUrlFromIngressEndpoint };
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.33";
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";
@@ -399,9 +399,23 @@ var init_http = __esm({
399
399
  });
400
400
 
401
401
  // src/models.ts
402
+ function camelToSnake(str) {
403
+ return str.replace(CAMEL_TO_SNAKE_RE, (ch) => "_" + ch.toLowerCase());
404
+ }
402
405
  function snakeToCamel(str) {
403
406
  return str.replace(/_([a-z])/g, (_, ch) => ch.toUpperCase());
404
407
  }
408
+ function toSnakeKeys(obj) {
409
+ if (Array.isArray(obj)) return obj.map(toSnakeKeys);
410
+ if (obj !== null && typeof obj === "object" && !(obj instanceof Date)) {
411
+ const result = {};
412
+ for (const [k, v] of Object.entries(obj)) {
413
+ result[camelToSnake(k)] = toSnakeKeys(v);
414
+ }
415
+ return result;
416
+ }
417
+ return obj;
418
+ }
405
419
  function parseTimestamp(v) {
406
420
  if (v == null) return void 0;
407
421
  if (v instanceof Date) return v;
@@ -440,7 +454,7 @@ function fromSnakeKeys(obj, idField) {
440
454
  }
441
455
  return obj;
442
456
  }
443
- var SandboxStatus, SnapshotStatus, ProcessStatus, StdinMode, OutputMode, ContainerState;
457
+ var SandboxStatus, SnapshotStatus, ProcessStatus, StdinMode, OutputMode, ContainerState, CAMEL_TO_SNAKE_RE;
444
458
  var init_models = __esm({
445
459
  "src/models.ts"() {
446
460
  "use strict";
@@ -465,6 +479,7 @@ var init_models = __esm({
465
479
  ProcessStatus2["RUNNING"] = "running";
466
480
  ProcessStatus2["EXITED"] = "exited";
467
481
  ProcessStatus2["SIGNALED"] = "signaled";
482
+ ProcessStatus2["OOM_KILLED"] = "oom_killed";
468
483
  return ProcessStatus2;
469
484
  })(ProcessStatus || {});
470
485
  StdinMode = /* @__PURE__ */ ((StdinMode2) => {
@@ -482,6 +497,7 @@ var init_models = __esm({
482
497
  ContainerState2["RUNNING"] = "Running";
483
498
  return ContainerState2;
484
499
  })(ContainerState || {});
500
+ CAMEL_TO_SNAKE_RE = /[A-Z]/g;
485
501
  }
486
502
  });
487
503
 
@@ -3639,6 +3655,11 @@ var init_sandbox = __esm({
3639
3655
  if (options?.stderrMode != null && options.stderrMode !== "capture" /* CAPTURE */) {
3640
3656
  payload.stderr_mode = options.stderrMode;
3641
3657
  }
3658
+ if (options?.name != null) payload.name = options.name;
3659
+ if (options?.restart != null) payload.restart = toSnakeKeys(options.restart);
3660
+ if (options?.healthCheck != null) {
3661
+ payload.health_check = toSnakeKeys(options.healthCheck);
3662
+ }
3642
3663
  const raw = await this.http.requestJson(
3643
3664
  "POST",
3644
3665
  "/api/v1/processes",
@@ -3667,6 +3688,14 @@ var init_sandbox = __esm({
3667
3688
  async killProcess(pid) {
3668
3689
  await this.http.requestJson("DELETE", `/api/v1/processes/${pid}`);
3669
3690
  }
3691
+ /** Restart a managed process by PID. */
3692
+ async restartProcess(pid) {
3693
+ const raw = await this.http.requestJson(
3694
+ "POST",
3695
+ `/api/v1/processes/${pid}/restart`
3696
+ );
3697
+ return Object.assign(fromSnakeKeys(raw), { traceId: raw.traceId });
3698
+ }
3670
3699
  /** Send an arbitrary signal to a process (e.g. `15` for SIGTERM, `9` for SIGKILL). */
3671
3700
  async sendSignal(pid, signal) {
3672
3701
  const raw = await this.http.requestJson(
@@ -3943,6 +3972,50 @@ var client_exports = {};
3943
3972
  __export(client_exports, {
3944
3973
  SandboxClient: () => SandboxClient
3945
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
+ }
3946
4019
  function resolveRequestTimeoutMs(options) {
3947
4020
  if (options?.requestTimeout != null) {
3948
4021
  return secondsToMillis4(options.requestTimeout);
@@ -4020,7 +4093,7 @@ function validateUserPort(port) {
4020
4093
  function dedupeAndSortPorts(ports) {
4021
4094
  return [...new Set(ports)].sort((a, b) => a - b);
4022
4095
  }
4023
- 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;
4024
4097
  var init_client = __esm({
4025
4098
  "src/client.ts"() {
4026
4099
  "use strict";
@@ -4033,6 +4106,7 @@ var init_client = __esm({
4033
4106
  CREATE_SANDBOX_RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([502, 503]);
4034
4107
  CREATE_SANDBOX_ALLOWED_ERROR_STATUS_CODES = /* @__PURE__ */ new Set([504]);
4035
4108
  COPY_SANDBOX_ALLOWED_ERROR_STATUS_CODES = /* @__PURE__ */ new Set([422, 504]);
4109
+ MAX_CLOUD_INIT_USER_DATA_BYTES = 16 * 1024;
4036
4110
  SandboxClient = class _SandboxClient {
4037
4111
  http;
4038
4112
  apiUrl;
@@ -4123,6 +4197,7 @@ var init_client = __esm({
4123
4197
  // --- Sandbox CRUD ---
4124
4198
  /** Create a new sandbox. Returns immediately; the sandbox may still be starting. Use `createAndConnect()` for a blocking, ready-to-use handle. */
4125
4199
  async create(options) {
4200
+ const cloudInitBase64 = await readCloudInitBase64(options?.cloudInit);
4126
4201
  const body = {
4127
4202
  resources: {
4128
4203
  cpus: options?.cpus ?? 1,
@@ -4135,6 +4210,7 @@ var init_client = __esm({
4135
4210
  if (options?.entrypoint != null) body.entrypoint = options.entrypoint;
4136
4211
  if (options?.snapshotId != null) body.snapshot_id = options.snapshotId;
4137
4212
  if (options?.name != null) body.name = options.name;
4213
+ if (cloudInitBase64 != null) body.cloud_init_base64 = cloudInitBase64;
4138
4214
  if (options?.allowInternetAccess === false || options?.allowOut != null || options?.denyOut != null) {
4139
4215
  body.network = {
4140
4216
  allow_internet_access: options?.allowInternetAccess ?? true,
@@ -4367,7 +4443,7 @@ var init_client = __esm({
4367
4443
  const client = this.withRequestTimeout(options?.requestTimeout);
4368
4444
  const raw = await client.http.requestJson(
4369
4445
  "POST",
4370
- client.path(`sandbox/${sandboxId}/copy?times=${encodeURIComponent(String(times))}`),
4446
+ client.path(`sandboxes/${sandboxId}/copy?times=${encodeURIComponent(String(times))}`),
4371
4447
  { allowedErrorStatusCodes: COPY_SANDBOX_ALLOWED_ERROR_STATUS_CODES }
4372
4448
  );
4373
4449
  const result = fromSnakeKeys(raw, "sandboxId");
@@ -4552,6 +4628,9 @@ var init_client = __esm({
4552
4628
  * @throws {SandboxError} If the sandbox terminates during startup or the timeout elapses.
4553
4629
  */
4554
4630
  async createAndConnect(options) {
4631
+ if (options?.poolId != null && options?.cloudInit != null) {
4632
+ throw new SandboxError("cloud-init cannot be used with poolId");
4633
+ }
4555
4634
  const requestTimeout = options?.requestTimeout ?? options?.startupTimeout ?? this.requestTimeoutMs / 1e3;
4556
4635
  const requestClient = this.withRequestTimeout(requestTimeout);
4557
4636
  const result = options?.poolId != null ? await requestClient.claim(options.poolId) : await requestClient.create(options);