tensorlake 0.5.126 → 0.5.128

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.
@@ -46,7 +46,7 @@ var init_defaults = __esm({
46
46
  "src/defaults.ts"() {
47
47
  "use strict";
48
48
  init_esm_shims();
49
- SDK_VERSION = "0.5.126";
49
+ SDK_VERSION = "0.5.128";
50
50
  API_URL = process.env.TENSORLAKE_API_URL ?? "https://api.tensorlake.ai";
51
51
  API_KEY = process.env.TENSORLAKE_API_KEY ?? void 0;
52
52
  NAMESPACE = process.env.INDEXIFY_NAMESPACE ?? "default";
@@ -81,6 +81,27 @@ function describeError(err) {
81
81
  if (parts.length > 0) return parts.join(": ");
82
82
  return err instanceof Error ? err.message : String(err);
83
83
  }
84
+ function formatErrorDetails(errorDetails) {
85
+ if (errorDetails == null) return void 0;
86
+ if (typeof errorDetails === "string") {
87
+ const detail = errorDetails.trim();
88
+ return detail || void 0;
89
+ }
90
+ if (Array.isArray(errorDetails)) {
91
+ const parts = errorDetails.map((item) => formatErrorDetails(item)).filter((item) => Boolean(item));
92
+ return parts.length > 0 ? parts.join("; ") : JSON.stringify(errorDetails);
93
+ }
94
+ if (typeof errorDetails === "object") {
95
+ for (const key of ["message", "detail", "error", "reason"]) {
96
+ const value = errorDetails[key];
97
+ if (typeof value === "string" && value.trim()) {
98
+ return value.trim();
99
+ }
100
+ }
101
+ return JSON.stringify(errorDetails);
102
+ }
103
+ return String(errorDetails);
104
+ }
84
105
  var SandboxException, SandboxError, SandboxConnectionError, SandboxNotFoundError, PoolNotFoundError, PoolInUseError, RemoteAPIError, RequestNotFinishedError, RequestFailedError, RequestExecutionError;
85
106
  var init_errors = __esm({
86
107
  "src/errors.ts"() {
@@ -132,9 +153,39 @@ var init_errors = __esm({
132
153
  };
133
154
  RemoteAPIError = class extends SandboxError {
134
155
  statusCode;
156
+ /** Original response body, retained for compatibility and diagnostics. */
135
157
  responseMessage;
158
+ sandboxId;
159
+ /** Server reason, including unknown future reasons. */
160
+ reason;
161
+ errorDetails;
136
162
  constructor(statusCode, message) {
137
- super(`API error (status ${statusCode}): ${message}`);
163
+ let failure;
164
+ try {
165
+ const payload = JSON.parse(message);
166
+ if (payload && typeof payload === "object" && !Array.isArray(payload)) {
167
+ const record = payload;
168
+ if (typeof record.sandbox_id === "string" && record.sandbox_id.trim() && (record.status === "failed" || record.status === "terminated"))
169
+ failure = record;
170
+ }
171
+ } catch {
172
+ }
173
+ const sandboxId = failure?.sandbox_id;
174
+ const rawReason = failure?.reason ?? failure?.termination_reason;
175
+ const reason = typeof rawReason === "string" ? rawReason : void 0;
176
+ const errorDetails = failure?.error_details;
177
+ let displayMessage = message;
178
+ if (failure) {
179
+ displayMessage = `Sandbox ${sandboxId} ${failure.status}`;
180
+ if (reason) displayMessage += ` (${reason})`;
181
+ const detail = formatErrorDetails(errorDetails);
182
+ if (detail) displayMessage += `: ${detail}`;
183
+ if (!reason && !detail) displayMessage = message;
184
+ }
185
+ super(`API error (status ${statusCode}): ${displayMessage}`);
186
+ this.sandboxId = sandboxId;
187
+ this.reason = reason;
188
+ this.errorDetails = errorDetails;
138
189
  this.name = "RemoteAPIError";
139
190
  this.statusCode = statusCode;
140
191
  this.responseMessage = message;
@@ -3630,9 +3681,11 @@ init_cloud_client();
3630
3681
 
3631
3682
  // src/filesystem.ts
3632
3683
  init_esm_shims();
3633
- init_defaults();
3634
- import { execFile } from "child_process";
3635
3684
  import { randomBytes } from "crypto";
3685
+
3686
+ // src/mount-cli.ts
3687
+ init_esm_shims();
3688
+ import { execFile } from "child_process";
3636
3689
  import { accessSync, constants } from "fs";
3637
3690
  import { homedir } from "os";
3638
3691
  import { join } from "path";
@@ -3716,14 +3769,71 @@ var ReadOnlyMountNotSupportedError = class extends MountError {
3716
3769
  }
3717
3770
  };
3718
3771
  var CliNotFoundError = class extends MountError {
3719
- constructor(detail) {
3772
+ constructor(detail, command = "fs") {
3720
3773
  super(
3721
- `Mount operations require the Tensorlake CLI (\`tl\`) with \`tl fs\` support: ${detail}. Install or upgrade it with: curl -fsSL https://tensorlake.ai/install.sh | sh`
3774
+ `Mount operations require the Tensorlake CLI (\`tl\`) with \`tl ${command}\` support: ${detail}. Install or upgrade it with: curl -fsSL https://tensorlake.ai/install.sh | sh`
3722
3775
  );
3723
3776
  this.name = "CliNotFoundError";
3724
3777
  }
3725
3778
  };
3726
3779
 
3780
+ // src/mount-cli.ts
3781
+ var execFileAsync = promisify(execFile);
3782
+ var MountCli = class {
3783
+ constructor(command, envOverrides) {
3784
+ this.command = command;
3785
+ this.envOverrides = envOverrides;
3786
+ }
3787
+ binary = null;
3788
+ async findCli() {
3789
+ const candidates = [];
3790
+ if (process.env.TENSORLAKE_CLI) candidates.push(process.env.TENSORLAKE_CLI);
3791
+ candidates.push("tl");
3792
+ const installed = join(homedir(), ".tensorlake", "bin", "tl");
3793
+ try {
3794
+ accessSync(installed, constants.F_OK);
3795
+ candidates.push(installed);
3796
+ } catch {
3797
+ }
3798
+ const support = this.command === "git" ? "git mount" : "fs";
3799
+ const probe = this.command === "git" ? ["git", "mount", "--help"] : ["fs", "--help"];
3800
+ let unsupported = null;
3801
+ for (const candidate of candidates) {
3802
+ try {
3803
+ await execFileAsync(candidate, probe, { timeout: 15e3 });
3804
+ return candidate;
3805
+ } catch (error) {
3806
+ if (error.code !== "ENOENT") unsupported = candidate;
3807
+ }
3808
+ }
3809
+ throw new CliNotFoundError(
3810
+ unsupported ? `\`tl\` at ${unsupported} does not support \`tl ${support}\` (upgrade required)` : "`tl` was not found on PATH",
3811
+ support
3812
+ );
3813
+ }
3814
+ async run(args, timeoutMs = 3e5) {
3815
+ if (this.binary === null) this.binary = await this.findCli();
3816
+ try {
3817
+ const { stdout } = await execFileAsync(this.binary, [this.command, ...args], {
3818
+ timeout: timeoutMs,
3819
+ env: { ...process.env, ...this.envOverrides },
3820
+ maxBuffer: 16 * 1024 * 1024
3821
+ });
3822
+ return stdout;
3823
+ } catch (error) {
3824
+ const failure = error;
3825
+ if (failure.killed) {
3826
+ throw new MountError(`\`tl ${this.command} ${args[0]}\` timed out after ${timeoutMs}ms`);
3827
+ }
3828
+ const detail = (failure.stderr || failure.stdout || String(error)).trim();
3829
+ throw new MountError(`\`tl ${this.command} ${args.join(" ")}\` failed: ${detail}`);
3830
+ }
3831
+ }
3832
+ };
3833
+
3834
+ // src/filesystem.ts
3835
+ init_defaults();
3836
+
3727
3837
  // src/native-sandbox.ts
3728
3838
  init_esm_shims();
3729
3839
  init_errors();
@@ -3947,7 +4057,7 @@ function createWorkerBinding(runtime) {
3947
4057
  };
3948
4058
  }
3949
4059
  var runtimeKey = /* @__PURE__ */ Symbol.for(
3950
- `tensorlake.native.worker.${false ? "source" : "0.5.126"}.v1`
4060
+ `tensorlake.native.worker.${false ? "source" : "0.5.128"}.v1`
3951
4061
  );
3952
4062
  var runtimes = globalThis;
3953
4063
  function workerBinding() {
@@ -3964,7 +4074,6 @@ function loadNativeSandboxBinding() {
3964
4074
 
3965
4075
  // src/filesystem.ts
3966
4076
  init_sandbox_image();
3967
- var execFileAsync = promisify(execFile);
3968
4077
  var FILESYSTEM_REPO_KIND = "filesystem";
3969
4078
  function translateNativeError(error, notFound) {
3970
4079
  const message = error instanceof Error ? error.message : String(error);
@@ -3996,58 +4105,9 @@ async function callNative(fn, notFound) {
3996
4105
  throw translateNativeError(error, notFound);
3997
4106
  }
3998
4107
  }
3999
- var FsCli = class {
4000
- binary = null;
4001
- envOverrides;
4108
+ var FsCli = class extends MountCli {
4002
4109
  constructor(envOverrides) {
4003
- this.envOverrides = envOverrides;
4004
- }
4005
- async findCli() {
4006
- const candidates = [];
4007
- if (process.env.TENSORLAKE_CLI) {
4008
- candidates.push(process.env.TENSORLAKE_CLI);
4009
- }
4010
- candidates.push("tl");
4011
- const installed = join(homedir(), ".tensorlake", "bin", "tl");
4012
- try {
4013
- accessSync(installed, constants.F_OK);
4014
- candidates.push(installed);
4015
- } catch {
4016
- }
4017
- let unsupported = null;
4018
- for (const candidate of candidates) {
4019
- try {
4020
- await execFileAsync(candidate, ["fs", "--help"], { timeout: 15e3 });
4021
- return candidate;
4022
- } catch (error) {
4023
- if (error.code !== "ENOENT") {
4024
- unsupported = candidate;
4025
- }
4026
- }
4027
- }
4028
- throw new CliNotFoundError(
4029
- unsupported ? `\`tl\` at ${unsupported} does not support \`tl fs\` (upgrade required)` : "`tl` was not found on PATH"
4030
- );
4031
- }
4032
- async run(args, timeoutMs = 3e5) {
4033
- if (this.binary === null) {
4034
- this.binary = await this.findCli();
4035
- }
4036
- try {
4037
- const { stdout } = await execFileAsync(this.binary, ["fs", ...args], {
4038
- timeout: timeoutMs,
4039
- env: { ...process.env, ...this.envOverrides },
4040
- maxBuffer: 16 * 1024 * 1024
4041
- });
4042
- return stdout;
4043
- } catch (error) {
4044
- const failure = error;
4045
- if (failure.killed) {
4046
- throw new MountError(`\`tl fs ${args[0]}\` timed out after ${timeoutMs}ms`);
4047
- }
4048
- const detail = (failure.stderr || failure.stdout || String(error)).trim();
4049
- throw new MountError(`\`tl fs ${args.join(" ")}\` failed: ${detail}`);
4050
- }
4110
+ super("fs", envOverrides);
4051
4111
  }
4052
4112
  // Flags always precede a `--` end-of-options separator so caller-supplied
4053
4113
  // names/paths can never be parsed as CLI flags (e.g. a path literally