tensorlake 0.4.45 → 0.4.47

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.
@@ -1 +1 @@
1
- export { v as CreateSandboxImageOptions, x as DockerfileBuildPlan, y as DockerfileInstruction, J as SandboxImageSource, V as createSandboxImage, X as defaultRegisteredName, Y as loadDockerfilePlan, Z as loadImagePlan, _ as logicalDockerfileLines, $ as runCreateSandboxImageCli } from './sandbox-image-B5Fa0xqb.cjs';
1
+ export { v as CreateSandboxImageOptions, x as DockerfileBuildPlan, y as DockerfileInstruction, J as SandboxImageSource, V as createSandboxImage, X as defaultRegisteredName, Y as loadDockerfilePlan, Z as loadImagePlan, _ as logicalDockerfileLines, $ as runCreateSandboxImageCli } from './sandbox-image-B130uMYt.cjs';
@@ -1 +1 @@
1
- export { v as CreateSandboxImageOptions, x as DockerfileBuildPlan, y as DockerfileInstruction, J as SandboxImageSource, V as createSandboxImage, X as defaultRegisteredName, Y as loadDockerfilePlan, Z as loadImagePlan, _ as logicalDockerfileLines, $ as runCreateSandboxImageCli } from './sandbox-image-B5Fa0xqb.js';
1
+ export { v as CreateSandboxImageOptions, x as DockerfileBuildPlan, y as DockerfileInstruction, J as SandboxImageSource, V as createSandboxImage, X as defaultRegisteredName, Y as loadDockerfilePlan, Z as loadImagePlan, _ as logicalDockerfileLines, $ as runCreateSandboxImageCli } from './sandbox-image-B130uMYt.js';
@@ -138,6 +138,9 @@ var HttpClient = class {
138
138
  if (options.hostHeader) {
139
139
  this.headers["Host"] = options.hostHeader;
140
140
  }
141
+ if (options.routingHint) {
142
+ this.headers["X-Tensorlake-Route-Hint"] = options.routingHint;
143
+ }
141
144
  }
142
145
  close() {
143
146
  this.abortController?.abort();
@@ -172,12 +175,13 @@ var HttpClient = class {
172
175
  const buffer = await response.arrayBuffer();
173
176
  return new Uint8Array(buffer);
174
177
  }
175
- /** Make a request and return the raw Response (for SSE streaming). */
178
+ /** Make a request and return the response body as an SSE stream. */
176
179
  async requestStream(method, path2, options) {
177
180
  const response = await this.requestResponse(
178
181
  method,
179
182
  path2,
180
183
  {
184
+ json: options?.json,
181
185
  headers: { Accept: "text/event-stream" },
182
186
  signal: options?.signal
183
187
  }
@@ -3031,7 +3035,8 @@ var Sandbox = class {
3031
3035
  apiKey: options.apiKey,
3032
3036
  organizationId: options.organizationId,
3033
3037
  projectId: options.projectId,
3034
- hostHeader
3038
+ hostHeader,
3039
+ routingHint: options.routingHint
3035
3040
  });
3036
3041
  }
3037
3042
  /** @internal Used by SandboxClient.createAndConnect to set ownership. */
@@ -3052,37 +3057,45 @@ var Sandbox = class {
3052
3057
  }
3053
3058
  }
3054
3059
  // --- High-level convenience ---
