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.
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/dist/index.cjs CHANGED
@@ -176,6 +176,9 @@ var HttpClient = class {
176
176
  if (options.hostHeader) {
177
177
  this.headers["Host"] = options.hostHeader;
178
178
  }
179
+ if (options.routingHint) {
180
+ this.headers["X-Tensorlake-Route-Hint"] = options.routingHint;
181
+ }
179
182
  }
180
183
  close() {
181
184
  this.abortController?.abort();
@@ -210,12 +213,13 @@ var HttpClient = class {
210
213
  const buffer = await response.arrayBuffer();
211
214
  return new Uint8Array(buffer);
212
215
  }
213
- /** Make a request and return the raw Response (for SSE streaming). */
216
+ /** Make a request and return the response body as an SSE stream. */
214
217
  async requestStream(method, path2, options) {
215
218
  const response = await this.requestResponse(
216
219
  method,
217
220
  path2,
218
221
  {
222
+ json: options?.json,
219
223
  headers: { Accept: "text/event-stream" },
220
224
  signal: options?.signal
221
225
  }
@@ -3148,7 +3152,8 @@ var Sandbox = class {
3148
3152
  apiKey: options.apiKey,
3149
3153
  organizationId: options.organizationId,
3150
3154
  projectId: options.projectId,
3151
- hostHeader
3155
+ hostHeader,
3156
+ routingHint: options.routingHint
3152
3157
  });
3153
3158
  }
3154
3159
  /** @internal Used by SandboxClient.createAndConnect to set ownership. */
@@ -3169,37 +3174,45 @@ var Sandbox = class {
3169
3174
  }
3170
3175
  }
3171
3176
  // --- High-level convenience ---
3177
+ /**
3178
+ * Run a command to completion and return its output.
3179
+ *
3180
+ * Uses a single streaming `POST /api/v1/processes/run` request that starts
3181
+ * the process, streams output, and delivers the exit code over one connection.
3182
+ */
3172
3183
  async run(command, options) {
3173
- const proc = await this.startProcess(command, {
3174
- args: options?.args,
3175
- env: options?.env,
3176
- workingDir: options?.workingDir
3177
- });
3178
- const deadline = options?.timeout ? Date.now() + options.timeout * 1e3 : null;
3179
- let info;
3180
- while (true) {
3181
- info = await this.getProcess(proc.pid);
3182
- if (info.status !== "running" /* RUNNING */) break;
3183
- if (deadline && Date.now() > deadline) {
3184
- await this.killProcess(proc.pid);
3185
- throw new SandboxError(`Command timed out after ${options.timeout}s`);
3184
+ const body = { command };
3185
+ if (options?.args) body.args = options.args;
3186
+ if (options?.env) body.env = options.env;
3187
+ if (options?.workingDir) body.working_dir = options.workingDir;
3188
+ if (options?.timeout != null) body.timeout = options.timeout;
3189
+ const sseStream = await this.http.requestStream(
3190
+ "POST",
3191
+ "/api/v1/processes/run",
3192
+ { json: body }
3193
+ );
3194
+ const stdoutLines = [];
3195
+ const stderrLines = [];
3196
+ let exitCode = -1;
3197
+ for await (const raw of parseSSEStream(sseStream)) {
3198
+ if (typeof raw.line === "string") {
3199
+ if (raw.stream === "stderr") {
3200
+ stderrLines.push(raw.line);
3201
+ } else {
3202
+ stdoutLines.push(raw.line);
3203
+ }
3204
+ } else if ("exit_code" in raw || "signal" in raw) {
3205
+ if (typeof raw.exit_code === "number") {
3206
+ exitCode = raw.exit_code;
3207
+ } else if (typeof raw.signal === "number") {
3208
+ exitCode = -raw.signal;
3209
+ }
3186
3210
  }
3187
- await sleep2(100);
3188
- }
3189
- const stdoutResp = await this.getStdout(proc.pid);
3190
- const stderrResp = await this.getStderr(proc.pid);
3191
- let exitCode;
3192
- if (info.exitCode != null) {
3193
- exitCode = info.exitCode;
3194
- } else if (info.signal != null) {
3195
- exitCode = -info.signal;
3196
- } else {
3197
- exitCode = -1;
3198
3211
  }
3199
3212
  return {
3200
3213
  exitCode,
3201
- stdout: stdoutResp.lines.join("\n"),
3202
- stderr: stderrResp.lines.join("\n")
3214
+ stdout: stdoutLines.join("\n"),
3215
+ stderr: stderrLines.join("\n")
3203
3216
  };
3204
3217
  }
3205
3218
  // --- Process management ---
@@ -3448,9 +3461,6 @@ var Sandbox = class {
3448
3461
  return fromSnakeKeys(raw);
3449
3462
  }
3450
3463
  };
3451
- function sleep2(ms) {
3452
- return new Promise((resolve) => setTimeout(resolve, ms));
3453
- }
3454
3464
 
3455
3465
  // src/client.ts
3456
3466
  var SandboxClient = class _SandboxClient {
@@ -3666,7 +3676,7 @@ var SandboxClient = class _SandboxClient {
3666
3676
  `Snapshot ${result.snapshotId} failed: ${info.error}`
3667
3677
  );
3668
3678
  }
3669
- await sleep3(pollInterval * 1e3);
3679
+ await sleep2(pollInterval * 1e3);
3670
3680
  }
