@tensorlakeai/tensorlake 0.5.158 → 0.5.160

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.
Files changed (30) hide show
  1. package/README.md +25 -0
  2. package/dist/applications/index.cjs +12 -2
  3. package/dist/applications/index.cjs.map +1 -1
  4. package/dist/applications/index.js +12 -2
  5. package/dist/applications/index.js.map +1 -1
  6. package/dist/function-agent/main.cjs +1 -1
  7. package/dist/function-agent/main.cjs.map +1 -1
  8. package/dist/function-agent/main.js +1 -1
  9. package/dist/function-agent/main.js.map +1 -1
  10. package/dist/function-executor/main.cjs +2 -2
  11. package/dist/function-executor/main.cjs.map +1 -1
  12. package/dist/function-executor/main.js +2 -2
  13. package/dist/function-executor/main.js.map +1 -1
  14. package/dist/index.cjs +131 -29
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +164 -1
  17. package/dist/index.d.ts +164 -1
  18. package/dist/index.js +130 -29
  19. package/dist/index.js.map +1 -1
  20. package/package.json +7 -7
  21. package/runtime/function-executor/manifest.json +7 -7
  22. package/runtime/function-executor/package/dist/function-executor/main.js +2 -2
  23. package/runtime/function-executor/package/dist/function-executor/main.js.map +1 -1
  24. package/runtime/function-executor/package/npm-shrinkwrap.json +2 -2
  25. package/runtime/function-executor/package/package.json +1 -1
  26. package/runtime/typescript-function-runner/manifest.json +7 -7
  27. package/runtime/typescript-function-runner/package/dist/function-agent/main.js +1 -1
  28. package/runtime/typescript-function-runner/package/dist/function-agent/main.js.map +1 -1
  29. package/runtime/typescript-function-runner/package/npm-shrinkwrap.json +26 -26
  30. package/runtime/typescript-function-runner/package/package.json +7 -7