3060
+ /**
3061
+ * Run a command to completion and return its output.
3062
+ *
3063
+ * Uses a single streaming `POST /api/v1/processes/run` request that starts
3064
+ * the process, streams output, and delivers the exit code over one connection.
3065
+ */
3055
3066
  async run(command, options) {
3056
- const proc = await this.startProcess(command, {
3057
- args: options?.args,
3058
- env: options?.env,
3059
- workingDir: options?.workingDir
3060
- });
3061
- const deadline = options?.timeout ? Date.now() + options.timeout * 1e3 : null;
3062
- let info;
3063
- while (true) {
3064
- info = await this.getProcess(proc.pid);
3065
- if (info.status !== "running" /* RUNNING */) break;
3066
- if (deadline && Date.now() > deadline) {
3067
- await this.killProcess(proc.pid);
3068
- throw new SandboxError(`Command timed out after ${options.timeout}s`);
3067
+ const body = { command };
3068
+ if (options?.args) body.args = options.args;
3069
+ if (options?.env) body.env = options.env;
3070
+ if (options?.workingDir) body.working_dir = options.workingDir;
3071
+ if (options?.timeout != null) body.timeout = options.timeout;
3072
+ const sseStream = await this.http.requestStream(
3073
+ "POST",
3074
+ "/api/v1/processes/run",
3075
+ { json: body }
3076
+ );
3077
+ const stdoutLines = [];
3078
+ const stderrLines = [];
3079
+ let exitCode = -1;
3080
+ for await (const raw of parseSSEStream(sseStream)) {
3081
+ if (typeof raw.line === "string") {
3082
+ if (raw.stream === "stderr") {
3083
+ stderrLines.push(raw.line);
3084
+ } else {
3085
+ stdoutLines.push(raw.line);
3086
+ }
3087
+ } else if ("exit_code" in raw || "signal" in raw) {
3088
+ if (typeof raw.exit_code === "number") {
3089
+ exitCode = raw.exit_code;
3090
+ } else if (typeof raw.signal === "number") {
3091
+ exitCode = -raw.signal;
3092
+ }
3069
3093
  }
3070
- await sleep2(100);
3071
- }
3072
- const stdoutResp = await this.getStdout(proc.pid);
3073
- const stderrResp = await this.getStderr(proc.pid);
3074
- let exitCode;
3075
- if (info.exitCode != null) {
3076
- exitCode = info.exitCode;
3077
- } else if (info.signal != null) {
3078
- exitCode = -info.signal;
3079
- } else {
3080
- exitCode = -1;
3081
3094
  }
3082
3095
  return {
3083
3096
  exitCode,
3084
- stdout: stdoutResp.lines.join("\n"),
3085
- stderr: stderrResp.lines.join("\n")
3097
+ stdout: stdoutLines.join("\n"),
3098
+ stderr: stderrLines.join("\n")
3086
3099
  };
3087
3100
  }
3088
3101
  // --- Process management ---
@@ -3331,9 +3344,6 @@ var Sandbox = class {
3331
3344
  return fromSnakeKeys(raw);
3332
3345
  }
3333
3346
  };
3334
- function sleep2(ms) {
3335
- return new Promise((resolve) => setTimeout(resolve, ms));
3336
- }
3337
3347
 
3338
3348
  // src/client.ts
3339
3349
  var SandboxClient = class _SandboxClient {
@@ -3549,7 +3559,7 @@ var SandboxClient = class _SandboxClient {
3549
3559
  `Snapshot ${result.snapshotId} failed: ${info.error}`
3550
3560
  );
3551
3561
  }
3552
- await sleep3(pollInterval * 1e3);
3562
+ await sleep2(pollInterval * 1e3);
3553
3563
  }
3554
3564
  throw new SandboxError(
3555
3565
  `Snapshot ${result.snapshotId} did not complete within ${timeout}s`
@@ -3621,14 +3631,15 @@ var SandboxClient = class _SandboxClient {
3621
3631
  );
3622
3632
  }
3623
3633
  // --- Connect ---
3624
- connect(identifier, proxyUrl) {
3634
+ connect(identifier, proxyUrl, routingHint) {
3625
3635
  const resolvedProxy = proxyUrl ?? resolveProxyUrl(this.apiUrl);
3626
3636
  return new Sandbox({
3627
3637
  sandboxId: identifier,
3628
3638
  proxyUrl: resolvedProxy,
3629
3639
  apiKey: this.apiKey,
3630
3640
  organizationId: this.organizationId,
3631
- projectId: this.projectId
3641
+ projectId: this.projectId,
3642
+ routingHint
3632
3643
  });
3633
3644
  }
3634
3645
  async createAndConnect(options) {
@@ -3639,6 +3650,11 @@ var SandboxClient = class _SandboxClient {
3639
3650
  } else {
3640
3651
  result = await this.create(options);
3641
3652
  }
3653
+ if (result.status === "running" /* RUNNING */) {
3654
+ const sandbox = this.connect(result.sandboxId, options?.proxyUrl, result.routingHint);
3655
+ sandbox._setOwner(this);
3656
+ return sandbox;
3657
+ }
3642
3658
  const deadline = Date.now() + startupTimeout * 1e3;
3643
3659
  while (Date.now() < deadline) {
3644
3660
  const info = await this.get(result.sandboxId);
@@ -3652,7 +3668,7 @@ var SandboxClient = class _SandboxClient {
3652
3668
  `Sandbox ${result.sandboxId} terminated during startup`
3653
3669
  );
3654
3670
  }
3655
- await sleep3(500);
3671
+ await sleep2(500);
3656
3672
  }
3657
3673
  try {
3658
3674
  await this.delete(result.sandboxId);
@@ -3663,7 +3679,7 @@ var SandboxClient = class _SandboxClient {
3663
3679
  );
3664
3680
  }
3665
3681
  };
3666
- function sleep3(ms) {
3682
+ function sleep2(ms) {
3667
3683
  return new Promise((resolve) => setTimeout(resolve, ms));
3668
3684
  }
3669
3685
  var RESERVED_SANDBOX_MANAGEMENT_PORT = 9501;
@@ -4086,7 +4102,7 @@ async function runChecked(sandbox, command, args, env, workingDir) {
4086
4102
  }
4087
4103
  return result;
4088
4104
  }