3671
3681
  throw new SandboxError(
3672
3682
  `Snapshot ${result.snapshotId} did not complete within ${timeout}s`
@@ -3738,14 +3748,15 @@ var SandboxClient = class _SandboxClient {
3738
3748
  );
3739
3749
  }
3740
3750
  // --- Connect ---
3741
- connect(identifier, proxyUrl) {
3751
+ connect(identifier, proxyUrl, routingHint) {
3742
3752
  const resolvedProxy = proxyUrl ?? resolveProxyUrl(this.apiUrl);
3743
3753
  return new Sandbox({
3744
3754
  sandboxId: identifier,
3745
3755
  proxyUrl: resolvedProxy,
3746
3756
  apiKey: this.apiKey,
3747
3757
  organizationId: this.organizationId,
3748
- projectId: this.projectId
3758
+ projectId: this.projectId,
3759
+ routingHint
3749
3760
  });
3750
3761
  }
3751
3762
  async createAndConnect(options) {
@@ -3756,6 +3767,11 @@ var SandboxClient = class _SandboxClient {
3756
3767
  } else {
3757
3768
  result = await this.create(options);
3758
3769
  }
3770
+ if (result.status === "running" /* RUNNING */) {
3771
+ const sandbox = this.connect(result.sandboxId, options?.proxyUrl, result.routingHint);
3772
+ sandbox._setOwner(this);
3773
+ return sandbox;
3774
+ }
3759
3775
  const deadline = Date.now() + startupTimeout * 1e3;
3760
3776
  while (Date.now() < deadline) {
3761
3777
  const info = await this.get(result.sandboxId);
@@ -3769,7 +3785,7 @@ var SandboxClient = class _SandboxClient {
3769
3785
  `Sandbox ${result.sandboxId} terminated during startup`
3770
3786
  );
3771
3787
  }
3772
- await sleep3(500);
3788
+ await sleep2(500);
3773
3789
  }
3774
3790
  try {
3775
3791
  await this.delete(result.sandboxId);
@@ -3780,7 +3796,7 @@ var SandboxClient = class _SandboxClient {
3780
3796
  );
3781
3797
  }
3782
3798
  };
3783
- function sleep3(ms) {
3799
+ function sleep2(ms) {
3784
3800
  return new Promise((resolve) => setTimeout(resolve, ms));
3785
3801
  }
3786
3802
  var RESERVED_SANDBOX_MANAGEMENT_PORT = 9501;
@@ -4662,7 +4678,7 @@ async function runChecked(sandbox, command, args, env, workingDir) {
4662
4678
  }
4663
4679
  return result;
4664
4680
  }