package/dist/index.js CHANGED
@@ -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.158";
49
+ SDK_VERSION = "0.5.160";
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";
@@ -181,13 +181,17 @@ var init_errors = __esm({
181
181
  statusCode;
182
182
  /** Original response body, retained for compatibility and diagnostics. */
183
183
  responseMessage;
184
+ /** Machine-readable API error code, including proxy policy failures. */
185
+ code;
184
186
  errorDetails;
185
187
  constructor(statusCode, message) {
186
188
  let failure;
189
+ let code;
187
190
  try {
188
191
  const payload = JSON.parse(message);
189
192
  if (payload && typeof payload === "object" && !Array.isArray(payload)) {
190
193
  const record = payload;
194
+ if (typeof record.code === "string") code = record.code;
191
195
  if (typeof record.sandbox_id === "string" && record.sandbox_id.trim() && (record.status === "failed" || record.status === "terminated"))
192
196
  failure = record;
193
197
  }
@@ -213,6 +217,7 @@ var init_errors = __esm({
213
217
  this.name = "RemoteAPIError";
214
218
  this.statusCode = statusCode;
215
219
  this.responseMessage = message;
220
+ this.code = code;
216
221
  }
217
222
  };
218
223
  RequestNotFinishedError = class extends Error {
@@ -327,6 +332,11 @@ function createWorkerBinding(runtime) {
327
332
  return runtime.handle("NativeRepositoryClient", args);
328
333
  }
329
334
  },
335
+ NativeUsageClient: class {
336
+ constructor(...args) {
337
+ return runtime.handle("NativeUsageClient", args);
338
+ }
339
+ },
330
340
  NativeTcpTunnel: class {
331
341
  constructor() {
332
342
  return runtime.handle("NativeTcpTunnel", []);
@@ -509,7 +519,7 @@ var init_native_worker_client = __esm({
509
519
  }
510
520
  };
511
521
  runtimeKey = /* @__PURE__ */ Symbol.for(
512
- `tensorlake.native.worker.${false ? "source" : "0.5.158"}.v1`
522
+ `tensorlake.native.worker.${false ? "source" : "0.5.160"}.v1`
513
523
  );
514
524
  runtimes = globalThis;
515
525
  }
@@ -4930,6 +4940,12 @@ var init_client = __esm({
4930
4940
  if (options?.timeoutSecs != null) body.timeout_secs = options.timeoutSecs;
4931
4941
  if (options?.entrypoint != null) body.entrypoint = options.entrypoint;
4932
4942
  if (options?.snapshotId != null) body.snapshot_id = options.snapshotId;
4943
+ if (options?.allowUnauthenticatedAccess != null) {
4944
+ body.allow_unauthenticated_access = options.allowUnauthenticatedAccess;
4945
+ }
4946
+ if (options?.exposedPorts != null) {
4947
+ body.exposed_ports = normalizeUserPorts(options.exposedPorts);
4948
+ }
4933
4949
  if (options?.name != null) body.name = options.name;
4934
4950
  if (options?.fileSystems != null && options.fileSystems.length > 0) {
4935
4951
  body.file_systems = options.fileSystems.map(fileSystemMountToWire);
@@ -4941,6 +4957,7 @@ var init_client = __esm({
4941
4957
  deny_out: options?.denyOut ?? []
4942
4958
  };
4943
4959
  }
4960
+ if (options?.autoResume != null) body.auto_resume = options.autoResume;
4944
4961
  if (options?.maxPendingSecs != null) {
4945
4962
  if (!Number.isInteger(options.maxPendingSecs) || options.maxPendingSecs < 0) {
4946
4963
  throw new SandboxError("maxPendingSecs must be a non-negative integer");
@@ -5057,13 +5074,14 @@ var init_client = __esm({
5057
5074
  const resizing = Object.keys(resources).length > 0;
5058
5075
  if (resizing) {
5059
5076
  validateResizeWait(options);
5060
- if (options.name != null || options.allowUnauthenticatedAccess != null || options.exposedPorts != null || options.network !== void 0) {
5077
+ if (options.name != null || options.allowUnauthenticatedAccess != null || options.exposedPorts != null || options.autoResume != null || options.network !== void 0) {
5061
5078
  throw new SandboxError(
5062
5079
  "resources cannot be combined with other sandbox update fields"
5063
5080
  );
5064
5081
  }
5065
5082
  body.resources = resources;
5066
5083
  }
5084
+ if (options.autoResume != null) body.auto_resume = options.autoResume;
5067
5085
  if (options.name != null) body.name = options.name;
5068
5086
  if (options.allowUnauthenticatedAccess != null) {
5069
5087
  body.allow_unauthenticated_access = options.allowUnauthenticatedAccess;
@@ -5158,28 +5176,19 @@ var init_client = __esm({
5158
5176
  * cannot. By default blocks until the sandbox is fully `Suspended`. Pass
5159
5177
  * `{ wait: false }` to return immediately after the request is sent
5160
5178
  * (fire-and-return); the server processes the suspend asynchronously.
5179
+ *
5180
+ * The server answers as soon as the suspend completes. When its wait runs
5181
+ * out first, or the server does not support waiting, the rest of `timeout`
5182
+ * is spent polling every `pollInterval` seconds.
5161
5183
  */
5162
5184
  async suspend(sandboxId, options) {
5163
- await callNative(() => this.native.suspendSandbox(sandboxId), {
5185
+ await this.changeLifecycle(
5164
5186
  sandboxId,
5165
- notFoundKind: "sandbox"
5166
- });
5167
- if (options?.wait === false) return;
5168
- const timeout = options?.timeout ?? 300;
5169
- const pollInterval = options?.pollInterval ?? 1;
5170
- const deadline = Date.now() + timeout * 1e3;
5171
- while (Date.now() < deadline) {
5172
- const info = await this.get(sandboxId);
5173
- if (info.status === "suspended" /* SUSPENDED */) return;
5174
- if (info.status === "terminated" /* TERMINATED */) {
5175
- throw new SandboxError(
5176
- `Sandbox ${sandboxId} terminated while waiting for suspend`
5177
- );
5178
- }
5179
- await sleep2(pollInterval * 1e3);
5180
- }
5181
- throw new SandboxError(
5182
- `Sandbox ${sandboxId} did not suspend within ${timeout}s`
5187
+ "suspend",
5188
+ "suspended" /* SUSPENDED */,
5189
+ () => this.native.suspendSandbox(sandboxId),
5190
+ (waitSec) => this.native.suspendSandboxAndWait(sandboxId, waitSec),
5191
+ options
5183
5192
  );
5184
5193
  }
5185
5194
  /**
@@ -5188,28 +5197,58 @@ var init_client = __esm({
5188
5197
  * By default blocks until the sandbox is `Running` and routable. Pass
5189
5198
  * `{ wait: false }` to return immediately after the request is sent
5190
5199
  * (fire-and-return); the server processes the resume asynchronously.
5200
+ *
5201
+ * The server answers as soon as the sandbox runs. When its wait runs out
5202
+ * first, or the server does not support waiting, the rest of `timeout` is
5203
+ * spent polling every `pollInterval` seconds.
5191
5204
  */
5192
5205
  async resume(sandboxId, options) {
5193
- await callNative(() => this.native.resumeSandbox(sandboxId), {
5206
+ await this.changeLifecycle(
5194
5207
  sandboxId,
5195
- notFoundKind: "sandbox"
5196
- });
5197
- if (options?.wait === false) return;
5208
+ "resume",
5209
+ "running" /* RUNNING */,
5210
+ () => this.native.resumeSandbox(sandboxId),
5211
+ (waitSec) => this.native.resumeSandboxAndWait(sandboxId, waitSec),
5212
+ options
5213
+ );
5214
+ }
5215
+ /**
5216
+ * Send a suspend or resume. With `wait`, the server waits for `target` and
5217
+ * answers whether it was reached; when its wait runs out first, the rest of
5218
+ * the timeout is spent polling.
5219
+ */
5220
+ async changeLifecycle(sandboxId, action, target, send, sendAndWait, options) {
5221
+ const context = { sandboxId, notFoundKind: "sandbox" };
5222
+ if (options?.wait === false) {
5223
+ await callNative(send, context);
5224
+ return;
5225
+ }
5198
5226
  const timeout = options?.timeout ?? 300;
5199
5227
  const pollInterval = options?.pollInterval ?? 1;
5200
5228
  const deadline = Date.now() + timeout * 1e3;
5229
+ let settled;
5230
+ try {
5231
+ settled = await callNative(() => sendAndWait(timeout), context);
5232
+ } catch (error) {
5233
+ if (!(error instanceof RemoteAPIError) || error.statusCode !== 409) {
5234
+ throw error;
5235
+ }
5236
+ if ((await this.get(sandboxId)).status === target) return;
5237
+ throw error;
5238
+ }
5239
+ if (settled) return;
5201
5240
  while (Date.now() < deadline) {
5202
5241
  const info = await this.get(sandboxId);
5203
- if (info.status === "running" /* RUNNING */) return;
5242
+ if (info.status === target) return;
5204
5243
  if (info.status === "terminated" /* TERMINATED */) {
5205
5244
  throw new SandboxError(
5206
- `Sandbox ${sandboxId} terminated while waiting for resume`
5245
+ `Sandbox ${sandboxId} terminated while waiting for ${action}`
5207
5246
  );
5208
5247
  }
5209
5248
  await sleep2(pollInterval * 1e3);
5210
5249
  }
5211
5250
  throw new SandboxError(
5212
- `Sandbox ${sandboxId} did not resume within ${timeout}s`
5251
+ `Sandbox ${sandboxId} did not ${action} within ${timeout}s`
5213
5252
  );
5214
5253
  }
5215
5254
  /**
@@ -5486,6 +5525,11 @@ var init_client = __esm({
5486
5525
  * claim that is still starting is then waited on the same way.
5487
5526
  */
5488
5527
  async createAndConnect(options) {
5528
+ if (options?.poolId != null && (options.allowUnauthenticatedAccess != null || options.exposedPorts != null)) {
5529
+ throw new SandboxError(
5530
+ "allowUnauthenticatedAccess and exposedPorts cannot be combined with poolId: pool claims inherit access settings from the pool."
5531
+ );
5532
+ }
5489
5533
  const opStart = nowMs();
5490
5534
  const requestTimeout = options?.requestTimeout ?? options?.startupTimeout ?? this.requestTimeoutMs / 1e3;
5491
5535
  const requestClient = this.withRequestTimeout(requestTimeout);
@@ -5498,6 +5542,9 @@ var init_client = __esm({
5498
5542
  const requestedName = options?.poolId != null ? null : options?.name ?? null;
5499
5543
  const createStart = nowMs();
5500
5544
  let result;
5545
+ if (options?.poolId != null && options.autoResume != null) {
5546
+ throw new SandboxError("autoResume cannot be set when claiming from a pool");
5547
+ }
5501
5548
  if (options?.poolId != null) {
5502
5549
  result = await requestClient.claim(options.poolId, {
5503
5550
  fileSystems: options.fileSystems
@@ -8753,6 +8800,59 @@ function validateTimeoutMs2(timeoutMs) {
8753
8800
  }
8754
8801
  }
8755
8802
 
8803
+ // src/usage.ts
8804
+ init_esm_shims();
8805
+ init_defaults();
8806
+ init_errors();
8807
+ init_native_sandbox();
8808
+ init_native_worker_client();
8809
+ var UsageClient = class {
8810
+ native;
8811
+ constructor(options) {
8812
+ const apiKey = options?.apiKey ?? API_KEY;
8813
+ if (!apiKey) {
8814
+ throw new SandboxError("Missing TENSORLAKE_API_KEY credentials.");
8815
+ }
8816
+ const organizationId = options?.organizationId ?? process.env.TENSORLAKE_ORGANIZATION_ID;
8817
+ if (!organizationId) {
8818
+ throw new SandboxError(
8819
+ "An organization ID is required. Pass organizationId or set TENSORLAKE_ORGANIZATION_ID."
8820
+ );
8821
+ }
8822
+ const binding = loadNativeSandboxBinding();
8823
+ if (typeof binding.NativeUsageClient !== "function") {
8824
+ throw new SandboxError(
8825
+ "native binding does not export the usage client; rebuild with 'npm run build:native'"
8826
+ );
8827
+ }
8828
+ this.native = new binding.NativeUsageClient(
8829
+ options?.apiUrl ?? API_URL,
8830
+ apiKey,
8831
+ organizationId,
8832
+ `tensorlake-typescript-sdk/${SDK_VERSION}`,
8833
+ DEFAULT_HTTP_TIMEOUT_MS / 1e3
8834
+ );
8835
+ }
8836
+ close() {
8837
+ releaseNativeHandle(this.native);
8838
+ }
8839
+ /** Organization usage totals for the window. */
8840
+ async summary(options) {
8841
+ const { json } = await callNative(() => this.native.summary(options?.last ?? null));
8842
+ return JSON.parse(json);
8843
+ }
8844
+ /**
8845
+ * Usage and attributed cost of every sandbox that ran in the window.
8846
+ *
8847
+ * The server computes the attribution once and returns every sandbox in one
8848
+ * response.
8849
+ */
8850
+ async sandboxes(options) {
8851
+ const { json } = await callNative(() => this.native.sandboxes(options?.last ?? null));
8852
+ return JSON.parse(json);
8853
+ }
8854
+ };
8855
+
8756
8856
  // src/index.ts
8757
8857
  init_sandbox_image();
8758
8858
  init_image_builds();
@@ -10665,6 +10765,7 @@ export {
10665
10765
  TERMINATION_REASON_CANCELLED,
10666
10766
  TERMINATION_REASON_NO_CAPACITY,
10667
10767
  TcpTunnel,
10768
+ UsageClient,
10668
10769
  cancelImageBuild,
10669
10770
  createFileSystem,
10670
10771
  createSandboxImage,