tensorlake 0.5.0 → 0.5.2

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.
@@ -54,7 +54,8 @@ interface CreateSandboxOptions {
54
54
  image?: string;
55
55
  cpus?: number;
56
56
  memoryMb?: number;
57
- ephemeralDiskMb?: number;
57
+ /** Root disk size in megabytes. When omitted, the server uses its default disk size. */
58
+ diskMb?: number;
58
59
  secretNames?: string[];
59
60
  timeoutSecs?: number;
60
61
  entrypoint?: string[];
@@ -77,6 +78,9 @@ interface CreateSandboxResponse {
77
78
  sandboxId: string;
78
79
  status: SandboxStatus;
79
80
  routingHint?: string;
81
+ name?: string | null;
82
+ terminationReason?: string;
83
+ errorDetails?: unknown;
80
84
  }
81
85
  interface SandboxInfo {
82
86
  sandboxId: string;
@@ -91,6 +95,8 @@ interface SandboxInfo {
91
95
  network?: NetworkConfig;
92
96
  poolId?: string;
93
97
  outcome?: string;
98
+ terminationReason?: string;
99
+ errorDetails?: unknown;
94
100
  createdAt?: Date;
95
101
  terminatedAt?: Date;
96
102
  name?: string;
@@ -117,6 +123,7 @@ interface SnapshotInfo {
117
123
  error?: string;
118
124
  snapshotUri?: string;
119
125
  sizeBytes?: number;
126
+ rootfsDiskBytes?: number;
120
127
  createdAt?: Date;
121
128
  }
122
129
  interface SnapshotOptions {
@@ -357,6 +364,7 @@ interface CreateSandboxImageOptions {
357
364
  registeredName?: string;
358
365
  cpus?: number;
359
366
  memoryMb?: number;
367
+ diskMb?: number;
360
368
  isPublic?: boolean;
361
369
  contextDir?: string;
362
370
  /**
@@ -400,6 +408,7 @@ interface BuildClient {
400
408
  image?: string;
401
409
  cpus?: number;
402
410
  memoryMb?: number;
411
+ diskMb?: number;
403
412
  }): Promise<BuildSandbox>;
404
413
  snapshotAndWait(sandboxId: string, options?: {
405
414
  timeout?: number;
@@ -411,7 +420,7 @@ interface BuildClient {
411
420
  interface CreateSandboxImageDeps {
412
421
  emit?: (event: Record<string, unknown>) => void;
413
422
  createClient?: (context: BuildContext) => BuildClient;
414
- registerImage?: (context: BuildContext, name: string, dockerfile: string, snapshotId: string, snapshotUri: string, isPublic: boolean) => Promise<Record<string, unknown>>;
423
+ registerImage?: (context: BuildContext, name: string, dockerfile: string, snapshotId: string, snapshotSandboxId: string, snapshotUri: string, snapshotSizeBytes: number, rootfsDiskBytes: number, isPublic: boolean) => Promise<Record<string, unknown>>;
415
424
  sleep?: (ms: number) => Promise<void>;
416
425
  }
417
426
  declare function defaultRegisteredName(dockerfilePath: string): string;
@@ -424,4 +433,4 @@ declare function loadImagePlan(image: Image, options?: Pick<CreateSandboxImageOp
424
433
  declare function createSandboxImage(source: SandboxImageSource, options?: CreateSandboxImageOptions, deps?: CreateSandboxImageDeps): Promise<Record<string, unknown>>;
425
434
  declare function runCreateSandboxImageCli(argv?: string[]): Promise<void>;
426
435
 
427
- export { loadDockerfilePlan as $, type DockerfileBuildPlan as A, type DockerfileInstruction as B, type CreatePtySessionOptions as C, type DaemonInfo as D, type ImageBuildOperation as E, ImageBuildOperationType as F, type ImageOptions as G, type HealthResponse as H, Image as I, OutputMode as J, type PoolContainerInfo as K, type ListDirectoryResponse as L, ProcessStatus as M, type NetworkConfig as N, type OutputResponse as O, type ProcessInfo as P, type SandboxImageSource as Q, type RunOptions as R, type SandboxOptions as S, SandboxStatus as T, type UpdateSandboxOptions as U, type SnapshotContentMode as V, SnapshotStatus as W, StdinMode as X, createSandboxImage as Y, dockerfileContent as Z, defaultRegisteredName as _, type CreateAndConnectOptions as a, loadImagePlan as a0, logicalDockerfileLines as a1, runCreateSandboxImageCli as a2, type SandboxClientOptions as b, type ConnectOptions as c, type SnapshotInfo as d, type SuspendResumeOptions as e, type CheckpointOptions as f, type CommandResult as g, type StartProcessOptions as h, type SendSignalResponse as i, type OutputEvent as j, type PtySessionInfo as k, type CreateSandboxOptions as l, type CreateSandboxResponse as m, type SandboxInfo as n, type SandboxPortAccess as o, type SnapshotOptions as p, type CreateSnapshotResponse as q, type SnapshotAndWaitOptions as r, type CreatePoolOptions as s, type CreateSandboxPoolResponse as t, type SandboxPoolInfo as u, type UpdatePoolOptions as v, type ContainerResourcesInfo as w, ContainerState as x, type CreateSandboxImageOptions as y, type DirectoryEntry as z };
436
+ export { loadDockerfilePlan as $, type DirectoryEntry as A, type DockerfileBuildPlan as B, type CreatePtySessionOptions as C, type DaemonInfo as D, type DockerfileInstruction as E, type ImageBuildOperation as F, ImageBuildOperationType as G, type HealthResponse as H, Image as I, type ImageOptions as J, OutputMode as K, type ListDirectoryResponse as L, type PoolContainerInfo as M, type NetworkConfig as N, type OutputResponse as O, type ProcessInfo as P, ProcessStatus as Q, type RunOptions as R, type SandboxOptions as S, type SandboxImageSource as T, type UpdateSandboxOptions as U, type SnapshotContentMode as V, SnapshotStatus as W, StdinMode as X, createSandboxImage as Y, dockerfileContent as Z, defaultRegisteredName as _, type CreateAndConnectOptions as a, loadImagePlan as a0, logicalDockerfileLines as a1, runCreateSandboxImageCli as a2, type SandboxClientOptions as b, type ConnectOptions as c, type SnapshotInfo as d, SandboxStatus as e, type SandboxInfo as f, type SuspendResumeOptions as g, type CheckpointOptions as h, type CommandResult as i, type StartProcessOptions as j, type SendSignalResponse as k, type OutputEvent as l, type PtySessionInfo as m, type CreateSandboxOptions as n, type CreateSandboxResponse as o, type SandboxPortAccess as p, type SnapshotOptions as q, type CreateSnapshotResponse as r, type SnapshotAndWaitOptions as s, type CreatePoolOptions as t, type CreateSandboxPoolResponse as u, type SandboxPoolInfo as v, type UpdatePoolOptions as w, type ContainerResourcesInfo as x, ContainerState as y, type CreateSandboxImageOptions as z };
@@ -54,7 +54,8 @@ interface CreateSandboxOptions {
54
54
  image?: string;
55
55
  cpus?: number;
56
56
  memoryMb?: number;
57
- ephemeralDiskMb?: number;
57
+ /** Root disk size in megabytes. When omitted, the server uses its default disk size. */
58
+ diskMb?: number;
58
59
  secretNames?: string[];
59
60
  timeoutSecs?: number;
60
61
  entrypoint?: string[];
@@ -77,6 +78,9 @@ interface CreateSandboxResponse {
77
78
  sandboxId: string;
78
79
  status: SandboxStatus;
79
80
  routingHint?: string;
81
+ name?: string | null;
82
+ terminationReason?: string;
83
+ errorDetails?: unknown;
80
84
  }
81
85
  interface SandboxInfo {
82
86
  sandboxId: string;
@@ -91,6 +95,8 @@ interface SandboxInfo {
91
95
  network?: NetworkConfig;
92
96
  poolId?: string;
93
97
  outcome?: string;
98
+ terminationReason?: string;
99
+ errorDetails?: unknown;
94
100
  createdAt?: Date;
95
101
  terminatedAt?: Date;
96
102
  name?: string;
@@ -117,6 +123,7 @@ interface SnapshotInfo {
117
123
  error?: string;
118
124
  snapshotUri?: string;
119
125
  sizeBytes?: number;
126
+ rootfsDiskBytes?: number;
120
127
  createdAt?: Date;
121
128
  }
122
129
  interface SnapshotOptions {
@@ -357,6 +364,7 @@ interface CreateSandboxImageOptions {
357
364
  registeredName?: string;
358
365
  cpus?: number;
359
366
  memoryMb?: number;
367
+ diskMb?: number;
360
368
  isPublic?: boolean;
361
369
  contextDir?: string;
362
370
  /**
@@ -400,6 +408,7 @@ interface BuildClient {
400
408
  image?: string;
401
409
  cpus?: number;
402
410
  memoryMb?: number;
411
+ diskMb?: number;
403
412
  }): Promise<BuildSandbox>;
404
413
  snapshotAndWait(sandboxId: string, options?: {
405
414
  timeout?: number;
@@ -411,7 +420,7 @@ interface BuildClient {
411
420
  interface CreateSandboxImageDeps {
412
421
  emit?: (event: Record<string, unknown>) => void;
413
422
  createClient?: (context: BuildContext) => BuildClient;
414
- registerImage?: (context: BuildContext, name: string, dockerfile: string, snapshotId: string, snapshotUri: string, isPublic: boolean) => Promise<Record<string, unknown>>;
423
+ registerImage?: (context: BuildContext, name: string, dockerfile: string, snapshotId: string, snapshotSandboxId: string, snapshotUri: string, snapshotSizeBytes: number, rootfsDiskBytes: number, isPublic: boolean) => Promise<Record<string, unknown>>;
415
424
  sleep?: (ms: number) => Promise<void>;
416
425
  }
417
426
  declare function defaultRegisteredName(dockerfilePath: string): string;
@@ -424,4 +433,4 @@ declare function loadImagePlan(image: Image, options?: Pick<CreateSandboxImageOp
424
433
  declare function createSandboxImage(source: SandboxImageSource, options?: CreateSandboxImageOptions, deps?: CreateSandboxImageDeps): Promise<Record<string, unknown>>;
425
434
  declare function runCreateSandboxImageCli(argv?: string[]): Promise<void>;
426
435
 
427
- export { loadDockerfilePlan as $, type DockerfileBuildPlan as A, type DockerfileInstruction as B, type CreatePtySessionOptions as C, type DaemonInfo as D, type ImageBuildOperation as E, ImageBuildOperationType as F, type ImageOptions as G, type HealthResponse as H, Image as I, OutputMode as J, type PoolContainerInfo as K, type ListDirectoryResponse as L, ProcessStatus as M, type NetworkConfig as N, type OutputResponse as O, type ProcessInfo as P, type SandboxImageSource as Q, type RunOptions as R, type SandboxOptions as S, SandboxStatus as T, type UpdateSandboxOptions as U, type SnapshotContentMode as V, SnapshotStatus as W, StdinMode as X, createSandboxImage as Y, dockerfileContent as Z, defaultRegisteredName as _, type CreateAndConnectOptions as a, loadImagePlan as a0, logicalDockerfileLines as a1, runCreateSandboxImageCli as a2, type SandboxClientOptions as b, type ConnectOptions as c, type SnapshotInfo as d, type SuspendResumeOptions as e, type CheckpointOptions as f, type CommandResult as g, type StartProcessOptions as h, type SendSignalResponse as i, type OutputEvent as j, type PtySessionInfo as k, type CreateSandboxOptions as l, type CreateSandboxResponse as m, type SandboxInfo as n, type SandboxPortAccess as o, type SnapshotOptions as p, type CreateSnapshotResponse as q, type SnapshotAndWaitOptions as r, type CreatePoolOptions as s, type CreateSandboxPoolResponse as t, type SandboxPoolInfo as u, type UpdatePoolOptions as v, type ContainerResourcesInfo as w, ContainerState as x, type CreateSandboxImageOptions as y, type DirectoryEntry as z };
436
+ export { loadDockerfilePlan as $, type DirectoryEntry as A, type DockerfileBuildPlan as B, type CreatePtySessionOptions as C, type DaemonInfo as D, type DockerfileInstruction as E, type ImageBuildOperation as F, ImageBuildOperationType as G, type HealthResponse as H, Image as I, type ImageOptions as J, OutputMode as K, type ListDirectoryResponse as L, type PoolContainerInfo as M, type NetworkConfig as N, type OutputResponse as O, type ProcessInfo as P, ProcessStatus as Q, type RunOptions as R, type SandboxOptions as S, type SandboxImageSource as T, type UpdateSandboxOptions as U, type SnapshotContentMode as V, SnapshotStatus as W, StdinMode as X, createSandboxImage as Y, dockerfileContent as Z, defaultRegisteredName as _, type CreateAndConnectOptions as a, loadImagePlan as a0, logicalDockerfileLines as a1, runCreateSandboxImageCli as a2, type SandboxClientOptions as b, type ConnectOptions as c, type SnapshotInfo as d, SandboxStatus as e, type SandboxInfo as f, type SuspendResumeOptions as g, type CheckpointOptions as h, type CommandResult as i, type StartProcessOptions as j, type SendSignalResponse as k, type OutputEvent as l, type PtySessionInfo as m, type CreateSandboxOptions as n, type CreateSandboxResponse as o, type SandboxPortAccess as p, type SnapshotOptions as q, type CreateSnapshotResponse as r, type SnapshotAndWaitOptions as s, type CreatePoolOptions as t, type CreateSandboxPoolResponse as u, type SandboxPoolInfo as v, type UpdatePoolOptions as w, type ContainerResourcesInfo as x, ContainerState as y, type CreateSandboxImageOptions as z };
@@ -3121,8 +3121,11 @@ var init_sandbox = __esm({
3121
3121
  wsHeaders;
3122
3122
  ownsSandbox = false;
3123
3123
  lifecycleClient = null;
3124
+ lifecycleIdentifier;
3125
+ sandboxName = null;
3124
3126
  constructor(options) {
3125
3127
  this.sandboxId = options.sandboxId;
3128
+ this.lifecycleIdentifier = options.sandboxId;
3126
3129
  const proxyUrl = options.proxyUrl ?? SANDBOX_PROXY_URL;
3127
3130
  const { baseUrl, hostHeader } = resolveProxyTarget(proxyUrl, options.sandboxId);
3128
3131
  this.baseUrl = baseUrl;
@@ -3148,6 +3151,17 @@ var init_sandbox = __esm({
3148
3151
  routingHint: options.routingHint
3149
3152
  });
3150
3153
  }
3154
+ get name() {
3155
+ return this.sandboxName;
3156
+ }
3157
+ /** @internal Used by client wiring to keep locally cached name in sync. */
3158
+ _setName(name) {
3159
+ this.sandboxName = name;
3160
+ }
3161
+ /** @internal Used by lifecycle operations to pin to canonical sandbox ID. */
3162
+ _setLifecycleIdentifier(identifier) {
3163
+ this.lifecycleIdentifier = identifier;
3164
+ }
3151
3165
  /** @internal Used by SandboxClient.createAndConnect to set ownership. */
3152
3166
  _setOwner(client) {
3153
3167
  this.ownsSandbox = true;
@@ -3185,9 +3199,15 @@ var init_sandbox = __esm({
3185
3199
  /* _internal */
3186
3200
  true
3187
3201
  );
3188
- await client.get(options.sandboxId);
3189
- const sandbox = client.connect(options.sandboxId, options.proxyUrl, options.routingHint);
3202
+ const info = await client.get(options.sandboxId);
3203
+ const sandbox = client.connect(
3204
+ info.sandboxId,
3205
+ options.proxyUrl,
3206
+ options.routingHint ?? info.routingHint
3207
+ );
3190
3208
  sandbox.lifecycleClient = client;
3209
+ sandbox._setLifecycleIdentifier(info.sandboxId);
3210
+ sandbox._setName(info.name ?? null);
3191
3211
  return sandbox;
3192
3212
  }
3193
3213
  // --- Static snapshot management ---
@@ -3220,6 +3240,32 @@ var init_sandbox = __esm({
3220
3240
  }
3221
3241
  return this.lifecycleClient;
3222
3242
  }
3243
+ /**
3244
+ * Fetch the current sandbox status from the server.
3245
+ *
3246
+ * Always hits the network — the value is not cached locally because the
3247
+ * status changes over the sandbox's lifecycle.
3248
+ */
3249
+ async status() {
3250
+ const client = this.requireLifecycleClient("read_status");
3251
+ const info = await client.get(this.lifecycleIdentifier);
3252
+ this._setLifecycleIdentifier(info.sandboxId);
3253
+ this._setName(info.name ?? null);
3254
+ return info.status;
3255
+ }
3256
+ /**
3257
+ * Update this sandbox's properties (name, exposed ports, proxy auth).
3258
+ *
3259
+ * Naming an ephemeral sandbox makes it non-ephemeral and enables
3260
+ * suspend/resume.
3261
+ */
3262
+ async update(options) {
3263
+ const client = this.requireLifecycleClient("update");
3264
+ const info = await client.update(this.lifecycleIdentifier, options);
3265
+ this._setLifecycleIdentifier(info.sandboxId);
3266
+ this._setName(info.name ?? null);
3267
+ return info;
3268
+ }
3223
3269
  /**
3224
3270
  * Suspend this sandbox.
3225
3271
  *
@@ -3228,7 +3274,7 @@ var init_sandbox = __esm({
3228
3274
  */
3229
3275
  async suspend(options) {
3230
3276
  const client = this.requireLifecycleClient("suspend");
3231
- await client.suspend(this.sandboxId, options);
3277
+ await client.suspend(this.lifecycleIdentifier, options);
3232
3278
  }
3233
3279
  /**
3234
3280
  * Resume this sandbox.
@@ -3238,7 +3284,7 @@ var init_sandbox = __esm({
3238
3284
  */
3239
3285
  async resume(options) {
3240
3286
  const client = this.requireLifecycleClient("resume");
3241
- await client.resume(this.sandboxId, options);
3287
+ await client.resume(this.lifecycleIdentifier, options);
3242
3288
  }
3243
3289
  /**
3244
3290
  * Create a snapshot of this sandbox's filesystem and wait for it to
@@ -3251,10 +3297,10 @@ var init_sandbox = __esm({
3251
3297
  async checkpoint(options) {
3252
3298
  const client = this.requireLifecycleClient("checkpoint");
3253
3299
  if (options?.wait === false) {
3254
- await client.snapshot(this.sandboxId, { contentMode: options.contentMode });
3300
+ await client.snapshot(this.lifecycleIdentifier, { contentMode: options.contentMode });
3255
3301
  return void 0;
3256
3302
  }
3257
- return client.snapshotAndWait(this.sandboxId, {
3303
+ return client.snapshotAndWait(this.lifecycleIdentifier, {
3258
3304
  timeout: options?.timeout,
3259
3305
  pollInterval: options?.pollInterval,
3260
3306
  contentMode: options?.contentMode
@@ -3266,7 +3312,8 @@ var init_sandbox = __esm({
3266
3312
  async listSnapshots() {
3267
3313
  const client = this.requireLifecycleClient("listSnapshots");
3268
3314
  const all = await client.listSnapshots();
3269
- return all.filter((s) => s.sandboxId === this.sandboxId);
3315
+ const filtered = all.filter((s) => s.sandboxId === this.lifecycleIdentifier);
3316
+ return Object.assign(filtered, { traceId: all.traceId });
3270
3317
  }
3271
3318
  /** Close the HTTP client. The sandbox keeps running. */
3272
3319
  close() {
@@ -3279,7 +3326,7 @@ var init_sandbox = __esm({
3279
3326
  this.lifecycleClient = null;
3280
3327
  this.close();
3281
3328
  if (client) {
3282
- await client.delete(this.sandboxId);
3329
+ await client.delete(this.lifecycleIdentifier);
3283
3330
  }
3284
3331
  }
3285
3332
  // --- High-level convenience ---
@@ -3360,7 +3407,8 @@ var init_sandbox = __esm({
3360
3407
  "GET",
3361
3408
  "/api/v1/processes"
3362
3409
  );
3363
- return (raw.processes ?? []).map((p) => fromSnakeKeys(p));
3410
+ const processes = (raw.processes ?? []).map((p) => fromSnakeKeys(p));
3411
+ return Object.assign(processes, { traceId: raw.traceId });
3364
3412
  }
3365
3413
  /** Get current status and metadata for a process by PID. */
3366
3414
  async getProcess(pid) {
@@ -3612,6 +3660,38 @@ __export(client_exports, {
3612
3660
  function sleep2(ms) {
3613
3661
  return new Promise((resolve) => setTimeout(resolve, ms));
3614
3662
  }
3663
+ function formatStartupFailureMessage(sandboxId, status, options) {
3664
+ const prefix = status === "terminated" /* TERMINATED */ ? `Sandbox ${sandboxId} terminated during startup` : `Sandbox ${sandboxId} became ${status} during startup`;
3665
+ const detail = formatErrorDetails(options.errorDetails);
3666
+ if (detail) {
3667
+ return `${prefix}: ${detail}`;
3668
+ }
3669
+ if (options.terminationReason) {
3670
+ return `${prefix}: termination reason: ${options.terminationReason}`;
3671
+ }
3672
+ return prefix;
3673
+ }
3674
+ function formatErrorDetails(errorDetails) {
3675
+ if (errorDetails == null) return void 0;
3676
+ if (typeof errorDetails === "string") {
3677
+ const detail = errorDetails.trim();
3678
+ return detail || void 0;
3679
+ }
3680
+ if (Array.isArray(errorDetails)) {
3681
+ const parts = errorDetails.map((item) => formatErrorDetails(item)).filter((item) => Boolean(item));
3682
+ return parts.length > 0 ? parts.join("; ") : JSON.stringify(errorDetails);
3683
+ }
3684
+ if (typeof errorDetails === "object") {
3685
+ for (const key of ["message", "detail", "error", "reason"]) {
3686
+ const value = errorDetails[key];
3687
+ if (typeof value === "string" && value.trim()) {
3688
+ return value.trim();
3689
+ }
3690
+ }
3691
+ return JSON.stringify(errorDetails);
3692
+ }
3693
+ return String(errorDetails);
3694
+ }
3615
3695
  function normalizeUserPorts(ports) {
3616
3696
  return dedupeAndSortPorts(ports.map(validateUserPort));
3617
3697
  }
@@ -3697,7 +3777,7 @@ var init_client = __esm({
3697
3777
  resources: {
3698
3778
  cpus: options?.cpus ?? 1,
3699
3779
  memory_mb: options?.memoryMb ?? 1024,
3700
- ephemeral_disk_mb: options?.ephemeralDiskMb ?? 1024
3780
+ ...options?.diskMb != null ? { disk_mb: options.diskMb } : {}
3701
3781
  }
3702
3782
  };
3703
3783
  if (options?.image != null) body.image = options.image;
@@ -3735,9 +3815,10 @@ var init_client = __esm({
3735
3815
  "GET",
3736
3816
  this.path("sandboxes")
3737
3817
  );
3738
- return (raw.sandboxes ?? []).map(
3818
+ const sandboxes = (raw.sandboxes ?? []).map(
3739
3819
  (s) => fromSnakeKeys(s, "sandboxId")
3740
3820
  );
3821
+ return Object.assign(sandboxes, { traceId: raw.traceId });
3741
3822
  }
3742
3823
  /** Update sandbox properties such as name, exposed ports, and proxy auth settings. */
3743
3824
  async update(sandboxId, options) {
@@ -3907,9 +3988,10 @@ var init_client = __esm({
3907
3988
  "GET",
3908
3989
  this.path("snapshots")
3909
3990
  );
3910
- return (raw.snapshots ?? []).map(
3991
+ const snapshots = (raw.snapshots ?? []).map(
3911
3992
  (s) => fromSnakeKeys(s, "snapshotId")
3912
3993
  );
3994
+ return Object.assign(snapshots, { traceId: raw.traceId });
3913
3995
  }
3914
3996
  /** Delete a snapshot by ID. */
3915
3997
  async deleteSnapshot(snapshotId) {
@@ -3989,9 +4071,10 @@ var init_client = __esm({
3989
4071
  "GET",
3990
4072
  this.path("sandbox-pools")
3991
4073
  );
3992
- return (raw.pools ?? []).map(
4074
+ const pools = (raw.pools ?? []).map(
3993
4075
  (p) => fromSnakeKeys(p, "poolId")
3994
4076
  );
4077
+ return Object.assign(pools, { traceId: raw.traceId });
3995
4078
  }
3996
4079
  /** Replace the configuration of an existing sandbox pool. */
3997
4080
  async updatePool(poolId, options) {
@@ -4046,30 +4129,39 @@ var init_client = __esm({
4046
4129
  */
4047
4130
  async createAndConnect(options) {
4048
4131
  const startupTimeout = options?.startupTimeout ?? 60;
4049
- let result;
4050
- if (options?.poolId != null) {
4051
- result = await this.claim(options.poolId);
4052
- } else {
4053
- result = await this.create(options);
4054
- }
4055
- if (result.status === "running" /* RUNNING */) {
4056
- const sandbox = this.connect(result.sandboxId, options?.proxyUrl, result.routingHint);
4132
+ const result = options?.poolId != null ? await this.claim(options.poolId) : await this.create(options);
4133
+ const requestedName = options?.poolId != null ? null : options?.name ?? null;
4134
+ const finishConnect = (routingHint, name) => {
4135
+ const sandbox = this.connect(result.sandboxId, options?.proxyUrl, routingHint);
4057
4136
  sandbox._setOwner(this);
4058
4137
  sandbox.traceId = result.traceId;
4138
+ sandbox._setLifecycleIdentifier(result.sandboxId);
4139
+ sandbox._setName(name ?? requestedName);
4059
4140
  return sandbox;
4141
+ };
4142
+ if (result.status === "running" /* RUNNING */) {
4143
+ return finishConnect(result.routingHint, result.name);
4144
+ }
4145
+ if (result.status === "suspended" /* SUSPENDED */ || result.status === "terminated" /* TERMINATED */) {
4146
+ throw new SandboxError(
4147
+ formatStartupFailureMessage(result.sandboxId, result.status, {
4148
+ errorDetails: result.errorDetails,
4149
+ terminationReason: result.terminationReason
4150
+ })
4151
+ );
4060
4152
  }
4061
4153
  const deadline = Date.now() + startupTimeout * 1e3;
4062
4154
  while (Date.now() < deadline) {
4063
4155
  const info = await this.get(result.sandboxId);
4064
4156
  if (info.status === "running" /* RUNNING */) {
4065
- const sandbox = this.connect(result.sandboxId, options?.proxyUrl, info.routingHint);
4066
- sandbox._setOwner(this);
4067
- sandbox.traceId = result.traceId;
4068
- return sandbox;
4157
+ return finishConnect(info.routingHint, info.name);
4069
4158
  }
4070
- if (info.status === "terminated" /* TERMINATED */) {
4159
+ if (info.status === "suspended" /* SUSPENDED */ || info.status === "terminated" /* TERMINATED */) {
4071
4160
  throw new SandboxError(
4072
- `Sandbox ${result.sandboxId} terminated during startup`
4161
+ formatStartupFailureMessage(result.sandboxId, info.status, {
4162
+ errorDetails: info.errorDetails,
4163
+ terminationReason: info.terminationReason
4164
+ })
4073
4165
  );
4074
4166
  }
4075
4167
  await sleep2(500);
@@ -4753,7 +4845,7 @@ async function executeDockerfilePlan(sandbox, plan, emit, sleep3) {
4753
4845
  );
4754
4846
  }
4755
4847
  }
4756
- async function registerImage(context, name, dockerfile, snapshotId, snapshotUri, isPublic) {
4848
+ async function registerImage(context, name, dockerfile, snapshotId, snapshotSandboxId, snapshotUri, snapshotSizeBytes, rootfsDiskBytes, isPublic) {
4757
4849
  if (!context.organizationId || !context.projectId) {
4758
4850
  throw new Error(
4759
4851
  "Organization ID and Project ID are required. Run 'tl login' and 'tl init'."
@@ -4780,8 +4872,11 @@ async function registerImage(context, name, dockerfile, snapshotId, snapshotUri,
4780
4872
  name,
4781
4873
  dockerfile,
4782
4874
  snapshotId,
4875
+ snapshotSandboxId,
4783
4876
  snapshotUri,
4784
- isPublic
4877
+ snapshotSizeBytes,
4878
+ rootfsDiskBytes,
4879
+ public: isPublic
4785
4880
  })
4786
4881
  });
4787
4882
  if (!response.ok) {
@@ -4811,7 +4906,8 @@ async function createSandboxImage(source, options = {}, deps = {}) {
4811
4906
  sandbox = await client.createAndConnect({
4812
4907
  ...plan.baseImage == null ? {} : { image: plan.baseImage },
4813
4908
  cpus: options.cpus ?? 2,
4814
- memoryMb: options.memoryMb ?? 4096
4909
+ memoryMb: options.memoryMb ?? 4096,
4910
+ ...options.diskMb != null ? { diskMb: options.diskMb } : {}
4815
4911
  });
4816
4912
  emit({
4817
4913
  type: "status",
@@ -4824,14 +4920,23 @@ async function createSandboxImage(source, options = {}, deps = {}) {
4824
4920
  });
4825
4921
  emit({
4826
4922
  type: "snapshot_created",
4827
- snapshot_id: snapshot.snapshotId,
4828
- snapshot_uri: snapshot.snapshotUri ?? null
4923
+ snapshot_id: snapshot.snapshotId
4829
4924
  });
4830
4925
  if (!snapshot.snapshotUri) {
4831
4926
  throw new Error(
4832
4927
  `Snapshot ${snapshot.snapshotId} is missing snapshotUri and cannot be registered as a sandbox image.`
4833
4928
  );
4834
4929
  }
4930
+ if (snapshot.sizeBytes == null) {
4931
+ throw new Error(
4932
+ `Snapshot ${snapshot.snapshotId} is missing sizeBytes and cannot be registered as a sandbox image.`
4933
+ );
4934
+ }
4935
+ if (snapshot.rootfsDiskBytes == null) {
4936
+ throw new Error(
4937
+ `Snapshot ${snapshot.snapshotId} is missing rootfsDiskBytes and cannot be registered as a sandbox image.`
4938
+ );
4939
+ }
4835
4940
  emit({
4836
4941
  type: "status",
4837
4942
  message: `Registering image '${plan.registeredName}'...`
@@ -4841,7 +4946,10 @@ async function createSandboxImage(source, options = {}, deps = {}) {
4841
4946
  plan.registeredName,
4842
4947
  plan.dockerfileText,
4843
4948
  snapshot.snapshotId,
4949
+ snapshot.sandboxId,
4844
4950
  snapshot.snapshotUri,
4951
+ snapshot.sizeBytes,
4952
+ snapshot.rootfsDiskBytes,
4845
4953
  options.isPublic ?? false
4846
4954
  );
4847
4955
  emit({
@@ -4869,27 +4977,33 @@ async function runCreateSandboxImageCli(argv = process.argv.slice(2)) {
4869
4977
  name: { type: "string", short: "n" },
4870
4978
  cpus: { type: "string" },
4871
4979
  memory: { type: "string" },
4980
+ disk: { type: "string" },
4872
4981
  public: { type: "boolean", default: false }
4873
4982
  }
4874
4983
  });
4875
4984
  const dockerfilePath = parsed.positionals[0];
4876
4985
  if (!dockerfilePath) {
4877
- throw new Error("Usage: tensorlake-create-sandbox-image <dockerfile_path> [--name NAME] [--cpus N] [--memory MB] [--public]");
4986
+ throw new Error("Usage: tensorlake-create-sandbox-image <dockerfile_path> [--name NAME] [--cpus N] [--memory MB] [--disk GB] [--public]");
4878
4987
  }
4879
4988
  const cpus = parsed.values.cpus != null ? Number(parsed.values.cpus) : void 0;
4880
4989
  const memoryMb = parsed.values.memory != null ? Number(parsed.values.memory) : void 0;
4990
+ const diskGb = parsed.values.disk != null ? Number(parsed.values.disk) : void 0;
4881
4991
  if (cpus != null && !Number.isFinite(cpus)) {
4882
4992
  throw new Error(`Invalid --cpus value: ${parsed.values.cpus}`);
4883
4993
  }
4884
4994
  if (memoryMb != null && !Number.isInteger(memoryMb)) {
4885
4995
  throw new Error(`Invalid --memory value: ${parsed.values.memory}`);
4886
4996
  }
4997
+ if (diskGb != null && !Number.isInteger(diskGb)) {
4998
+ throw new Error(`Invalid --disk value: ${parsed.values.disk}`);
4999
+ }
4887
5000
  await createSandboxImage(
4888
5001
  dockerfilePath,
4889
5002
  {
4890
5003
  registeredName: parsed.values.name,
4891
5004
  cpus,
4892
5005
  memoryMb,
5006
+ diskMb: diskGb != null ? diskGb * 1024 : void 0,
4893
5007
  isPublic: parsed.values.public
4894
5008
  },
4895
5009
  { emit: ndjsonStdoutEmit }