@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.cjs CHANGED
@@ -49,7 +49,7 @@ var init_defaults = __esm({
49
49
  "src/defaults.ts"() {
50
50
  "use strict";
51
51
  init_cjs_shims();
52
- SDK_VERSION = "0.5.158";
52
+ SDK_VERSION = "0.5.160";
53
53
  API_URL = process.env.TENSORLAKE_API_URL ?? "https://api.tensorlake.ai";
54
54
  API_KEY = process.env.TENSORLAKE_API_KEY ?? void 0;
55
55
  NAMESPACE = process.env.INDEXIFY_NAMESPACE ?? "default";
@@ -184,13 +184,17 @@ var init_errors = __esm({
184
184
  statusCode;
185
185
  /** Original response body, retained for compatibility and diagnostics. */
186
186
  responseMessage;
187
+ /** Machine-readable API error code, including proxy policy failures. */
188
+ code;
187
189
  errorDetails;
188
190
  constructor(statusCode, message) {
189
191
  let failure;
192
+ let code;
190
193
  try {
191
194
  const payload = JSON.parse(message);
192
195
  if (payload && typeof payload === "object" && !Array.isArray(payload)) {
193
196
  const record = payload;
197
+ if (typeof record.code === "string") code = record.code;
194
198
  if (typeof record.sandbox_id === "string" && record.sandbox_id.trim() && (record.status === "failed" || record.status === "terminated"))
195
199
  failure = record;
196
200
  }
@@ -216,6 +220,7 @@ var init_errors = __esm({
216
220
  this.name = "RemoteAPIError";
217
221
  this.statusCode = statusCode;
218
222
  this.responseMessage = message;
223
+ this.code = code;
219
224
  }
220
225
  };
221
226
  RequestNotFinishedError = class extends Error {
@@ -328,6 +333,11 @@ function createWorkerBinding(runtime) {
328
333
  return runtime.handle("NativeRepositoryClient", args);
329
334
  }
330
335
  },
336
+ NativeUsageClient: class {
337
+ constructor(...args) {
338
+ return runtime.handle("NativeUsageClient", args);
339
+ }
340
+ },
331
341
  NativeTcpTunnel: class {
332
342
  constructor() {
333
343
  return runtime.handle("NativeTcpTunnel", []);
@@ -512,7 +522,7 @@ var init_native_worker_client = __esm({
512
522
  }
513
523
  };
514
524
  runtimeKey = /* @__PURE__ */ Symbol.for(
515
- `tensorlake.native.worker.${false ? "source" : "0.5.158"}.v1`
525
+ `tensorlake.native.worker.${false ? "source" : "0.5.160"}.v1`
516
526
  );
517
527
  runtimes = globalThis;
518
528
  }
@@ -4933,6 +4943,12 @@ var init_client = __esm({
4933
4943
  if (options?.timeoutSecs != null) body.timeout_secs = options.timeoutSecs;
4934
4944
  if (options?.entrypoint != null) body.entrypoint = options.entrypoint;
4935
4945
  if (options?.snapshotId != null) body.snapshot_id = options.snapshotId;
4946
+ if (options?.allowUnauthenticatedAccess != null) {
4947
+ body.allow_unauthenticated_access = options.allowUnauthenticatedAccess;
4948
+ }
4949
+ if (options?.exposedPorts != null) {
4950
+ body.exposed_ports = normalizeUserPorts(options.exposedPorts);
4951
+ }
4936
4952
  if (options?.name != null) body.name = options.name;
4937
4953
  if (options?.fileSystems != null && options.fileSystems.length > 0) {
4938
4954
  body.file_systems = options.fileSystems.map(fileSystemMountToWire);
@@ -4944,6 +4960,7 @@ var init_client = __esm({
4944
4960
  deny_out: options?.denyOut ?? []
4945
4961
  };
4946
4962
  }
4963
+ if (options?.autoResume != null) body.auto_resume = options.autoResume;
4947
4964
  if (options?.maxPendingSecs != null) {
4948
4965
  if (!Number.isInteger(options.maxPendingSecs) || options.maxPendingSecs < 0) {
4949
4966
  throw new SandboxError("maxPendingSecs must be a non-negative integer");
@@ -5060,13 +5077,14 @@ var init_client = __esm({
5060
5077
  const resizing = Object.keys(resources).length > 0;
5061
5078
  if (resizing) {
5062
5079
  validateResizeWait(options);
5063
- if (options.name != null || options.allowUnauthenticatedAccess != null || options.exposedPorts != null || options.network !== void 0) {
5080
+ if (options.name != null || options.allowUnauthenticatedAccess != null || options.exposedPorts != null || options.autoResume != null || options.network !== void 0) {
5064
5081
  throw new SandboxError(
5065
5082
  "resources cannot be combined with other sandbox update fields"
5066
5083
  );
5067
5084
  }
5068
5085
  body.resources = resources;
5069
5086
  }
5087
+ if (options.autoResume != null) body.auto_resume = options.autoResume;
5070
5088
  if (options.name != null) body.name = options.name;
5071
5089
  if (options.allowUnauthenticatedAccess != null) {
5072
5090
  body.allow_unauthenticated_access = options.allowUnauthenticatedAccess;
@@ -5161,28 +5179,19 @@ var init_client = __esm({
5161
5179
  * cannot. By default blocks until the sandbox is fully `Suspended`. Pass
5162
5180
  * `{ wait: false }` to return immediately after the request is sent
5163
5181
  * (fire-and-return); the server processes the suspend asynchronously.
5182
+ *
5183
+ * The server answers as soon as the suspend completes. When its wait runs
5184
+ * out first, or the server does not support waiting, the rest of `timeout`
5185
+ * is spent polling every `pollInterval` seconds.
5164
5186
  */
5165
5187
  async suspend(sandboxId, options) {
5166
- await callNative(() => this.native.suspendSandbox(sandboxId), {
5188
+ await this.changeLifecycle(
5167
5189
  sandboxId,
5168
- notFoundKind: "sandbox"
5169
- });
5170
- if (options?.wait === false) return;
5171
- const timeout = options?.timeout ?? 300;
5172
- const pollInterval = options?.pollInterval ?? 1;
5173
- const deadline = Date.now() + timeout * 1e3;
5174
- while (Date.now() < deadline) {
5175
- const info = await this.get(sandboxId);
5176
- if (info.status === "suspended" /* SUSPENDED */) return;
5177
- if (info.status === "terminated" /* TERMINATED */) {
5178
- throw new SandboxError(
5179
- `Sandbox ${sandboxId} terminated while waiting for suspend`
5180
- );
5181
- }
5182
- await sleep2(pollInterval * 1e3);
5183
- }
5184
- throw new SandboxError(
5185
- `Sandbox ${sandboxId} did not suspend within ${timeout}s`
5190
+ "suspend",
5191
+ "suspended" /* SUSPENDED */,
5192
+ () => this.native.suspendSandbox(sandboxId),
5193
+ (waitSec) => this.native.suspendSandboxAndWait(sandboxId, waitSec),
5194
+ options
5186
5195
  );
5187
5196
  }
5188
5197
  /**
@@ -5191,28 +5200,58 @@ var init_client = __esm({
5191
5200
  * By default blocks until the sandbox is `Running` and routable. Pass
5192
5201
  * `{ wait: false }` to return immediately after the request is sent
5193
5202
  * (fire-and-return); the server processes the resume asynchronously.
5203
+ *
5204
+ * The server answers as soon as the sandbox runs. When its wait runs out
5205
+ * first, or the server does not support waiting, the rest of `timeout` is
5206
+ * spent polling every `pollInterval` seconds.
5194
5207
  */
5195
5208
  async resume(sandboxId, options) {
5196
- await callNative(() => this.native.resumeSandbox(sandboxId), {
5209
+ await this.changeLifecycle(
5197
5210
  sandboxId,
5198
- notFoundKind: "sandbox"
5199
- });
5200
- if (options?.wait === false) return;
5211
+ "resume",
5212
+ "running" /* RUNNING */,
5213
+ () => this.native.resumeSandbox(sandboxId),
5214
+ (waitSec) => this.native.resumeSandboxAndWait(sandboxId, waitSec),
5215
+ options
5216
+ );
5217
+ }
5218
+ /**
5219
+ * Send a suspend or resume. With `wait`, the server waits for `target` and
5220
+ * answers whether it was reached; when its wait runs out first, the rest of
5221
+ * the timeout is spent polling.
5222
+ */
5223
+ async changeLifecycle(sandboxId, action, target, send, sendAndWait, options) {
5224
+ const context = { sandboxId, notFoundKind: "sandbox" };
5225
+ if (options?.wait === false) {
5226
+ await callNative(send, context);
5227
+ return;
5228
+ }
5201
5229
  const timeout = options?.timeout ?? 300;
5202
5230
  const pollInterval = options?.pollInterval ?? 1;
5203
5231
  const deadline = Date.now() + timeout * 1e3;
5232
+ let settled;
5233
+ try {
5234
+ settled = await callNative(() => sendAndWait(timeout), context);
5235
+ } catch (error) {
5236
+ if (!(error instanceof RemoteAPIError) || error.statusCode !== 409) {
5237
+ throw error;
5238
+ }
5239
+ if ((await this.get(sandboxId)).status === target) return;
5240
+ throw error;
5241
+ }
5242
+ if (settled) return;
5204
5243
  while (Date.now() < deadline) {
5205
5244
  const info = await this.get(sandboxId);
5206
- if (info.status === "running" /* RUNNING */) return;
5245
+ if (info.status === target) return;
5207
5246
  if (info.status === "terminated" /* TERMINATED */) {
5208
5247
  throw new SandboxError(
5209
- `Sandbox ${sandboxId} terminated while waiting for resume`
5248
+ `Sandbox ${sandboxId} terminated while waiting for ${action}`
5210
5249
  );
5211
5250
  }
5212
5251
  await sleep2(pollInterval * 1e3);
5213
5252
  }
5214
5253
  throw new SandboxError(
5215
- `Sandbox ${sandboxId} did not resume within ${timeout}s`
5254
+ `Sandbox ${sandboxId} did not ${action} within ${timeout}s`
5216
5255
  );
5217
5256
  }
5218
5257
  /**
@@ -5489,6 +5528,11 @@ var init_client = __esm({
5489
5528
  * claim that is still starting is then waited on the same way.
5490
5529
  */
5491
5530
  async createAndConnect(options) {
5531
+ if (options?.poolId != null && (options.allowUnauthenticatedAccess != null || options.exposedPorts != null)) {
5532
+ throw new SandboxError(
5533
+ "allowUnauthenticatedAccess and exposedPorts cannot be combined with poolId: pool claims inherit access settings from the pool."
5534
+ );
5535
+ }
5492
5536
  const opStart = nowMs();
5493
5537
  const requestTimeout = options?.requestTimeout ?? options?.startupTimeout ?? this.requestTimeoutMs / 1e3;
5494
5538
  const requestClient = this.withRequestTimeout(requestTimeout);
@@ -5501,6 +5545,9 @@ var init_client = __esm({
5501
5545
  const requestedName = options?.poolId != null ? null : options?.name ?? null;
5502
5546
  const createStart = nowMs();
5503
5547
  let result;
5548
+ if (options?.poolId != null && options.autoResume != null) {
5549
+ throw new SandboxError("autoResume cannot be set when claiming from a pool");
5550
+ }
5504
5551
  if (options?.poolId != null) {
5505
5552
  result = await requestClient.claim(options.poolId, {
5506
5553
  fileSystems: options.fileSystems
@@ -7123,6 +7170,7 @@ __export(index_exports, {
7123
7170
  TERMINATION_REASON_CANCELLED: () => TERMINATION_REASON_CANCELLED,
7124
7171
  TERMINATION_REASON_NO_CAPACITY: () => TERMINATION_REASON_NO_CAPACITY,
7125
7172
  TcpTunnel: () => TcpTunnel,
7173
+ UsageClient: () => UsageClient,
7126
7174
  cancelImageBuild: () => cancelImageBuild,
7127
7175
  createFileSystem: () => createFileSystem,
7128
7176
  createSandboxImage: () => createSandboxImage,
@@ -8847,6 +8895,59 @@ function validateTimeoutMs2(timeoutMs) {
8847
8895
  }
8848
8896
  }
8849
8897
 
8898
+ // src/usage.ts
8899
+ init_cjs_shims();
8900
+ init_defaults();
8901
+ init_errors();
8902
+ init_native_sandbox();
8903
+ init_native_worker_client();
8904
+ var UsageClient = class {
8905
+ native;
8906
+ constructor(options) {
8907
+ const apiKey = options?.apiKey ?? API_KEY;
8908
+ if (!apiKey) {
8909
+ throw new SandboxError("Missing TENSORLAKE_API_KEY credentials.");
8910
+ }
8911
+ const organizationId = options?.organizationId ?? process.env.TENSORLAKE_ORGANIZATION_ID;
8912
+ if (!organizationId) {
8913
+ throw new SandboxError(
8914
+ "An organization ID is required. Pass organizationId or set TENSORLAKE_ORGANIZATION_ID."
8915
+ );
8916
+ }
8917
+ const binding = loadNativeSandboxBinding();
8918
+ if (typeof binding.NativeUsageClient !== "function") {
8919
+ throw new SandboxError(
8920
+ "native binding does not export the usage client; rebuild with 'npm run build:native'"
8921
+ );
8922
+ }
8923
+ this.native = new binding.NativeUsageClient(
8924
+ options?.apiUrl ?? API_URL,
8925
+ apiKey,
8926
+ organizationId,
8927
+ `tensorlake-typescript-sdk/${SDK_VERSION}`,
8928
+ DEFAULT_HTTP_TIMEOUT_MS / 1e3
8929
+ );
8930
+ }
8931
+ close() {
8932
+ releaseNativeHandle(this.native);
8933
+ }
8934
+ /** Organization usage totals for the window. */
8935
+ async summary(options) {
8936
+ const { json } = await callNative(() => this.native.summary(options?.last ?? null));
8937
+ return JSON.parse(json);
8938
+ }
8939
+ /**
8940
+ * Usage and attributed cost of every sandbox that ran in the window.
8941
+ *
8942
+ * The server computes the attribution once and returns every sandbox in one
8943
+ * response.
8944
+ */
8945
+ async sandboxes(options) {
8946
+ const { json } = await callNative(() => this.native.sandboxes(options?.last ?? null));
8947
+ return JSON.parse(json);
8948
+ }
8949
+ };
8950
+
8850
8951
  // src/index.ts
8851
8952
  init_sandbox_image();
8852
8953
  init_image_builds();
@@ -10760,6 +10861,7 @@ init_models();
10760
10861
  TERMINATION_REASON_CANCELLED,
10761
10862
  TERMINATION_REASON_NO_CAPACITY,
10762
10863
  TcpTunnel,
10864
+ UsageClient,
10763
10865
  cancelImageBuild,
10764
10866
  createFileSystem,
10765
10867
  createSandboxImage,