4089
- async function runStreaming(sandbox, emit, sleep4, command, args = [], env, workingDir) {
4105
+ async function runStreaming(sandbox, emit, sleep3, command, args = [], env, workingDir) {
4090
4106
  const proc = await sandbox.startProcess(command, {
4091
4107
  args,
4092
4108
  env,
@@ -4111,13 +4127,13 @@ async function runStreaming(sandbox, emit, sleep4, command, args = [], env, work
4111
4127
  emitOutputLines(emit, "stderr", finalStderr, stderrSeen);
4112
4128
  break;
4113
4129
  }
4114
- await sleep4(300);
4130
+ await sleep3(300);
4115
4131
  }
4116
4132
  for (let i = 0; i < 10; i++) {
4117
4133
  if (info.exitCode != null || info.signal != null) {
4118
4134
  break;
4119
4135
  }
4120
- await sleep4(200);
4136
+ await sleep3(200);
4121
4137
  info = await sandbox.getProcess(proc.pid);
4122
4138
  }
4123
4139
  const exitCode = info.exitCode != null ? info.exitCode : info.signal != null ? -info.signal : 0;
@@ -4215,7 +4231,7 @@ async function copyFromContext(sandbox, emit, contextDir, sources, destination,
4215
4231
  await copyLocalPathToSandbox(sandbox, localSource, remoteDestination);
4216
4232
  }
4217
4233
  }
4218
- async function addUrlToSandbox(sandbox, emit, url, destination, workingDir, processEnv, sleep4) {
4234
+ async function addUrlToSandbox(sandbox, emit, url, destination, workingDir, processEnv, sleep3) {
4219
4235
  let destinationPath = resolveContainerPath(destination, workingDir);
4220
4236
  const parsedUrl = new URL(url);
4221
4237
  const fileName = path.posix.basename(parsedUrl.pathname.replace(/\/$/, "")) || "downloaded";
@@ -4231,7 +4247,7 @@ async function addUrlToSandbox(sandbox, emit, url, destination, workingDir, proc
4231
4247
  await runStreaming(
4232
4248
  sandbox,
4233
4249
  emit,
4234
- sleep4,
4250
+ sleep3,
4235
4251
  "sh",
4236
4252
  [
4237
4253
  "-c",
@@ -4241,7 +4257,7 @@ async function addUrlToSandbox(sandbox, emit, url, destination, workingDir, proc
4241
4257
  workingDir
4242
4258
  );
4243
4259
  }
4244
- async function executeDockerfilePlan(sandbox, plan, emit, sleep4) {
4260
+ async function executeDockerfilePlan(sandbox, plan, emit, sleep3) {
4245
4261
  const processEnv = { ...BUILD_SANDBOX_PIP_ENV };
4246
4262
  let workingDir = "/";
4247
4263
  for (const instruction of plan.instructions) {
@@ -4251,7 +4267,7 @@ async function executeDockerfilePlan(sandbox, plan, emit, sleep4) {
4251
4267
  await runStreaming(
4252
4268
  sandbox,
4253
4269
  emit,
4254
- sleep4,
4270
+ sleep3,
4255
4271
  "sh",
4256
4272
  ["-c", value],
4257
4273
  processEnv,
@@ -4308,7 +4324,7 @@ async function executeDockerfilePlan(sandbox, plan, emit, sleep4) {
4308
4324
  destination,
4309
4325
  workingDir,
4310
4326
  processEnv,
4311
- sleep4
4327
+ sleep3
4312
4328
  );
4313
4329
  } else {
4314
4330
  await copyFromContext(
@@ -4376,7 +4392,7 @@ async function registerImage(context, name, dockerfile, snapshotId, snapshotUri,
4376
4392
  }
4377
4393
  async function createSandboxImage(source, options = {}, deps = {}) {
4378
4394
  const emit = deps.emit ?? defaultEmit;
4379
- const sleep4 = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
4395
+ const sleep3 = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
4380
4396
  const context = buildContextFromEnv();
4381
4397
  const clientFactory = deps.createClient ?? createDefaultClient;
4382
4398
  const register = deps.registerImage ?? ((...args) => registerImage(...args));
@@ -4399,7 +4415,7 @@ async function createSandboxImage(source, options = {}, deps = {}) {
4399
4415
  type: "status",
4400
4416
  message: `Materializing image in sandbox ${sandbox.sandboxId}...`
4401
4417
  });
4402
- await executeDockerfilePlan(sandbox, plan, emit, sleep4);
4418
+ await executeDockerfilePlan(sandbox, plan, emit, sleep3);
4403
4419
  emit({ type: "status", message: "Creating snapshot..." });
4404
4420
  const snapshot = await client.snapshotAndWait(sandbox.sandboxId, {
4405
4421
  contentMode: "filesystem_only"