4665
- async function runStreaming(sandbox, emit, sleep4, command, args = [], env, workingDir) {
4681
+ async function runStreaming(sandbox, emit, sleep3, command, args = [], env, workingDir) {
4666
4682
  const proc = await sandbox.startProcess(command, {
4667
4683
  args,
4668
4684
  env,
@@ -4687,13 +4703,13 @@ async function runStreaming(sandbox, emit, sleep4, command, args = [], env, work
4687
4703
  emitOutputLines(emit, "stderr", finalStderr, stderrSeen);
4688
4704
  break;
4689
4705
  }
4690
- await sleep4(300);
4706
+ await sleep3(300);
4691
4707
  }
4692
4708
  for (let i = 0; i < 10; i++) {
4693
4709
  if (info.exitCode != null || info.signal != null) {
4694
4710
  break;
4695
4711
  }
4696
- await sleep4(200);
4712
+ await sleep3(200);
4697
4713
  info = await sandbox.getProcess(proc.pid);
4698
4714
  }
4699
4715
  const exitCode = info.exitCode != null ? info.exitCode : info.signal != null ? -info.signal : 0;
@@ -4791,7 +4807,7 @@ async function copyFromContext(sandbox, emit, contextDir, sources, destination,
4791
4807
  await copyLocalPathToSandbox(sandbox, localSource, remoteDestination);
4792
4808
  }
4793
4809
  }
4794
- async function addUrlToSandbox(sandbox, emit, url, destination, workingDir, processEnv, sleep4) {
4810
+ async function addUrlToSandbox(sandbox, emit, url, destination, workingDir, processEnv, sleep3) {
4795
4811
  let destinationPath = resolveContainerPath(destination, workingDir);
4796
4812
  const parsedUrl = new URL(url);
4797
4813
  const fileName = import_node_path.default.posix.basename(parsedUrl.pathname.replace(/\/$/, "")) || "downloaded";
@@ -4807,7 +4823,7 @@ async function addUrlToSandbox(sandbox, emit, url, destination, workingDir, proc
4807
4823
  await runStreaming(
4808
4824
  sandbox,
4809
4825
  emit,
4810
- sleep4,
4826
+ sleep3,
4811
4827
  "sh",
4812
4828
  [
4813
4829
  "-c",
@@ -4817,7 +4833,7 @@ async function addUrlToSandbox(sandbox, emit, url, destination, workingDir, proc
4817
4833
  workingDir
4818
4834
  );
4819
4835
  }
4820
- async function executeDockerfilePlan(sandbox, plan, emit, sleep4) {
4836
+ async function executeDockerfilePlan(sandbox, plan, emit, sleep3) {
4821
4837
  const processEnv = { ...BUILD_SANDBOX_PIP_ENV };
4822
4838
  let workingDir = "/";
4823
4839
  for (const instruction of plan.instructions) {
@@ -4827,7 +4843,7 @@ async function executeDockerfilePlan(sandbox, plan, emit, sleep4) {
4827
4843
  await runStreaming(
4828
4844
  sandbox,
4829
4845
  emit,
4830
- sleep4,
4846
+ sleep3,
4831
4847
  "sh",
4832
4848
  ["-c", value],
4833
4849
  processEnv,
@@ -4884,7 +4900,7 @@ async function executeDockerfilePlan(sandbox, plan, emit, sleep4) {
4884
4900
  destination,
4885
4901
  workingDir,
4886
4902
  processEnv,
4887
- sleep4
4903
+ sleep3
4888
4904
  );
4889
4905
  } else {
4890
4906
  await copyFromContext(
@@ -4952,7 +4968,7 @@ async function registerImage(context, name, dockerfile, snapshotId, snapshotUri,
4952
4968
  }
4953
4969
  async function createSandboxImage(source, options = {}, deps = {}) {
4954
4970
  const emit = deps.emit ?? defaultEmit;
4955
- const sleep4 = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
4971
+ const sleep3 = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
4956
4972
  const context = buildContextFromEnv();
4957
4973
  const clientFactory = deps.createClient ?? createDefaultClient;
4958
4974
  const register = deps.registerImage ?? ((...args) => registerImage(...args));
@@ -4975,7 +4991,7 @@ async function createSandboxImage(source, options = {}, deps = {}) {
4975
4991
  type: "status",
4976
4992
  message: `Materializing image in sandbox ${sandbox.sandboxId}...`
4977
4993
  });
4978
- await executeDockerfilePlan(sandbox, plan, emit, sleep4);
4994
+ await executeDockerfilePlan(sandbox, plan, emit, sleep3);
4979
4995
  emit({ type: "status", message: "Creating snapshot..." });
4980
4996
  const snapshot = await client.snapshotAndWait(sandbox.sandboxId, {
4981
4997
  contentMode: "filesystem_only"