@tensorlakeai/tensorlake 0.0.0-bootstrap.0 → 0.5.145

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 (69) hide show
  1. package/README.md +166 -2
  2. package/bin/function-executor.js +8 -0
  3. package/bin/tensorlake-create-sandbox-image.js +9 -0
  4. package/bin/tensorlake-deploy.cjs +8 -0
  5. package/bin/tensorlake-import-sandbox-image.js +9 -0
  6. package/bin/tensorlake-typescript-function-runner.js +8 -0
  7. package/dist/applications/index.cjs +4821 -0
  8. package/dist/applications/index.cjs.map +1 -0
  9. package/dist/applications/index.d.cts +130 -0
  10. package/dist/applications/index.d.ts +130 -0
  11. package/dist/applications/index.js +4782 -0
  12. package/dist/applications/index.js.map +1 -0
  13. package/dist/function-agent/main.cjs +1838 -0
  14. package/dist/function-agent/main.cjs.map +1 -0
  15. package/dist/function-agent/main.d.cts +3 -0
  16. package/dist/function-agent/main.d.ts +3 -0
  17. package/dist/function-agent/main.js +1825 -0
  18. package/dist/function-agent/main.js.map +1 -0
  19. package/dist/function-executor/main.cjs +4944 -0
  20. package/dist/function-executor/main.cjs.map +1 -0
  21. package/dist/function-executor/main.d.cts +4 -0
  22. package/dist/function-executor/main.d.ts +4 -0
  23. package/dist/function-executor/main.js +4902 -0
  24. package/dist/function-executor/main.js.map +1 -0
  25. package/dist/index.cjs +10184 -0
  26. package/dist/index.cjs.map +1 -0
  27. package/dist/index.d.cts +2431 -0
  28. package/dist/index.d.ts +2431 -0
  29. package/dist/index.js +10108 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/native-worker.cjs +278 -0
  32. package/dist/native-worker.cjs.map +1 -0
  33. package/dist/native-worker.d.cts +2 -0
  34. package/dist/native-worker.d.ts +2 -0
  35. package/dist/native-worker.js +276 -0
  36. package/dist/native-worker.js.map +1 -0
  37. package/dist/remote-CNJ9TmcQ.d.cts +283 -0
  38. package/dist/remote-dblFxKug.d.ts +283 -0
  39. package/dist/sandbox-image-ChzWDeZy.d.cts +357 -0
  40. package/dist/sandbox-image-ChzWDeZy.d.ts +357 -0
  41. package/dist/sandbox-image.cjs +1992 -0
  42. package/dist/sandbox-image.cjs.map +1 -0
  43. package/dist/sandbox-image.d.cts +1 -0
  44. package/dist/sandbox-image.d.ts +1 -0
  45. package/dist/sandbox-image.js +1987 -0
  46. package/dist/sandbox-image.js.map +1 -0
  47. package/lib/libc.cjs +61 -0
  48. package/lib/libc.d.cts +1 -0
  49. package/lib/runtime.cjs +155 -0
  50. package/package.json +104 -4
  51. package/runtime/function-executor/manifest.json +59 -0
  52. package/runtime/function-executor/package/bin/function-executor.js +8 -0
  53. package/runtime/function-executor/package/dist/function-executor/main.js +4902 -0
  54. package/runtime/function-executor/package/dist/function-executor/main.js.map +1 -0
  55. package/runtime/function-executor/package/dist/native-worker.cjs +278 -0
  56. package/runtime/function-executor/package/dist/native-worker.cjs.map +1 -0
  57. package/runtime/function-executor/package/npm-shrinkwrap.json +475 -0
  58. package/runtime/function-executor/package/package.json +22 -0
  59. package/runtime/function-executor/package/proto/README.md +18 -0
  60. package/runtime/function-executor/package/proto/tensorlake/function_executor/proto/function_executor.proto +613 -0
  61. package/runtime/function-executor/package/proto/tensorlake/function_executor/proto/status.proto +42 -0
  62. package/runtime/typescript-function-runner/manifest.json +44 -0
  63. package/runtime/typescript-function-runner/package/bin/tensorlake-typescript-function-runner.js +8 -0
  64. package/runtime/typescript-function-runner/package/dist/function-agent/main.js +1825 -0
  65. package/runtime/typescript-function-runner/package/dist/function-agent/main.js.map +1 -0
  66. package/runtime/typescript-function-runner/package/dist/native-worker.cjs +278 -0
  67. package/runtime/typescript-function-runner/package/dist/native-worker.cjs.map +1 -0
  68. package/runtime/typescript-function-runner/package/npm-shrinkwrap.json +586 -0
  69. package/runtime/typescript-function-runner/package/package.json +25 -0
@@ -0,0 +1,4821 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
11
+ var __commonJS = (cb, mod) => function __require() {
12
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
13
+ };
14
+ var __export = (target, all) => {
15
+ for (var name in all)
16
+ __defProp(target, name, { get: all[name], enumerable: true });
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") {
20
+ for (let key of __getOwnPropNames(from))
21
+ if (!__hasOwnProp.call(to, key) && key !== except)
22
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23
+ }
24
+ return to;
25
+ };
26
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
27
+ // If the importer is in node compatibility mode or this is not an ESM
28
+ // file that has been converted to a CommonJS file using a Babel-
29
+ // compatible transform (i.e. "__esModule" has not been set), then set
30
+ // "default" to the CommonJS "module.exports" for node compatibility.
31
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
32
+ mod
33
+ ));
34
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
35
+
36
+ // node_modules/tsup/assets/cjs_shims.js
37
+ var getImportMetaUrl, importMetaUrl;
38
+ var init_cjs_shims = __esm({
39
+ "node_modules/tsup/assets/cjs_shims.js"() {
40
+ "use strict";
41
+ getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
42
+ importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
43
+ }
44
+ });
45
+
46
+ // src/defaults.ts
47
+ var SDK_VERSION, API_URL, API_KEY, NAMESPACE, SANDBOX_PROXY_URL, DEFAULT_HTTP_TIMEOUT_MS, MAX_RETRIES, RETRY_BACKOFF_MS;
48
+ var init_defaults = __esm({
49
+ "src/defaults.ts"() {
50
+ "use strict";
51
+ init_cjs_shims();
52
+ SDK_VERSION = "0.5.145";
53
+ API_URL = process.env.TENSORLAKE_API_URL ?? "https://api.tensorlake.ai";
54
+ API_KEY = process.env.TENSORLAKE_API_KEY ?? void 0;
55
+ NAMESPACE = process.env.INDEXIFY_NAMESPACE ?? "default";
56
+ SANDBOX_PROXY_URL = process.env.TENSORLAKE_SANDBOX_PROXY_URL ?? "https://sandbox.tensorlake.ai";
57
+ DEFAULT_HTTP_TIMEOUT_MS = 3e5;
58
+ MAX_RETRIES = 3;
59
+ RETRY_BACKOFF_MS = 500;
60
+ }
61
+ });
62
+
63
+ // src/models.ts
64
+ function snakeToCamel(str) {
65
+ return str.replace(/_([a-z])/g, (_, ch) => ch.toUpperCase());
66
+ }
67
+ function parseTimestamp(v) {
68
+ if (v == null) return void 0;
69
+ if (v instanceof Date) return v;
70
+ if (typeof v === "string") {
71
+ const parsed = Date.parse(v);
72
+ return Number.isNaN(parsed) ? void 0 : new Date(parsed);
73
+ }
74
+ const ts = Number(v);
75
+ if (isNaN(ts)) return void 0;
76
+ if (ts > 1e15) return new Date(ts / 1e3);
77
+ if (ts > 1e12) return new Date(ts);
78
+ return new Date(ts * 1e3);
79
+ }
80
+ function fromSnakeKeys(obj, idField) {
81
+ if (Array.isArray(obj))
82
+ return obj.map((item) => fromSnakeKeys(item, idField));
83
+ if (obj !== null && typeof obj === "object" && !(obj instanceof Date)) {
84
+ const result = {};
85
+ for (const [k, v] of Object.entries(obj)) {
86
+ let key;
87
+ if (k === "id" && idField) {
88
+ key = idField;
89
+ } else {
90
+ key = snakeToCamel(k);
91
+ }
92
+ if (key.endsWith("At") || key === "timestamp" || key === "startedAt" || key === "endedAt") {
93
+ result[key] = parseTimestamp(v);
94
+ } else if (typeof v === "object" && v !== null && !Array.isArray(v)) {
95
+ result[key] = fromSnakeKeys(v);
96
+ } else if (Array.isArray(v)) {
97
+ result[key] = v.map((item) => fromSnakeKeys(item));
98
+ } else {
99
+ result[key] = v === null ? void 0 : v;
100
+ }
101
+ }
102
+ return result;
103
+ }
104
+ return obj;
105
+ }
106
+ var init_models = __esm({
107
+ "src/models.ts"() {
108
+ "use strict";
109
+ init_cjs_shims();
110
+ }
111
+ });
112
+
113
+ // src/errors.ts
114
+ function formatErrorDetails(errorDetails) {
115
+ if (errorDetails == null) return void 0;
116
+ if (typeof errorDetails === "string") {
117
+ const detail = errorDetails.trim();
118
+ return detail || void 0;
119
+ }
120
+ if (Array.isArray(errorDetails)) {
121
+ const parts = errorDetails.map((item) => formatErrorDetails(item)).filter((item) => Boolean(item));
122
+ return parts.length > 0 ? parts.join("; ") : JSON.stringify(errorDetails);
123
+ }
124
+ if (typeof errorDetails === "object") {
125
+ for (const key of ["message", "detail", "error", "reason"]) {
126
+ const value = errorDetails[key];
127
+ if (typeof value === "string" && value.trim()) {
128
+ return value.trim();
129
+ }
130
+ }
131
+ return JSON.stringify(errorDetails);
132
+ }
133
+ return String(errorDetails);
134
+ }
135
+ var SandboxException, SandboxError, SandboxResizeError, SandboxConnectionError, SandboxNotFoundError, PoolNotFoundError, PoolInUseError, RemoteAPIError, RequestNotFinishedError, RequestFailedError, RequestExecutionError;
136
+ var init_errors = __esm({
137
+ "src/errors.ts"() {
138
+ "use strict";
139
+ init_cjs_shims();
140
+ SandboxException = class extends Error {
141
+ constructor(message) {
142
+ super(message);
143
+ this.name = "SandboxException";
144
+ }
145
+ };
146
+ SandboxError = class extends SandboxException {
147
+ reason;
148
+ sandboxId;
149
+ constructor(message, options) {
150
+ super(message);
151
+ this.name = "SandboxError";
152
+ if (options?.reason !== void 0) this.reason = options.reason;
153
+ if (options?.sandboxId !== void 0) this.sandboxId = options.sandboxId;
154
+ }
155
+ };
156
+ SandboxResizeError = class extends SandboxError {
157
+ generation;
158
+ info;
159
+ constructor(payload) {
160
+ const resources = payload.info?.resources;
161
+ const allocation = resources ? `${resources.cpus} CPUs, ${resources.memoryMb} MiB memory, ${resources.diskMb} MiB disk` : "unavailable";
162
+ super(
163
+ `Sandbox ${payload.sandboxId} resize generation ${payload.generation}: ${payload.message}; last confirmed allocation: ${allocation}`,
164
+ { reason: payload.reason, sandboxId: payload.sandboxId }
165
+ );
166
+ this.name = "SandboxResizeError";
167
+ this.generation = payload.generation;
168
+ this.info = payload.info ?? void 0;
169
+ }
170
+ /** Last confirmed allocation, if an observation was available. */
171
+ get confirmedResources() {
172
+ return this.info?.resources;
173
+ }
174
+ };
175
+ SandboxConnectionError = class extends SandboxError {
176
+ constructor(message, options) {
177
+ super(`Connection error: ${message}`);
178
+ this.name = "SandboxConnectionError";
179
+ if (options?.cause !== void 0) this.cause = options.cause;
180
+ }
181
+ };
182
+ SandboxNotFoundError = class extends SandboxError {
183
+ constructor(sandboxId) {
184
+ super(`Sandbox not found: ${sandboxId}`, { sandboxId });
185
+ this.name = "SandboxNotFoundError";
186
+ }
187
+ };
188
+ PoolNotFoundError = class extends SandboxError {
189
+ poolId;
190
+ constructor(poolId) {
191
+ super(`Sandbox pool not found: ${poolId}`);
192
+ this.name = "PoolNotFoundError";
193
+ this.poolId = poolId;
194
+ }
195
+ };
196
+ PoolInUseError = class extends SandboxError {
197
+ poolId;
198
+ constructor(poolId, message) {
199
+ const base = `Cannot delete pool ${poolId}: pool is in use`;
200
+ super(message ? `${base} - ${message}` : base);
201
+ this.name = "PoolInUseError";
202
+ this.poolId = poolId;
203
+ }
204
+ };
205
+ RemoteAPIError = class extends SandboxError {
206
+ statusCode;
207
+ /** Original response body, retained for compatibility and diagnostics. */
208
+ responseMessage;
209
+ errorDetails;
210
+ constructor(statusCode, message) {
211
+ let failure;
212
+ try {
213
+ const payload = JSON.parse(message);
214
+ if (payload && typeof payload === "object" && !Array.isArray(payload)) {
215
+ const record = payload;
216
+ if (typeof record.sandbox_id === "string" && record.sandbox_id.trim() && (record.status === "failed" || record.status === "terminated"))
217
+ failure = record;
218
+ }
219
+ } catch {
220
+ }
221
+ const sandboxId = failure?.sandbox_id;
222
+ const rawReason = failure?.reason ?? failure?.termination_reason;
223
+ const reason = typeof rawReason === "string" ? rawReason : void 0;
224
+ const errorDetails = failure?.error_details;
225
+ let displayMessage = message;
226
+ if (failure) {
227
+ displayMessage = `Sandbox ${sandboxId} ${failure.status}`;
228
+ if (reason) displayMessage += ` (${reason})`;
229
+ const detail = formatErrorDetails(errorDetails);
230
+ if (detail) displayMessage += `: ${detail}`;
231
+ if (!reason && !detail) displayMessage = message;
232
+ }
233
+ super(`API error (status ${statusCode}): ${displayMessage}`, {
234
+ reason,
235
+ sandboxId
236
+ });
237
+ this.errorDetails = errorDetails;
238
+ this.name = "RemoteAPIError";
239
+ this.statusCode = statusCode;
240
+ this.responseMessage = message;
241
+ }
242
+ };
243
+ RequestNotFinishedError = class extends Error {
244
+ constructor() {
245
+ super("Request has not finished yet");
246
+ this.name = "RequestNotFinishedError";
247
+ }
248
+ };
249
+ RequestFailedError = class extends Error {
250
+ failure;
251
+ constructor(failure) {
252
+ super(`Request failed: ${failure}`);
253
+ this.name = "RequestFailedError";
254
+ this.failure = failure;
255
+ }
256
+ };
257
+ RequestExecutionError = class extends Error {
258
+ functionName;
259
+ constructor(message, functionName) {
260
+ super(
261
+ functionName ? `Request error in ${functionName}: ${message}` : message
262
+ );
263
+ this.name = "RequestExecutionError";
264
+ this.functionName = functionName;
265
+ }
266
+ };
267
+ }
268
+ });
269
+
270
+ // src/native-worker-protocol.ts
271
+ var cancelNativeCall, closeNativeHandle;
272
+ var init_native_worker_protocol = __esm({
273
+ "src/native-worker-protocol.ts"() {
274
+ "use strict";
275
+ init_cjs_shims();
276
+ cancelNativeCall = /* @__PURE__ */ Symbol.for("tensorlake.native.cancel.v1");
277
+ closeNativeHandle = /* @__PURE__ */ Symbol.for("tensorlake.native.close.v1");
278
+ }
279
+ });
280
+
281
+ // src/url.ts
282
+ function trimTrailingSlashes(url) {
283
+ return url.endsWith("/") ? url.slice(0, -1) : url;
284
+ }
285
+ function resolveProxyTarget(proxyUrl, sandboxId) {
286
+ try {
287
+ const parsed = new URL(proxyUrl);
288
+ const host = parsed.hostname;
289
+ if (host === "localhost" || host === "127.0.0.1") {
290
+ return {
291
+ baseUrl: trimTrailingSlashes(proxyUrl),
292
+ hostHeader: `${sandboxId}.local`,
293
+ sandboxIdHeader: void 0
294
+ };
295
+ }
296
+ const port = parsed.port ? `:${parsed.port}` : "";
297
+ return {
298
+ baseUrl: `${parsed.protocol}//${host}${port}`,
299
+ hostHeader: void 0,
300
+ sandboxIdHeader: sandboxId
301
+ };
302
+ } catch {
303
+ return {
304
+ baseUrl: `${trimTrailingSlashes(proxyUrl)}/${sandboxId}`,
305
+ hostHeader: void 0,
306
+ sandboxIdHeader: void 0
307
+ };
308
+ }
309
+ }
310
+ var init_url = __esm({
311
+ "src/url.ts"() {
312
+ "use strict";
313
+ init_cjs_shims();
314
+ init_defaults();
315
+ }
316
+ });
317
+
318
+ // src/native-worker-client.ts
319
+ function createWorkerBinding(runtime) {
320
+ return {
321
+ NativeCloudClient: class {
322
+ constructor(...args) {
323
+ return runtime.handle("NativeCloudClient", args);
324
+ }
325
+ },
326
+ NativeSandboxClient: class {
327
+ constructor(...args) {
328
+ return runtime.handle("NativeSandboxClient", args);
329
+ }
330
+ },
331
+ NativeSandboxProxyClient: class {
332
+ constructor(...args) {
333
+ return runtime.handle("NativeSandboxProxyClient", args);
334
+ }
335
+ },
336
+ NativeRepositoryClient: class {
337
+ constructor(...args) {
338
+ return runtime.handle("NativeRepositoryClient", args);
339
+ }
340
+ },
341
+ validateManagedName: (name) => runtime.call(void 0, "validateManagedName", [name])
342
+ };
343
+ }
344
+ function workerBinding() {
345
+ return createWorkerBinding(
346
+ runtimes[runtimeKey] ??= new NativeWorkerClient()
347
+ );
348
+ }
349
+ function releaseNativeHandle(handle) {
350
+ handle?.[closeNativeHandle]?.();
351
+ }
352
+ var import_node_module, import_node_worker_threads, NativeWorkerClient, runtimeKey, runtimes;
353
+ var init_native_worker_client = __esm({
354
+ "src/native-worker-client.ts"() {
355
+ "use strict";
356
+ init_cjs_shims();
357
+ import_node_module = require("module");
358
+ import_node_worker_threads = require("worker_threads");
359
+ init_native_worker_protocol();
360
+ init_url();
361
+ NativeWorkerClient = class {
362
+ constructor(workerPath = () => (0, import_node_module.createRequire)(importMetaUrl).resolve(
363
+ "@tensorlakeai/tensorlake/internal/native-worker"
364
+ )) {
365
+ this.workerPath = workerPath;
366
+ }
367
+ worker;
368
+ nextId = 1;
369
+ registered = /* @__PURE__ */ new Set();
370
+ pending = /* @__PURE__ */ new Map();
371
+ finalizers = new FinalizationRegistry(
372
+ (id) => this.release(id)
373
+ );
374
+ handle(kind, args, parent) {
375
+ const handle = { id: this.nextId++, kind, args, parent };
376
+ this.finalizers.register(handle, handle.id);
377
+ let closed = false;
378
+ return new Proxy(
379
+ {},
380
+ {
381
+ get: (_target, method) => {
382
+ if (method === "then") return void 0;
383
+ if (method === closeNativeHandle)
384
+ return () => {
385
+ closed = true;
386
+ this.release(handle.id);
387
+ };
388
+ if (method === "connectProxy")
389
+ return (...proxyArgs) => {
390
+ if (closed) throw new Error("Tensorlake native client is closed");
391
+ return this.handle("NativeSandboxProxyClient", proxyArgs, handle);
392
+ };
393
+ if (method === "baseUrl")
394
+ return () => resolveProxyTarget(String(args[0]), String(args[1])).baseUrl;
395
+ if (typeof method !== "string") return void 0;
396
+ return (...callArgs) => {
397
+ if (closed)
398
+ return Promise.reject(
399
+ new Error("Tensorlake native client is closed")
400
+ );
401
+ const emit = typeof callArgs.at(-1) === "function" ? callArgs.pop() : void 0;
402
+ return this.call(handle, method, callArgs, emit);
403
+ };
404
+ }
405
+ }
406
+ );
407
+ }
408
+ call(handle, method, args, emit) {
409
+ const id = this.nextId++;
410
+ let worker;
411
+ const promise = new Promise((resolve, reject) => {
412
+ try {
413
+ worker = this.getWorker();
414
+ this.pending.set(id, { resolve, reject, emit, handle });
415
+ worker.ref();
416
+ if (handle) this.register(handle, worker);
417
+ this.send(worker, {
418
+ type: "call",
419
+ id,
420
+ handleId: handle?.id,
421
+ method,
422
+ args,
423
+ stream: !!emit
424
+ });
425
+ } catch (error) {
426
+ this.pending.delete(id);
427
+ this.unrefIfIdle();
428
+ reject(error);
429
+ }
430
+ });
431
+ promise[cancelNativeCall] = () => {
432
+ const pending = this.pending.get(id);
433
+ if (pending && worker) {
434
+ pending.emit = void 0;
435
+ this.send(worker, { type: "cancel", id });
436
+ }
437
+ };
438
+ return promise;
439
+ }
440
+ getWorker() {
441
+ if (this.worker) return this.worker;
442
+ const worker = new import_node_worker_threads.Worker(this.workerPath(), {
443
+ // The bundled worker needs no application loaders or telemetry preloads.
444
+ // NODE_OPTIONS is parsed independently of execArgv by Node.
445
+ execArgv: [],
446
+ env: { ...process.env, NODE_OPTIONS: "" },
447
+ name: "tensorlake-native"
448
+ });
449
+ this.worker = worker;
450
+ worker.on("message", (message) => {
451
+ const pending = this.pending.get(message.id);
452
+ if (!pending || this.worker !== worker) return;
453
+ if (message.type === "event") {
454
+ Promise.resolve().then(() => pending.emit?.(message.value)).then(
455
+ () => {
456
+ if (this.worker === worker)
457
+ this.send(worker, { type: "ack", id: message.id });
458
+ },
459
+ (error) => {
460
+ this.send(worker, { type: "cancel", id: message.id });
461
+ pending.reject(error);
462
+ }
463
+ );
464
+ return;
465
+ }
466
+ this.pending.delete(message.id);
467
+ if (message.type === "error") {
468
+ const error = new Error(message.error.message);
469
+ error.name = message.error.name;
470
+ error.stack = message.error.stack ?? error.stack;
471
+ pending.reject(error);
472
+ } else {
473
+ pending.resolve(message.value);
474
+ }
475
+ this.unrefIfIdle();
476
+ });
477
+ const fail = (error) => {
478
+ if (this.worker !== worker) return;
479
+ this.worker = void 0;
480
+ this.registered.clear();
481
+ for (const pending of this.pending.values()) pending.reject(error);
482
+ this.pending.clear();
483
+ void worker.terminate();
484
+ };
485
+ worker.on("error", fail);
486
+ worker.on("messageerror", fail);
487
+ worker.on(
488
+ "exit",
489
+ (code) => fail(
490
+ new Error(
491
+ `Tensorlake native worker exited (${code}); in-flight operations were not retried`
492
+ )
493
+ )
494
+ );
495
+ worker.unref();
496
+ return worker;
497
+ }
498
+ register(handle, worker) {
499
+ if (this.registered.has(handle.id)) return;
500
+ if (handle.parent) this.register(handle.parent, worker);
501
+ this.send(worker, {
502
+ type: "create",
503
+ handle: { id: handle.id, kind: handle.kind, args: handle.args },
504
+ parentId: handle.parent?.id
505
+ });
506
+ this.registered.add(handle.id);
507
+ }
508
+ release(handleId) {
509
+ if (this.worker && this.registered.delete(handleId))
510
+ this.send(this.worker, { type: "release", handleId });
511
+ }
512
+ send(worker, message) {
513
+ worker.postMessage(message);
514
+ }
515
+ unrefIfIdle() {
516
+ if (this.pending.size === 0) this.worker?.unref();
517
+ }
518
+ };
519
+ runtimeKey = /* @__PURE__ */ Symbol.for(
520
+ `tensorlake.native.worker.${false ? "source" : "0.5.145"}.v1`
521
+ );
522
+ runtimes = globalThis;
523
+ }
524
+ });
525
+
526
+ // src/native-sandbox.ts
527
+ function loadNativeSandboxBinding() {
528
+ return cachedBinding ??= workerBinding();
529
+ }
530
+ function parseNativeError(error) {
531
+ const message = error instanceof Error ? error.message : typeof error === "string" ? error : "";
532
+ if (!message) return null;
533
+ try {
534
+ const parsed = JSON.parse(message);
535
+ if (parsed && typeof parsed.category === "string") {
536
+ return {
537
+ category: parsed.category,
538
+ status: typeof parsed.status === "number" ? parsed.status : null,
539
+ message: typeof parsed.message === "string" ? parsed.message : message
540
+ };
541
+ }
542
+ } catch {
543
+ }
544
+ return null;
545
+ }
546
+ function translateNativeError(error, context) {
547
+ const payload = parseNativeError(error);
548
+ if (!payload) {
549
+ if (error instanceof Error) return error;
550
+ return new SandboxError(String(error));
551
+ }
552
+ const { category, status, message } = payload;
553
+ if (category === "resize") {
554
+ return new SandboxResizeError(
555
+ fromSnakeKeys(JSON.parse(message), "sandboxId")
556
+ );
557
+ }
558
+ if (category === "connection") {
559
+ return new SandboxConnectionError(message, { cause: error });
560
+ }
561
+ if (status === 404) {
562
+ if (context?.notFoundKind === "pool" && context.poolId) {
563
+ return new PoolNotFoundError(context.poolId);
564
+ }
565
+ if (context?.notFoundKind === "sandbox" && context.sandboxId) {
566
+ return new SandboxNotFoundError(context.sandboxId);
567
+ }
568
+ return new RemoteAPIError(404, message);
569
+ }
570
+ if (status === 409 && context?.poolId) {
571
+ return new PoolInUseError(context.poolId, message);
572
+ }
573
+ if (typeof status === "number") {
574
+ return new RemoteAPIError(status, message);
575
+ }
576
+ return new SandboxError(message);
577
+ }
578
+ async function callNative(fn, context) {
579
+ try {
580
+ return await fn();
581
+ } catch (error) {
582
+ throw translateNativeError(error, context);
583
+ }
584
+ }
585
+ async function* nativeEventStream(start, context, signal) {
586
+ if (signal?.aborted) return;
587
+ const queue = [];
588
+ let wake;
589
+ let finished = false;
590
+ let stopped = false;
591
+ let failure;
592
+ const notify = () => {
593
+ const resolve = wake;
594
+ wake = void 0;
595
+ resolve?.();
596
+ };
597
+ const emit = (value) => {
598
+ if (stopped) return Promise.resolve();
599
+ return new Promise((consumed) => {
600
+ queue.push({ value, consumed });
601
+ notify();
602
+ });
603
+ };
604
+ let call;
605
+ const onAbort = () => {
606
+ stopped = true;
607
+ call?.[cancelNativeCall]?.();
608
+ notify();
609
+ };
610
+ signal?.addEventListener("abort", onAbort, { once: true });
611
+ try {
612
+ call = start(emit);
613
+ void call.catch((error) => {
614
+ failure = error;
615
+ }).finally(() => {
616
+ finished = true;
617
+ notify();
618
+ });
619
+ while (!stopped) {
620
+ const event = queue.shift();
621
+ if (event) {
622
+ try {
623
+ yield JSON.parse(event.value);
624
+ } finally {
625
+ event.consumed();
626
+ }
627
+ } else if (finished) {
628
+ break;
629
+ } else {
630
+ await new Promise((resolve) => {
631
+ wake = resolve;
632
+ });
633
+ }
634
+ }
635
+ if (!stopped && failure !== void 0) throw translateNativeError(failure, context);
636
+ } finally {
637
+ stopped = true;
638
+ signal?.removeEventListener("abort", onAbort);
639
+ call?.[cancelNativeCall]?.();
640
+ for (const event of queue) event.consumed();
641
+ }
642
+ }
643
+ var cachedBinding;
644
+ var init_native_sandbox = __esm({
645
+ "src/native-sandbox.ts"() {
646
+ "use strict";
647
+ init_cjs_shims();
648
+ init_models();
649
+ init_errors();
650
+ init_native_worker_client();
651
+ init_native_worker_protocol();
652
+ }
653
+ });
654
+
655
+ // src/native-cloud.ts
656
+ async function serializeRequest(method, path3, options) {
657
+ const headers = { ...options?.headers };
658
+ let body = options?.body;
659
+ if (options?.json !== void 0) {
660
+ body = JSON.stringify(options.json);
661
+ if (!Object.keys(headers).some((key) => key.toLowerCase() === "content-type")) {
662
+ headers["Content-Type"] = "application/json";
663
+ }
664
+ }
665
+ const request = {
666
+ method,
667
+ path: path3,
668
+ headersJson: JSON.stringify(headers),
669
+ statusOnlyCodes: [...options?.statusOnlyCodes ?? []]
670
+ };
671
+ if (body instanceof FormData) {
672
+ request.parts = [];
673
+ for (const [name, value] of body.entries()) {
674
+ request.parts.push(typeof value === "string" ? { name, data: Buffer.from(value) } : { name, data: Buffer.from(await value.arrayBuffer()), filename: value.name, contentType: value.type || "application/octet-stream" });
675
+ }
676
+ } else if (body !== void 0) {
677
+ if (body instanceof Blob) request.body = Buffer.from(await body.arrayBuffer());
678
+ else if (typeof body === "string") request.body = Buffer.from(body);
679
+ else if (body instanceof ArrayBuffer) request.body = Buffer.from(new Uint8Array(body));
680
+ else request.body = Buffer.from(body);
681
+ }
682
+ return request;
683
+ }
684
+ var NativeCloudTransport;
685
+ var init_native_cloud = __esm({
686
+ "src/native-cloud.ts"() {
687
+ "use strict";
688
+ init_cjs_shims();
689
+ init_native_sandbox();
690
+ init_native_worker_client();
691
+ NativeCloudTransport = class {
692
+ constructor(options) {
693
+ this.options = options;
694
+ if (!Number.isSafeInteger(options.maxRetries) || options.maxRetries < 0 || options.maxRetries > 4294967295) {
695
+ throw new RangeError("maxRetries must be a non-negative 32-bit integer");
696
+ }
697
+ if (!Number.isFinite(options.retryBackoffMs) || options.retryBackoffMs < 0) {
698
+ throw new RangeError("retryBackoffMs must be a non-negative finite number");
699
+ }
700
+ }
701
+ native;
702
+ closed = false;
703
+ client() {
704
+ if (this.closed) throw new Error("Tensorlake native client is closed");
705
+ if (this.native) return this.native;
706
+ const ctor = loadNativeSandboxBinding().NativeCloudClient;
707
+ if (!ctor) throw new Error("Native binding does not export NativeCloudClient; rebuild with 'npm run build:native'");
708
+ return this.native = new ctor(JSON.stringify(this.options));
709
+ }
710
+ close() {
711
+ this.closed = true;
712
+ releaseNativeHandle(this.native ?? null);
713
+ this.native = void 0;
714
+ }
715
+ async requestResponse(method, path3, options) {
716
+ const request = await serializeRequest(method, path3, options);
717
+ const raw = await callNative(() => this.client().request(request));
718
+ const response = new Response(
719
+ [204, 205, 304].includes(raw.status) ? null : Uint8Array.from(raw.data).buffer,
720
+ { status: raw.status, headers: JSON.parse(raw.headersJson) }
721
+ );
722
+ return Object.assign(response, { traceId: raw.traceId });
723
+ }
724
+ async requestJson(method, path3) {
725
+ const response = await this.requestResponse(method, path3);
726
+ const text = await response.text();
727
+ const value = text ? JSON.parse(text) : null;
728
+ return Object.assign(value ?? {}, { traceId: response.traceId });
729
+ }
730
+ async *stream(method, path3, signal) {
731
+ if (signal?.aborted) return;
732
+ const request = await serializeRequest(method, path3, { headers: { Accept: "text/event-stream" } });
733
+ yield* nativeEventStream((emit) => this.client().stream(request, emit), void 0, signal);
734
+ }
735
+ };
736
+ }
737
+ });
738
+
739
+ // src/cloud-client.ts
740
+ function secretFromMetadata(metadata) {
741
+ return {
742
+ id: metadata.id,
743
+ name: metadata.name,
744
+ createdAt: new Date(metadata.created_at_ms)
745
+ };
746
+ }
747
+ function applicationAllowsUnauthenticatedRequests(manifest) {
748
+ return Array.isArray(manifest.allow) && manifest.allow.includes(UNAUTHENTICATED_REQUESTS);
749
+ }
750
+ function publicEndpointIdFromManifest(manifest) {
751
+ for (const key of ["public_endpoint_id", "publicEndpointId"]) {
752
+ const value = manifest[key];
753
+ if (typeof value === "string" && value.length > 0) {
754
+ return value;
755
+ }
756
+ }
757
+ return void 0;
758
+ }
759
+ function generatePublicEndpointId() {
760
+ return `endpoint_${(0, import_nanoid.nanoid)()}`;
761
+ }
762
+ function createApplicationBuildForm(request, imageContexts) {
763
+ const contextsByPartName = /* @__PURE__ */ new Map();
764
+ for (const context of imageContexts) {
765
+ if (contextsByPartName.has(context.contextTarPartName)) {
766
+ throw new Error(
767
+ `duplicate image context part name '${context.contextTarPartName}'`
768
+ );
769
+ }
770
+ contextsByPartName.set(context.contextTarPartName, context);
771
+ }
772
+ const form = new FormData();
773
+ form.append(
774
+ "app_version",
775
+ new Blob([JSON.stringify(request)], { type: "application/json" }),
776
+ "app_version"
777
+ );
778
+ for (const image of request.images) {
779
+ const context = contextsByPartName.get(image.contextTarPartName);
780
+ if (!context) {
781
+ throw new Error(
782
+ `missing image context for part '${image.contextTarPartName}'`
783
+ );
784
+ }
785
+ form.append(
786
+ image.contextTarPartName,
787
+ new Blob([toBlobPart(context.contextTarGz)]),
788
+ `${image.contextTarPartName}.tar.gz`
789
+ );
790
+ }
791
+ for (const context of imageContexts) {
792
+ if (!request.images.some((image) => image.contextTarPartName === context.contextTarPartName)) {
793
+ throw new Error(
794
+ `unexpected image context for part '${context.contextTarPartName}'`
795
+ );
796
+ }
797
+ }
798
+ return form;
799
+ }
800
+ function trimTrailingSlashes2(value) {
801
+ return value.endsWith("/") ? value.slice(0, -1) : value;
802
+ }
803
+ function nextRequestPath(next) {
804
+ const schemeIndex = next.indexOf("://");
805
+ if (schemeIndex !== -1) {
806
+ const afterScheme = next.slice(schemeIndex + 3);
807
+ const slashIndex = afterScheme.indexOf("/");
808
+ return slashIndex === -1 ? "/" : afterScheme.slice(slashIndex);
809
+ }
810
+ return next.startsWith("/") ? next : `/${next}`;
811
+ }
812
+ function toBlobPart(data) {
813
+ if (typeof data === "string" || data instanceof Blob) {
814
+ return data;
815
+ }
816
+ if (data instanceof Uint8Array) {
817
+ return Uint8Array.from(data).buffer;
818
+ }
819
+ return data;
820
+ }
821
+ function toRequestBody(data) {
822
+ return toBlobPart(data);
823
+ }
824
+ async function parseJsonResponse(response) {
825
+ const text = await response.text();
826
+ if (!text) {
827
+ return void 0;
828
+ }
829
+ return JSON.parse(text);
830
+ }
831
+ var import_nanoid, CloudClient, UNAUTHENTICATED_REQUESTS;
832
+ var init_cloud_client = __esm({
833
+ "src/cloud-client.ts"() {
834
+ "use strict";
835
+ init_cjs_shims();
836
+ import_nanoid = require("nanoid");
837
+ init_defaults();
838
+ init_native_cloud();
839
+ init_models();
840
+ CloudClient = class _CloudClient {
841
+ transport;
842
+ organizationId;
843
+ projectId;
844
+ namespace;
845
+ constructor(options) {
846
+ this.organizationId = options?.organizationId;
847
+ this.projectId = options?.projectId;
848
+ this.namespace = options?.namespace ?? NAMESPACE;
849
+ this.transport = new NativeCloudTransport({
850
+ baseUrl: options?.apiUrl ?? API_URL,
851
+ apiKey: options?.apiKey ?? API_KEY,
852
+ organizationId: this.organizationId,
853
+ projectId: this.projectId,
854
+ maxRetries: options?.maxRetries ?? MAX_RETRIES,
855
+ retryBackoffMs: options?.retryBackoffMs ?? RETRY_BACKOFF_MS,
856
+ timeoutMs: DEFAULT_HTTP_TIMEOUT_MS,
857
+ userAgent: `tensorlake-typescript-sdk/${SDK_VERSION}`
858
+ });
859
+ }
860
+ static forCloud(options) {
861
+ return new _CloudClient(options);
862
+ }
863
+ close() {
864
+ this.transport.close();
865
+ }
866
+ async upsertApplication(manifest, codeZip, upgradeRunningRequests = false) {
867
+ const applicationManifest = { ...manifest };
868
+ let publicEndpointId = publicEndpointIdFromManifest(applicationManifest);
869
+ if (applicationAllowsUnauthenticatedRequests(applicationManifest) && publicEndpointId === void 0) {
870
+ const applicationName = applicationManifest.name;
871
+ if (typeof applicationName === "string" && applicationName.length > 0) {
872
+ publicEndpointId = await this.existingApplicationPublicEndpointId(applicationName);
873
+ }
874
+ publicEndpointId ??= generatePublicEndpointId();
875
+ }
876
+ if (publicEndpointId !== void 0) {
877
+ applicationManifest.public_endpoint_id = publicEndpointId;
878
+ delete applicationManifest.publicEndpointId;
879
+ }
880
+ const form = new FormData();
881
+ form.append(
882
+ "code",
883
+ new Blob([toBlobPart(codeZip)], { type: "application/zip" }),
884
+ "code.zip"
885
+ );
886
+ form.append("code_content_type", "application/zip");
887
+ form.append("application", JSON.stringify(applicationManifest));
888
+ form.append(
889
+ "upgrade_requests_to_latest_code",
890
+ String(upgradeRunningRequests)
891
+ );
892
+ await this.transport.requestResponse("POST", this.namespacePath("applications"), {
893
+ body: form
894
+ });
895
+ }
896
+ async deleteApplication(applicationName) {
897
+ await this.transport.requestResponse(
898
+ "DELETE",
899
+ this.namespacePath(`applications/${encodeURIComponent(applicationName)}`)
900
+ );
901
+ }
902
+ async deleteSandboxImage(imageName) {
903
+ await this.transport.requestResponse(
904
+ "DELETE",
905
+ this.namespacePath(`sandbox-images/${encodeURIComponent(imageName)}`)
906
+ );
907
+ }
908
+ /**
909
+ * Look up a registered sandbox image (template) by its registered name.
910
+ *
911
+ * Returns the template, or `null` when no image with that name exists.
912
+ * API-key clients may omit organization/project IDs and use the
913
+ * token-scoped Platform API route directly. Explicit scope remains
914
+ * available for PAT callers.
915
+ */
916
+ async findSandboxImageByName(imageName, options) {
917
+ const base = this.platformProjectPath(
918
+ "sandbox-templates",
919
+ options?.organizationId,
920
+ options?.projectId
921
+ );
922
+ const response = await this.transport.requestResponse(
923
+ "GET",
924
+ `${base}/by-name/${encodeURIComponent(imageName)}`,
925
+ { statusOnlyCodes: /* @__PURE__ */ new Set([404]) }
926
+ );
927
+ if (response.status === 404) {
928
+ return null;
929
+ }
930
+ const raw = await parseJsonResponse(response);
931
+ return fromSnakeKeys(raw);
932
+ }
933
+ /**
934
+ * List all registered sandbox images (templates), following pagination to
935
+ * the end. API-key clients may omit organization/project IDs and use the
936
+ * token-scoped Platform API route directly.
937
+ */
938
+ async listSandboxImages(options) {
939
+ const base = this.platformProjectPath(
940
+ "sandbox-templates",
941
+ options?.organizationId,
942
+ options?.projectId
943
+ );
944
+ let path3 = `${base}?pageSize=100`;
945
+ const templates = [];
946
+ while (path3 !== null) {
947
+ const page = await this.transport.requestJson(
948
+ "GET",
949
+ path3
950
+ );
951
+ for (const item of page.items ?? []) {
952
+ templates.push(fromSnakeKeys(item));
953
+ }
954
+ const next = page.pagination?.next;
955
+ path3 = next ? nextRequestPath(next) : null;
956
+ }
957
+ return templates;
958
+ }
959
+ async applications() {
960
+ const raw = await this.transport.requestJson(
961
+ "GET",
962
+ this.namespacePath("applications")
963
+ );
964
+ return (raw.applications ?? []).map(
965
+ (application) => fromSnakeKeys(application)
966
+ );
967
+ }
968
+ async applicationManifest(applicationName) {
969
+ const raw = await this.transport.requestJson(
970
+ "GET",
971
+ this.namespacePath(`applications/${encodeURIComponent(applicationName)}`)
972
+ );
973
+ return fromSnakeKeys(raw);
974
+ }
975
+ async runRequest(applicationName, inputs = []) {
976
+ const path3 = this.namespacePath(
977
+ `applications/${encodeURIComponent(applicationName)}`
978
+ );
979
+ const response = inputs.length === 0 ? await this.transport.requestResponse("POST", path3, {
980
+ body: new Uint8Array(),
981
+ headers: { Accept: "application/json" }
982
+ }) : inputs.length === 1 && inputs[0].name === "0" ? await this.transport.requestResponse("POST", path3, {
983
+ body: toRequestBody(inputs[0].data),
984
+ headers: {
985
+ Accept: "application/json",
986
+ "Content-Type": inputs[0].contentType
987
+ }
988
+ }) : await this.runMultipartRequest(path3, inputs);
989
+ const body = await parseJsonResponse(response);
990
+ const requestId = body?.request_id;
991
+ if (!requestId) {
992
+ throw new Error("missing request_id in run request response body");
993
+ }
994
+ return requestId;
995
+ }
996
+ async waitOnRequestCompletion(applicationName, requestId) {
997
+ const stream = this.transport.stream(
998
+ "GET",
999
+ this.namespacePath(
1000
+ `applications/${encodeURIComponent(applicationName)}/requests/${encodeURIComponent(requestId)}/progress`
1001
+ )
1002
+ );
1003
+ for await (const event of stream) {
1004
+ if (Object.prototype.hasOwnProperty.call(event, "RequestFinished")) {
1005
+ return;
1006
+ }
1007
+ }
1008
+ throw new Error("progress stream ended before request completion");
1009
+ }
1010
+ async requestMetadata(applicationName, requestId) {
1011
+ const raw = await this.transport.requestJson(
1012
+ "GET",
1013
+ this.namespacePath(
1014
+ `applications/${encodeURIComponent(applicationName)}/requests/${encodeURIComponent(requestId)}`
1015
+ )
1016
+ );
1017
+ return fromSnakeKeys(raw);
1018
+ }
1019
+ async requestOutput(applicationName, requestId) {
1020
+ const response = await this.transport.requestResponse(
1021
+ "GET",
1022
+ this.namespacePath(
1023
+ `applications/${encodeURIComponent(applicationName)}/requests/${encodeURIComponent(requestId)}/output`
1024
+ )
1025
+ );
1026
+ const serializedValue = new Uint8Array(await response.arrayBuffer());
1027
+ const contentType = response.headers.get("content-type") ?? "";
1028
+ return {
1029
+ serializedValue,
1030
+ contentType
1031
+ };
1032
+ }
1033
+ async listSecrets(options) {
1034
+ const base = this.secretCollectionPath(
1035
+ options?.organizationId,
1036
+ options?.projectId
1037
+ );
1038
+ const raw = await this.transport.requestJson("GET", base);
1039
+ const pageSize = Math.max(0, options?.pageSize ?? 100);
1040
+ return Object.assign(
1041
+ {
1042
+ items: raw.slice(0, pageSize).map(secretFromMetadata),
1043
+ pagination: { total: raw.length }
1044
+ },
1045
+ { traceId: raw.traceId }
1046
+ );
1047
+ }
1048
+ async getSecret(secretId, options) {
1049
+ const base = this.secretCollectionPath(
1050
+ options?.organizationId,
1051
+ options?.projectId
1052
+ );
1053
+ const raw = await this.transport.requestJson(
1054
+ "GET",
1055
+ `${base}/${encodeURIComponent(secretId)}`
1056
+ );
1057
+ return Object.assign(secretFromMetadata(raw), { traceId: raw.traceId });
1058
+ }
1059
+ async upsertSecrets(secrets, options) {
1060
+ const base = this.secretCollectionPath(
1061
+ options?.organizationId,
1062
+ options?.projectId
1063
+ );
1064
+ if (Array.isArray(secrets)) {
1065
+ const results = [];
1066
+ for (const secret of secrets) {
1067
+ results.push(await this.upsertSecret(base, secret));
1068
+ }
1069
+ return results;
1070
+ }
1071
+ return this.upsertSecret(base, secrets);
1072
+ }
1073
+ async deleteSecret(secretId, options) {
1074
+ const base = this.secretCollectionPath(
1075
+ options?.organizationId,
1076
+ options?.projectId
1077
+ );
1078
+ await this.transport.requestResponse(
1079
+ "DELETE",
1080
+ `${base}/${encodeURIComponent(secretId)}`
1081
+ );
1082
+ }
1083
+ async upsertSecret(base, secret) {
1084
+ let response = await this.transport.requestResponse("POST", base, {
1085
+ json: secret,
1086
+ headers: { "Idempotency-Key": (0, import_nanoid.nanoid)() },
1087
+ statusOnlyCodes: /* @__PURE__ */ new Set([409])
1088
+ });
1089
+ if (response.status === 409) {
1090
+ const prefix = base.slice(0, -"/secrets".length);
1091
+ const existing = await this.transport.requestJson(
1092
+ "GET",
1093
+ `${prefix}/secret-names/${encodeURIComponent(secret.name)}`
1094
+ );
1095
+ response = await this.transport.requestResponse(
1096
+ "POST",
1097
+ `${base}/${encodeURIComponent(existing.id)}/versions`,
1098
+ {
1099
+ json: { value: secret.value },
1100
+ headers: { "Idempotency-Key": (0, import_nanoid.nanoid)() }
1101
+ }
1102
+ );
1103
+ }
1104
+ const metadata = await parseJsonResponse(response);
1105
+ return Object.assign(secretFromMetadata(metadata), {
1106
+ traceId: response.traceId
1107
+ });
1108
+ }
1109
+ async startImageBuild(buildServicePath, request) {
1110
+ const form = new FormData();
1111
+ form.append("graph_name", request.applicationName);
1112
+ form.append("graph_version", request.applicationVersion);
1113
+ form.append("graph_function_name", request.functionName);
1114
+ form.append("image_name", request.imageName);
1115
+ form.append("image_id", request.imageId);
1116
+ form.append(
1117
+ "context",
1118
+ new Blob([toBlobPart(request.buildContext)]),
1119
+ "context.tar.gz"
1120
+ );
1121
+ const response = await this.transport.requestResponse(
1122
+ "PUT",
1123
+ `${trimTrailingSlashes2(buildServicePath)}/builds`,
1124
+ { body: form }
1125
+ );
1126
+ const raw = await parseJsonResponse(response);
1127
+ return fromSnakeKeys(raw);
1128
+ }
1129
+ async createApplicationBuild(buildServicePath, request, imageContexts) {
1130
+ const form = createApplicationBuildForm(request, imageContexts);
1131
+ const response = await this.transport.requestResponse(
1132
+ "POST",
1133
+ trimTrailingSlashes2(buildServicePath),
1134
+ { body: form }
1135
+ );
1136
+ const raw = await parseJsonResponse(response);
1137
+ return fromSnakeKeys(raw);
1138
+ }
1139
+ async applicationBuildInfo(buildServicePath, applicationBuildId) {
1140
+ const raw = await this.transport.requestJson(
1141
+ "GET",
1142
+ `${trimTrailingSlashes2(buildServicePath)}/${encodeURIComponent(applicationBuildId)}`
1143
+ );
1144
+ return fromSnakeKeys(raw);
1145
+ }
1146
+ async cancelApplicationBuild(buildServicePath, applicationBuildId) {
1147
+ const raw = await this.transport.requestJson(
1148
+ "POST",
1149
+ `${trimTrailingSlashes2(buildServicePath)}/${encodeURIComponent(applicationBuildId)}/cancel`
1150
+ );
1151
+ return fromSnakeKeys(raw);
1152
+ }
1153
+ async buildInfo(buildServicePath, buildId) {
1154
+ const raw = await this.transport.requestJson(
1155
+ "GET",
1156
+ `${trimTrailingSlashes2(buildServicePath)}/builds/${encodeURIComponent(buildId)}`
1157
+ );
1158
+ return fromSnakeKeys(raw);
1159
+ }
1160
+ async cancelBuild(buildServicePath, buildId) {
1161
+ await this.transport.requestResponse(
1162
+ "POST",
1163
+ `${trimTrailingSlashes2(buildServicePath)}/builds/${encodeURIComponent(buildId)}/cancel`
1164
+ );
1165
+ }
1166
+ async *streamBuildLogs(buildServicePath, buildId, signal) {
1167
+ const stream = this.transport.stream(
1168
+ "GET",
1169
+ `${trimTrailingSlashes2(buildServicePath)}/builds/${encodeURIComponent(buildId)}/logs`,
1170
+ signal
1171
+ );
1172
+ for await (const event of stream) {
1173
+ yield fromSnakeKeys(event);
1174
+ }
1175
+ }
1176
+ async runMultipartRequest(path3, inputs) {
1177
+ const form = new FormData();
1178
+ for (const input of inputs) {
1179
+ form.append(
1180
+ input.name,
1181
+ new Blob([toBlobPart(input.data)], { type: input.contentType }),
1182
+ input.name
1183
+ );
1184
+ }
1185
+ return this.transport.requestResponse("POST", path3, {
1186
+ body: form,
1187
+ headers: { Accept: "application/json" }
1188
+ });
1189
+ }
1190
+ namespacePath(subpath) {
1191
+ return `/v1/namespaces/${encodeURIComponent(this.namespace)}/${subpath.replace(/^\/+/, "")}`;
1192
+ }
1193
+ async existingApplicationPublicEndpointId(applicationName) {
1194
+ const response = await this.transport.requestResponse(
1195
+ "GET",
1196
+ this.namespacePath(`applications/${encodeURIComponent(applicationName)}`),
1197
+ { statusOnlyCodes: /* @__PURE__ */ new Set([404]) }
1198
+ );
1199
+ if (response.status === 404) {
1200
+ return void 0;
1201
+ }
1202
+ const application = await parseJsonResponse(response);
1203
+ return publicEndpointIdFromManifest(application);
1204
+ }
1205
+ platformProjectPath(resource, organizationId, projectId) {
1206
+ const resolvedOrganizationId = organizationId ?? this.organizationId;
1207
+ const resolvedProjectId = projectId ?? this.projectId;
1208
+ if (!resolvedOrganizationId && !resolvedProjectId) {
1209
+ return `/platform/v1/${resource}`;
1210
+ }
1211
+ if (!resolvedOrganizationId || !resolvedProjectId) {
1212
+ throw new Error(
1213
+ "organizationId and projectId must be provided together"
1214
+ );
1215
+ }
1216
+ return `/platform/v1/organizations/${encodeURIComponent(resolvedOrganizationId)}/projects/${encodeURIComponent(resolvedProjectId)}/${resource}`;
1217
+ }
1218
+ secretCollectionPath(organizationId, projectId) {
1219
+ const resolvedOrganizationId = organizationId ?? this.organizationId;
1220
+ const resolvedProjectId = projectId ?? this.projectId;
1221
+ if (!resolvedOrganizationId && !resolvedProjectId) {
1222
+ return this.namespacePath("secrets");
1223
+ }
1224
+ if (!resolvedOrganizationId || !resolvedProjectId) {
1225
+ throw new Error("organizationId and projectId must be provided together");
1226
+ }
1227
+ return this.namespacePath("secrets");
1228
+ }
1229
+ };
1230
+ UNAUTHENTICATED_REQUESTS = "unauthenticated_requests";
1231
+ }
1232
+ });
1233
+
1234
+ // lib/libc.cjs
1235
+ var require_libc = __commonJS({
1236
+ "lib/libc.cjs"(exports2, module2) {
1237
+ "use strict";
1238
+ init_cjs_shims();
1239
+ function detectLinuxLibc2(fs2, executable = process.execPath) {
1240
+ const override = process.env.TENSORLAKE_NODE_LIBC;
1241
+ if (override != null) {
1242
+ if (override === "gnu" || override === "musl") return override;
1243
+ throw new Error("TENSORLAKE_NODE_LIBC must be 'gnu' or 'musl'.");
1244
+ }
1245
+ let fd;
1246
+ try {
1247
+ let read2 = function(size, offset) {
1248
+ if (!Number.isSafeInteger(offset) || offset < 0) {
1249
+ throw new Error("Invalid ELF offset");
1250
+ }
1251
+ const buffer = Buffer.alloc(size);
1252
+ let count2 = 0;
1253
+ while (count2 < size) {
1254
+ const bytes = fs2.readSync(fd, buffer, count2, size - count2, offset + count2);
1255
+ if (bytes === 0) throw new Error("Truncated ELF executable");
1256
+ count2 += bytes;
1257
+ }
1258
+ return buffer;
1259
+ };
1260
+ var read = read2;
1261
+ fd = fs2.openSync(executable, "r");
1262
+ const header = read2(64, 0);
1263
+ if (header.readUInt32BE(0) !== 2135247942 || header[4] !== 2 || header[5] !== 1) {
1264
+ throw new Error("Expected a little-endian ELF64 executable");
1265
+ }
1266
+ const entrySize = header.readUInt16LE(54);
1267
+ const count = header.readUInt16LE(56);
1268
+ if (entrySize !== 56 || count === 0 || count > 128) {
1269
+ throw new Error("Unsupported ELF program headers");
1270
+ }
1271
+ const entries = read2(entrySize * count, Number(header.readBigUInt64LE(32)));
1272
+ for (let i = 0; i < count; i++) {
1273
+ const offset = i * entrySize;
1274
+ if (entries.readUInt32LE(offset) !== 3) continue;
1275
+ const size = Number(entries.readBigUInt64LE(offset + 32));
1276
+ if (size < 2 || size > 4096) throw new Error("Invalid ELF interpreter size");
1277
+ const interpreter = read2(size, Number(entries.readBigUInt64LE(offset + 8)));
1278
+ if (interpreter[size - 1] !== 0) throw new Error("Unterminated ELF interpreter");
1279
+ const name = interpreter.subarray(0, -1).toString("utf8").split("/").at(-1);
1280
+ if (name.startsWith("ld-musl-")) return "musl";
1281
+ if (name.startsWith("ld-linux-")) return "gnu";
1282
+ throw new Error("Unrecognized ELF interpreter");
1283
+ }
1284
+ throw new Error("No ELF interpreter (statically linked executable)");
1285
+ } catch (cause) {
1286
+ throw new Error(
1287
+ "Unable to detect Linux libc from the Node executable. Set TENSORLAKE_NODE_LIBC to 'gnu' or 'musl' for a nonstandard runtime.",
1288
+ { cause }
1289
+ );
1290
+ } finally {
1291
+ if (fd != null) fs2.closeSync(fd);
1292
+ }
1293
+ }
1294
+ module2.exports = { detectLinuxLibc: detectLinuxLibc2 };
1295
+ }
1296
+ });
1297
+
1298
+ // src/native-binding.ts
1299
+ function packageRoot() {
1300
+ const parent = (0, import_node_url.fileURLToPath)(new URL("../", importMetaUrl));
1301
+ if (fs.existsSync(import_node_path.default.join(parent, "package.json"))) return parent;
1302
+ const grandparent = (0, import_node_url.fileURLToPath)(new URL("../../", importMetaUrl));
1303
+ if (fs.existsSync(import_node_path.default.join(grandparent, "package.json"))) return grandparent;
1304
+ return parent;
1305
+ }
1306
+ function linuxLibcFamily(options) {
1307
+ if (options.libc != null) return options.libc;
1308
+ if (options.report != null) {
1309
+ return options.report.header?.glibcVersionRuntime ? "gnu" : "musl";
1310
+ }
1311
+ if (cachedLinuxLibc != null) return cachedLinuxLibc;
1312
+ cachedLinuxLibc = (0, import_libc.detectLinuxLibc)(fs);
1313
+ return cachedLinuxLibc;
1314
+ }
1315
+ function nativeTargetId(platform = process.platform, arch = process.arch, options = {}) {
1316
+ const target = `${platform}-${arch}`;
1317
+ if (platform !== "linux") return target;
1318
+ if (options.libc == null && options.report == null && platform !== process.platform) {
1319
+ return target;
1320
+ }
1321
+ return linuxLibcFamily(options) === "musl" ? `${target}-musl` : target;
1322
+ }
1323
+ function nativeBindingPath(options = {}) {
1324
+ const platform = options.platform ?? process.platform;
1325
+ const arch = options.arch ?? process.arch;
1326
+ return import_node_path.default.join(
1327
+ options.packageRoot ?? packageRoot(),
1328
+ "dist",
1329
+ "native",
1330
+ nativeTargetId(platform, arch, options),
1331
+ "tensorlake-node.node"
1332
+ );
1333
+ }
1334
+ function nativePackageName(platform = process.platform, arch = process.arch, options = {}) {
1335
+ return NATIVE_PACKAGES[nativeTargetId(platform, arch, options)];
1336
+ }
1337
+ function loadNative() {
1338
+ const target = nativeTargetId();
1339
+ const bindingPath = nativeBindingPath();
1340
+ const require2 = (0, import_node_module2.createRequire)(importMetaUrl);
1341
+ if (fs.existsSync(bindingPath)) return require2(bindingPath);
1342
+ const packageName = nativePackageName();
1343
+ if (!packageName) {
1344
+ throw new Error(
1345
+ `Tensorlake does not provide a native binding for ${target}.`
1346
+ );
1347
+ }
1348
+ let packageEntry;
1349
+ try {
1350
+ packageEntry = require2.resolve(packageName);
1351
+ } catch (cause) {
1352
+ throw new Error(
1353
+ `Missing native binding package ${packageName} for ${target}. Reinstall @tensorlakeai/tensorlake without omitting optional dependencies, and install dependencies on the machine where they will run.`,
1354
+ { cause }
1355
+ );
1356
+ }
1357
+ return require2(packageEntry);
1358
+ }
1359
+ var import_libc, fs, import_node_module2, import_node_path, import_node_url, NATIVE_PACKAGES, cachedLinuxLibc;
1360
+ var init_native_binding = __esm({
1361
+ "src/native-binding.ts"() {
1362
+ "use strict";
1363
+ init_cjs_shims();
1364
+ import_libc = __toESM(require_libc(), 1);
1365
+ fs = __toESM(require("fs"), 1);
1366
+ import_node_module2 = require("module");
1367
+ import_node_path = __toESM(require("path"), 1);
1368
+ import_node_url = require("url");
1369
+ NATIVE_PACKAGES = {
1370
+ "darwin-arm64": "@tensorlakeai/native-darwin-arm64",
1371
+ "linux-arm64": "@tensorlakeai/native-linux-arm64-gnu",
1372
+ "linux-arm64-musl": "@tensorlakeai/native-linux-arm64-musl",
1373
+ "linux-x64": "@tensorlakeai/native-linux-x64-gnu",
1374
+ "linux-x64-musl": "@tensorlakeai/native-linux-x64-musl",
1375
+ "win32-x64": "@tensorlakeai/native-win32-x64"
1376
+ };
1377
+ }
1378
+ });
1379
+
1380
+ // src/sandbox-image.ts
1381
+ var sandbox_image_exports = {};
1382
+ __export(sandbox_image_exports, {
1383
+ __setNativeBindingForTest: () => __setNativeBindingForTest,
1384
+ buildContextFromEnv: () => buildContextFromEnv,
1385
+ createSandboxImage: () => createSandboxImage,
1386
+ deleteSandboxImage: () => deleteSandboxImage,
1387
+ findSandboxImageByName: () => findSandboxImageByName,
1388
+ importSandboxImage: () => importSandboxImage,
1389
+ listSandboxImages: () => listSandboxImages,
1390
+ runCreateSandboxImageCli: () => runCreateSandboxImageCli,
1391
+ runImportSandboxImageCli: () => runImportSandboxImageCli
1392
+ });
1393
+ function loadNativeBinding() {
1394
+ if (cachedNativeBinding) return cachedNativeBinding;
1395
+ if (cachedNativeBindingError) throw cachedNativeBindingError;
1396
+ try {
1397
+ cachedNativeBinding = loadNative();
1398
+ return cachedNativeBinding;
1399
+ } catch (error) {
1400
+ cachedNativeBindingError = error instanceof Error ? error : new Error(String(error));
1401
+ throw cachedNativeBindingError;
1402
+ }
1403
+ }
1404
+ function __setNativeBindingForTest(binding) {
1405
+ cachedNativeBinding = binding;
1406
+ cachedNativeBindingError = void 0;
1407
+ }
1408
+ function nonEmpty(value) {
1409
+ return value && value.length > 0 ? value : void 0;
1410
+ }
1411
+ function buildContextFromEnv() {
1412
+ const debugRaw = (process.env.TENSORLAKE_DEBUG ?? "").toLowerCase();
1413
+ const debug = ["1", "true", "yes", "on"].includes(debugRaw);
1414
+ return {
1415
+ apiUrl: nonEmpty(process.env.TENSORLAKE_API_URL) ?? "https://api.tensorlake.ai",
1416
+ apiKey: nonEmpty(process.env.TENSORLAKE_API_KEY),
1417
+ personalAccessToken: nonEmpty(process.env.TENSORLAKE_PAT),
1418
+ namespace: nonEmpty(process.env.INDEXIFY_NAMESPACE) ?? "default",
1419
+ organizationId: nonEmpty(process.env.TENSORLAKE_ORGANIZATION_ID),
1420
+ projectId: nonEmpty(process.env.TENSORLAKE_PROJECT_ID),
1421
+ debug
1422
+ };
1423
+ }
1424
+ function defaultRegisteredName(dockerfilePath) {
1425
+ const parsed = import_node_path2.default.parse(dockerfilePath);
1426
+ if (parsed.name.toLowerCase() === "dockerfile") {
1427
+ const parentName = import_node_path2.default.basename(import_node_path2.default.dirname(dockerfilePath)).trim();
1428
+ return parentName || "sandbox-image";
1429
+ }
1430
+ return parsed.name || "sandbox-image";
1431
+ }
1432
+ function defaultRegisteredNameFromImage(imageReference) {
1433
+ const withoutDigest = imageReference.split("@", 1)[0] ?? imageReference;
1434
+ const lastSegment = withoutDigest.split("/").pop() ?? withoutDigest;
1435
+ const colonIndex = lastSegment.lastIndexOf(":");
1436
+ const name = colonIndex > 0 && colonIndex < lastSegment.length - 1 ? lastSegment.slice(0, colonIndex) : lastSegment;
1437
+ return name || "imported-image";
1438
+ }
1439
+ function noopEmit(_event) {
1440
+ }
1441
+ function stderrEmit(event) {
1442
+ const message = typeof event.message === "string" ? event.message : "";
1443
+ const type = typeof event.type === "string" ? event.type : "";
1444
+ if (type === "build_log") {
1445
+ const stream = typeof event.stream === "string" ? event.stream : "stdout";
1446
+ process.stderr.write(`[${stream}] ${message}
1447
+ `);
1448
+ } else if (message) {
1449
+ process.stderr.write(`[${type}] ${message}
1450
+ `);
1451
+ }
1452
+ }
1453
+ function ndjsonStdoutEmit(event) {
1454
+ process.stdout.write(`${JSON.stringify(event)}
1455
+ `);
1456
+ }
1457
+ function eventToEmitDict(event) {
1458
+ const out = {
1459
+ type: event.eventType,
1460
+ message: event.message
1461
+ };
1462
+ if (event.stream != null) out.stream = event.stream;
1463
+ return out;
1464
+ }
1465
+ function runOpMountsContext(op) {
1466
+ if (op.type !== ImageBuildOperationType.RUN) {
1467
+ return false;
1468
+ }
1469
+ const mount = op.options.mount;
1470
+ if (mount == null || mount === "") {
1471
+ return false;
1472
+ }
1473
+ const fields = {};
1474
+ for (const token of mount.split(",")) {
1475
+ const eq = token.indexOf("=");
1476
+ const key = (eq === -1 ? token : token.slice(0, eq)).trim();
1477
+ const value = eq === -1 ? "" : token.slice(eq + 1).trim();
1478
+ fields[key] = value;
1479
+ }
1480
+ if ((fields.type ?? "bind") !== "bind") {
1481
+ return false;
1482
+ }
1483
+ return !("from" in fields);
1484
+ }
1485
+ function opReferencesHostFiles(op) {
1486
+ if (op.type === ImageBuildOperationType.RUN) {
1487
+ return runOpMountsContext(op);
1488
+ }
1489
+ if (op.type !== ImageBuildOperationType.COPY && op.type !== ImageBuildOperationType.ADD) {
1490
+ return false;
1491
+ }
1492
+ if (op.options.from != null) {
1493
+ return false;
1494
+ }
1495
+ if (op.type === ImageBuildOperationType.ADD && (op.args[0].startsWith("http://") || op.args[0].startsWith("https://"))) {
1496
+ return false;
1497
+ }
1498
+ return true;
1499
+ }
1500
+ function imageRequiresContext(image) {
1501
+ return image.buildOperations.some(opReferencesHostFiles);
1502
+ }
1503
+ async function createSandboxImage(source, options = {}, deps = {}) {
1504
+ const emit = deps.emit ?? (options.verbose ? stderrEmit : noopEmit);
1505
+ const context = buildContextFromEnv();
1506
+ let dockerfilePath;
1507
+ let dockerfileText;
1508
+ let nativeContextDir;
1509
+ let effectiveName;
1510
+ let tempContextDir;
1511
+ if (source instanceof Image) {
1512
+ if (!source.baseImage) {
1513
+ throw new Error("Image must have a baseImage to build");
1514
+ }
1515
+ let resolvedContext;
1516
+ if (options.contextDir != null) {
1517
+ resolvedContext = import_node_path2.default.resolve(options.contextDir);
1518
+ } else if (imageRequiresContext(source)) {
1519
+ throw new Error(
1520
+ "This image reads files from the host (via COPY/ADD or a RUN bind mount), so it needs a build context. Pass `contextDir` pointing at the directory that contains those sources; they resolve relative to it, like `docker build <contextDir>`."
1521
+ );
1522
+ } else {
1523
+ tempContextDir = (0, import_node_fs.mkdtempSync)(import_node_path2.default.join(import_node_os.default.tmpdir(), "tl-build-context-"));
1524
+ resolvedContext = tempContextDir;
1525
+ }
1526
+ dockerfilePath = import_node_path2.default.join(resolvedContext, "Dockerfile");
1527
+ let text = dockerfileContent(source);
1528
+ if (!text.endsWith("\n")) text += "\n";
1529
+ dockerfileText = text;
1530
+ nativeContextDir = resolvedContext;
1531
+ effectiveName = options.registeredName ?? source.name;
1532
+ } else if (typeof source === "string") {
1533
+ const resolvedPath = import_node_path2.default.resolve(source);
1534
+ if (!(0, import_node_fs.existsSync)(resolvedPath)) {
1535
+ throw new Error(`Dockerfile not found: ${source}`);
1536
+ }
1537
+ dockerfilePath = resolvedPath;
1538
+ dockerfileText = void 0;
1539
+ nativeContextDir = void 0;
1540
+ effectiveName = options.registeredName ?? defaultRegisteredName(resolvedPath);
1541
+ } else {
1542
+ throw new TypeError(
1543
+ `source must be an Image or a Dockerfile path, got ${typeof source}`
1544
+ );
1545
+ }
1546
+ try {
1547
+ if (effectiveName === DEFAULT_IMAGE_NAME) {
1548
+ console.warn(
1549
+ `Building sandbox image with the default name "${DEFAULT_IMAGE_NAME}". Pass \`registeredName\` or \`Image({ name })\` to avoid collisions with other default-named images in this project.`
1550
+ );
1551
+ }
1552
+ const usePat = deps._allowPat === true && context.apiKey == null;
1553
+ const bearerToken = context.apiKey ?? (usePat ? context.personalAccessToken : void 0);
1554
+ if (!bearerToken) {
1555
+ if (context.personalAccessToken && !deps._allowPat) {
1556
+ throw new Error(
1557
+ "Sandbox image SDKs require TENSORLAKE_API_KEY. Personal access tokens are CLI-only."
1558
+ );
1559
+ }
1560
+ throw new Error(
1561
+ deps._allowPat ? "Missing TENSORLAKE_API_KEY or TENSORLAKE_PAT credentials." : "Missing TENSORLAKE_API_KEY credentials."
1562
+ );
1563
+ }
1564
+ emit({ type: "status", message: `Building image '${effectiveName}'...` });
1565
+ const binding = loadNativeBinding();
1566
+ let emitError;
1567
+ const resultJson = await binding.buildSandboxImage(
1568
+ {
1569
+ apiUrl: context.apiUrl,
1570
+ bearerToken,
1571
+ dockerfilePath,
1572
+ registeredName: effectiveName,
1573
+ diskMb: options.diskMb,
1574
+ builderDiskMb: options.builderDiskMb,
1575
+ cpus: options.cpus,
1576
+ memoryMb: options.memoryMb,
1577
+ isPublic: options.isPublic ?? false,
1578
+ organizationId: usePat ? context.organizationId : void 0,
1579
+ projectId: usePat ? context.projectId : void 0,
1580
+ namespace: context.namespace,
1581
+ useScopeHeaders: usePat,
1582
+ userAgent: void 0,
1583
+ dockerCompat: options.dockerCompat ?? false,
1584
+ dockerfileText,
1585
+ contextDir: nativeContextDir
1586
+ },
1587
+ (event) => {
1588
+ try {
1589
+ emit(eventToEmitDict(event));
1590
+ } catch (error) {
1591
+ emitError ??= error;
1592
+ }
1593
+ }
1594
+ );
1595
+ if (emitError != null) {
1596
+ throw emitError;
1597
+ }
1598
+ let result = {};
1599
+ if (resultJson.trim().length > 0) {
1600
+ result = JSON.parse(resultJson);
1601
+ }
1602
+ emit({
1603
+ type: "image_registered",
1604
+ name: effectiveName,
1605
+ image_id: typeof result.id === "string" && result.id || typeof result.templateId === "string" && result.templateId || ""
1606
+ });
1607
+ emit({ type: "done" });
1608
+ return result;
1609
+ } finally {
1610
+ if (tempContextDir != null) {
1611
+ (0, import_node_fs.rmSync)(tempContextDir, { recursive: true, force: true });
1612
+ }
1613
+ }
1614
+ }
1615
+ async function importSandboxImage(imageReference, options = {}, deps = {}) {
1616
+ const emit = deps.emit ?? (options.verbose ? stderrEmit : noopEmit);
1617
+ if (typeof imageReference !== "string" || imageReference.trim().length === 0) {
1618
+ throw new Error("image reference to import must not be empty");
1619
+ }
1620
+ const reference = imageReference.trim();
1621
+ const context = buildContextFromEnv();
1622
+ const effectiveName = options.registeredName ?? defaultRegisteredNameFromImage(reference);
1623
+ if (effectiveName === DEFAULT_IMAGE_NAME) {
1624
+ console.warn(
1625
+ `Importing sandbox image with the default name "${DEFAULT_IMAGE_NAME}". Pass \`registeredName\` to avoid collisions with other default-named images in this project.`
1626
+ );
1627
+ }
1628
+ const usePat = deps._allowPat === true && context.apiKey == null;
1629
+ const bearerToken = context.apiKey ?? (usePat ? context.personalAccessToken : void 0);
1630
+ if (!bearerToken) {
1631
+ if (context.personalAccessToken && !deps._allowPat) {
1632
+ throw new Error(
1633
+ "Sandbox image SDKs require TENSORLAKE_API_KEY. Personal access tokens are CLI-only."
1634
+ );
1635
+ }
1636
+ throw new Error(
1637
+ deps._allowPat ? "Missing TENSORLAKE_API_KEY or TENSORLAKE_PAT credentials." : "Missing TENSORLAKE_API_KEY credentials."
1638
+ );
1639
+ }
1640
+ emit({
1641
+ type: "status",
1642
+ message: `Importing image '${reference}' as '${effectiveName}'...`
1643
+ });
1644
+ const binding = loadNativeBinding();
1645
+ let emitError;
1646
+ const resultJson = await binding.importSandboxImage(
1647
+ {
1648
+ apiUrl: context.apiUrl,
1649
+ bearerToken,
1650
+ imageReference: reference,
1651
+ registeredName: effectiveName,
1652
+ diskMb: options.diskMb,
1653
+ builderDiskMb: options.builderDiskMb,
1654
+ cpus: options.cpus,
1655
+ memoryMb: options.memoryMb,
1656
+ isPublic: options.isPublic ?? false,
1657
+ organizationId: usePat ? context.organizationId : void 0,
1658
+ projectId: usePat ? context.projectId : void 0,
1659
+ namespace: context.namespace,
1660
+ useScopeHeaders: usePat,
1661
+ userAgent: void 0,
1662
+ dockerCompat: options.dockerCompat ?? false
1663
+ },
1664
+ (event) => {
1665
+ try {
1666
+ emit(eventToEmitDict(event));
1667
+ } catch (error) {
1668
+ emitError ??= error;
1669
+ }
1670
+ }
1671
+ );
1672
+ if (emitError != null) {
1673
+ throw emitError;
1674
+ }
1675
+ let result = {};
1676
+ if (resultJson.trim().length > 0) {
1677
+ result = JSON.parse(resultJson);
1678
+ }
1679
+ emit({
1680
+ type: "image_registered",
1681
+ name: effectiveName,
1682
+ image_id: typeof result.id === "string" && result.id || typeof result.templateId === "string" && result.templateId || ""
1683
+ });
1684
+ emit({ type: "done" });
1685
+ return result;
1686
+ }
1687
+ async function deleteSandboxImage(imageName) {
1688
+ if (typeof imageName !== "string" || imageName.length === 0) {
1689
+ throw new TypeError("imageName must be a non-empty string");
1690
+ }
1691
+ const context = buildContextFromEnv();
1692
+ const bearerToken = context.apiKey;
1693
+ if (!bearerToken) {
1694
+ if (context.personalAccessToken) {
1695
+ throw new Error(
1696
+ "Sandbox image SDKs require TENSORLAKE_API_KEY. Personal access tokens are CLI-only."
1697
+ );
1698
+ }
1699
+ throw new Error("Missing TENSORLAKE_API_KEY credentials.");
1700
+ }
1701
+ const client = new CloudClient({
1702
+ apiUrl: context.apiUrl,
1703
+ apiKey: bearerToken,
1704
+ namespace: context.namespace
1705
+ });
1706
+ try {
1707
+ await client.deleteSandboxImage(imageName);
1708
+ } finally {
1709
+ client.close();
1710
+ }
1711
+ }
1712
+ async function findSandboxImageByName(imageName) {
1713
+ if (typeof imageName !== "string" || imageName.length === 0) {
1714
+ throw new TypeError("imageName must be a non-empty string");
1715
+ }
1716
+ const context = buildContextFromEnv();
1717
+ const bearerToken = context.apiKey;
1718
+ if (!bearerToken) {
1719
+ if (context.personalAccessToken) {
1720
+ throw new Error(
1721
+ "Sandbox image SDKs require TENSORLAKE_API_KEY. Personal access tokens are CLI-only."
1722
+ );
1723
+ }
1724
+ throw new Error("Missing TENSORLAKE_API_KEY credentials.");
1725
+ }
1726
+ const client = new CloudClient({
1727
+ apiUrl: context.apiUrl,
1728
+ apiKey: bearerToken,
1729
+ namespace: context.namespace
1730
+ });
1731
+ try {
1732
+ return await client.findSandboxImageByName(imageName);
1733
+ } finally {
1734
+ client.close();
1735
+ }
1736
+ }
1737
+ async function listSandboxImages() {
1738
+ const context = buildContextFromEnv();
1739
+ const bearerToken = context.apiKey;
1740
+ if (!bearerToken) {
1741
+ if (context.personalAccessToken) {
1742
+ throw new Error(
1743
+ "Sandbox image SDKs require TENSORLAKE_API_KEY. Personal access tokens are CLI-only."
1744
+ );
1745
+ }
1746
+ throw new Error("Missing TENSORLAKE_API_KEY credentials.");
1747
+ }
1748
+ const client = new CloudClient({
1749
+ apiUrl: context.apiUrl,
1750
+ apiKey: bearerToken,
1751
+ namespace: context.namespace
1752
+ });
1753
+ try {
1754
+ return await client.listSandboxImages();
1755
+ } finally {
1756
+ client.close();
1757
+ }
1758
+ }
1759
+ async function runCreateSandboxImageCli(argv = process.argv.slice(2)) {
1760
+ const parsed = (0, import_node_util.parseArgs)({
1761
+ args: argv,
1762
+ allowPositionals: true,
1763
+ options: {
1764
+ name: { type: "string", short: "n" },
1765
+ cpus: { type: "string" },
1766
+ memory: { type: "string" },
1767
+ disk_mb: { type: "string" },
1768
+ builder_disk_mb: { type: "string" },
1769
+ docker_compat: { type: "boolean", default: false },
1770
+ public: { type: "boolean", default: false }
1771
+ }
1772
+ });
1773
+ const dockerfilePath = parsed.positionals[0];
1774
+ if (!dockerfilePath) {
1775
+ throw new Error(
1776
+ "Usage: tensorlake-create-sandbox-image <dockerfile_path> [--name NAME] [--cpus N] [--memory MiB] [--disk_mb MiB] [--builder_disk_mb MiB] [--docker_compat] [--public]"
1777
+ );
1778
+ }
1779
+ const cpus = parsed.values.cpus != null ? Number(parsed.values.cpus) : void 0;
1780
+ const memoryMb = parsed.values.memory != null ? Number(parsed.values.memory) : void 0;
1781
+ const diskMb = parsed.values.disk_mb != null ? Number(parsed.values.disk_mb) : void 0;
1782
+ const builderDiskMb = parsed.values.builder_disk_mb != null ? Number(parsed.values.builder_disk_mb) : void 0;
1783
+ if (cpus != null && !Number.isFinite(cpus)) {
1784
+ throw new Error(`Invalid --cpus value: ${parsed.values.cpus}`);
1785
+ }
1786
+ if (memoryMb != null && !Number.isInteger(memoryMb)) {
1787
+ throw new Error(`Invalid --memory value: ${parsed.values.memory}`);
1788
+ }
1789
+ if (diskMb != null && !Number.isInteger(diskMb)) {
1790
+ throw new Error(`Invalid --disk_mb value: ${parsed.values.disk_mb}`);
1791
+ }
1792
+ if (builderDiskMb != null && !Number.isInteger(builderDiskMb)) {
1793
+ throw new Error(
1794
+ `Invalid --builder_disk_mb value: ${parsed.values.builder_disk_mb}`
1795
+ );
1796
+ }
1797
+ await createSandboxImage(
1798
+ dockerfilePath,
1799
+ {
1800
+ registeredName: parsed.values.name,
1801
+ cpus,
1802
+ memoryMb,
1803
+ diskMb,
1804
+ builderDiskMb,
1805
+ dockerCompat: parsed.values.docker_compat,
1806
+ isPublic: parsed.values.public
1807
+ },
1808
+ { emit: ndjsonStdoutEmit, _allowPat: true }
1809
+ );
1810
+ }
1811
+ async function runImportSandboxImageCli(argv = process.argv.slice(2)) {
1812
+ const parsed = (0, import_node_util.parseArgs)({
1813
+ args: argv,
1814
+ allowPositionals: true,
1815
+ options: {
1816
+ name: { type: "string", short: "n" },
1817
+ cpus: { type: "string" },
1818
+ memory: { type: "string" },
1819
+ disk_mb: { type: "string" },
1820
+ builder_disk_mb: { type: "string" },
1821
+ docker_compat: { type: "boolean", default: false },
1822
+ public: { type: "boolean", default: false }
1823
+ }
1824
+ });
1825
+ const imageReference = parsed.positionals[0];
1826
+ if (!imageReference) {
1827
+ throw new Error(
1828
+ "Usage: tensorlake-import-sandbox-image <image_reference> [--name NAME] [--cpus N] [--memory MiB] [--disk_mb MiB] [--builder_disk_mb MiB] [--docker_compat] [--public]"
1829
+ );
1830
+ }
1831
+ const cpus = parsed.values.cpus != null ? Number(parsed.values.cpus) : void 0;
1832
+ const memoryMb = parsed.values.memory != null ? Number(parsed.values.memory) : void 0;
1833
+ const diskMb = parsed.values.disk_mb != null ? Number(parsed.values.disk_mb) : void 0;
1834
+ const builderDiskMb = parsed.values.builder_disk_mb != null ? Number(parsed.values.builder_disk_mb) : void 0;
1835
+ if (cpus != null && !Number.isFinite(cpus)) {
1836
+ throw new Error(`Invalid --cpus value: ${parsed.values.cpus}`);
1837
+ }
1838
+ if (memoryMb != null && !Number.isInteger(memoryMb)) {
1839
+ throw new Error(`Invalid --memory value: ${parsed.values.memory}`);
1840
+ }
1841
+ if (diskMb != null && !Number.isInteger(diskMb)) {
1842
+ throw new Error(`Invalid --disk_mb value: ${parsed.values.disk_mb}`);
1843
+ }
1844
+ if (builderDiskMb != null && !Number.isInteger(builderDiskMb)) {
1845
+ throw new Error(
1846
+ `Invalid --builder_disk_mb value: ${parsed.values.builder_disk_mb}`
1847
+ );
1848
+ }
1849
+ await importSandboxImage(
1850
+ imageReference,
1851
+ {
1852
+ registeredName: parsed.values.name,
1853
+ cpus,
1854
+ memoryMb,
1855
+ diskMb,
1856
+ builderDiskMb,
1857
+ dockerCompat: parsed.values.docker_compat,
1858
+ isPublic: parsed.values.public
1859
+ },
1860
+ { emit: ndjsonStdoutEmit, _allowPat: true }
1861
+ );
1862
+ }
1863
+ var import_node_path2, import_node_os, import_node_fs, import_node_util, cachedNativeBinding, cachedNativeBindingError, DEFAULT_IMAGE_NAME;
1864
+ var init_sandbox_image = __esm({
1865
+ "src/sandbox-image.ts"() {
1866
+ "use strict";
1867
+ init_cjs_shims();
1868
+ import_node_path2 = __toESM(require("path"), 1);
1869
+ import_node_os = __toESM(require("os"), 1);
1870
+ import_node_fs = require("fs");
1871
+ import_node_util = require("util");
1872
+ init_cloud_client();
1873
+ init_image();
1874
+ init_native_binding();
1875
+ DEFAULT_IMAGE_NAME = "default";
1876
+ }
1877
+ });
1878
+
1879
+ // src/image.ts
1880
+ function cloneOperation(op) {
1881
+ return {
1882
+ type: op.type,
1883
+ args: [...op.args],
1884
+ options: { ...op.options }
1885
+ };
1886
+ }
1887
+ function renderOptions(options) {
1888
+ const entries = Object.entries(options);
1889
+ if (entries.length === 0) {
1890
+ return "";
1891
+ }
1892
+ return ` ${entries.map(([key, value]) => `--${key}=${value}`).join(" ")}`;
1893
+ }
1894
+ function renderBuildOp(op) {
1895
+ const options = renderOptions(op.options);
1896
+ if (op.type === ImageBuildOperationType.ENV) {
1897
+ return `ENV${options} ${op.args[0]}=${JSON.stringify(op.args[1])}`;
1898
+ }
1899
+ return `${op.type}${options} ${op.args.join(" ")}`;
1900
+ }
1901
+ function dockerfileContent(image) {
1902
+ const lines = image.baseImage == null ? [] : [`FROM ${image.baseImage}`];
1903
+ lines.push(...image.buildOperations.map((op) => renderBuildOp(op)));
1904
+ return lines.join("\n");
1905
+ }
1906
+ var import_node_crypto2, DEFAULT_IMAGE_NAME2, ImageBuildOperationType, Image;
1907
+ var init_image = __esm({
1908
+ "src/image.ts"() {
1909
+ "use strict";
1910
+ init_cjs_shims();
1911
+ import_node_crypto2 = require("crypto");
1912
+ DEFAULT_IMAGE_NAME2 = "default";
1913
+ ImageBuildOperationType = {
1914
+ ADD: "ADD",
1915
+ COPY: "COPY",
1916
+ ENV: "ENV",
1917
+ RUN: "RUN",
1918
+ WORKDIR: "WORKDIR"
1919
+ };
1920
+ Image = class {
1921
+ _id;
1922
+ _name;
1923
+ _tag;
1924
+ _baseImage;
1925
+ _buildOperations;
1926
+ constructor(nameOrOptions = {}, tag = "latest", baseImage = null) {
1927
+ this._id = (0, import_node_crypto2.randomUUID)();
1928
+ this._buildOperations = [];
1929
+ if (typeof nameOrOptions === "string") {
1930
+ this._name = nameOrOptions;
1931
+ this._tag = tag;
1932
+ this._baseImage = baseImage;
1933
+ return;
1934
+ }
1935
+ this._name = nameOrOptions.name ?? DEFAULT_IMAGE_NAME2;
1936
+ this._tag = nameOrOptions.tag ?? "latest";
1937
+ this._baseImage = nameOrOptions.baseImage ?? null;
1938
+ }
1939
+ get name() {
1940
+ return this._name;
1941
+ }
1942
+ get tag() {
1943
+ return this._tag;
1944
+ }
1945
+ get baseImage() {
1946
+ return this._baseImage;
1947
+ }
1948
+ get buildOperations() {
1949
+ return this._buildOperations.map(cloneOperation);
1950
+ }
1951
+ add(src, dest, options = void 0) {
1952
+ return this._addOperation({
1953
+ type: ImageBuildOperationType.ADD,
1954
+ args: [src, dest],
1955
+ options: options == null ? {} : { ...options }
1956
+ });
1957
+ }
1958
+ copy(src, dest, options = void 0) {
1959
+ return this._addOperation({
1960
+ type: ImageBuildOperationType.COPY,
1961
+ args: [src, dest],
1962
+ options: options == null ? {} : { ...options }
1963
+ });
1964
+ }
1965
+ env(key, value) {
1966
+ return this._addOperation({
1967
+ type: ImageBuildOperationType.ENV,
1968
+ args: [key, value],
1969
+ options: {}
1970
+ });
1971
+ }
1972
+ run(commands, options = void 0) {
1973
+ return this._addOperation({
1974
+ type: ImageBuildOperationType.RUN,
1975
+ args: Array.isArray(commands) ? [...commands] : [commands],
1976
+ options: options == null ? {} : { ...options }
1977
+ });
1978
+ }
1979
+ workdir(directory) {
1980
+ return this._addOperation({
1981
+ type: ImageBuildOperationType.WORKDIR,
1982
+ args: [directory],
1983
+ options: {}
1984
+ });
1985
+ }
1986
+ /**
1987
+ * Build this image as a sandbox template and register it.
1988
+ *
1989
+ * Materializes the image in a build sandbox, snapshots the filesystem,
1990
+ * and registers the snapshot as a named sandbox template.
1991
+ */
1992
+ async build(options = {}) {
1993
+ const { createSandboxImage: createSandboxImage2 } = await Promise.resolve().then(() => (init_sandbox_image(), sandbox_image_exports));
1994
+ return createSandboxImage2(this, options);
1995
+ }
1996
+ _addOperation(op) {
1997
+ this._buildOperations.push(op);
1998
+ return this;
1999
+ }
2000
+ };
2001
+ }
2002
+ });
2003
+
2004
+ // src/applications/index.ts
2005
+ var applications_exports = {};
2006
+ __export(applications_exports, {
2007
+ DeserializationError: () => DeserializationError,
2008
+ File: () => File,
2009
+ FunctionError: () => FunctionError,
2010
+ Future: () => FunctionFuture,
2011
+ Headers: () => Headers,
2012
+ HttpBody: () => HttpBody,
2013
+ Image: () => Image,
2014
+ LocalRequest: () => LocalRequest,
2015
+ RemoteRequest: () => RemoteRequest,
2016
+ ReplayMismatchError: () => ReplayMismatchError,
2017
+ RequestContext: () => RequestContext,
2018
+ RequestError: () => RequestError,
2019
+ SDKUsageError: () => SDKUsageError,
2020
+ SDK_VERSION: () => SDK_VERSION,
2021
+ SerializationError: () => SerializationError,
2022
+ TensorlakeApplicationError: () => TensorlakeApplicationError,
2023
+ TimeoutError: () => TimeoutError,
2024
+ createApplicationManifest: () => createApplicationManifest,
2025
+ createApplicationManifests: () => createApplicationManifests,
2026
+ createCodeManifest: () => createCodeManifest,
2027
+ decodeDescriptor: () => decodeDescriptor,
2028
+ getApplications: () => getApplications,
2029
+ getFunction: () => getFunction,
2030
+ getFunctions: () => getFunctions,
2031
+ registerApplication: () => registerApplication,
2032
+ registerFunction: () => registerFunction,
2033
+ remoteOptions: () => remoteOptions,
2034
+ retries: () => retries,
2035
+ runLocal: () => runLocal,
2036
+ runRemote: () => runRemote,
2037
+ schema: () => schema
2038
+ });
2039
+ module.exports = __toCommonJS(applications_exports);
2040
+ init_cjs_shims();
2041
+
2042
+ // src/applications/function.ts
2043
+ init_cjs_shims();
2044
+ var import_node_async_hooks = require("async_hooks");
2045
+ var import_node_crypto = require("crypto");
2046
+
2047
+ // src/applications/errors.ts
2048
+ init_cjs_shims();
2049
+ var SDK_USAGE_ERROR_BRAND = /* @__PURE__ */ Symbol.for("tensorlake.applications.sdk-usage-error.v1");
2050
+ var REQUEST_ERROR_BRAND = /* @__PURE__ */ Symbol.for("tensorlake.applications.request-error.v1");
2051
+ var FUNCTION_ERROR_BRAND = /* @__PURE__ */ Symbol.for("tensorlake.applications.function-error.v1");
2052
+ var TIMEOUT_ERROR_BRAND = /* @__PURE__ */ Symbol.for("tensorlake.applications.timeout-error.v1");
2053
+ var TensorlakeApplicationError = class extends Error {
2054
+ constructor(message, options) {
2055
+ super(message, options);
2056
+ this.name = "TensorlakeApplicationError";
2057
+ }
2058
+ };
2059
+ var SDKUsageError = class _SDKUsageError extends TensorlakeApplicationError {
2060
+ [SDK_USAGE_ERROR_BRAND] = true;
2061
+ static [Symbol.hasInstance](value) {
2062
+ if (this !== _SDKUsageError) {
2063
+ return Function.prototype[Symbol.hasInstance].call(this, value);
2064
+ }
2065
+ return isSDKUsageError(value);
2066
+ }
2067
+ constructor(message) {
2068
+ super(message);
2069
+ this.name = "SDKUsageError";
2070
+ }
2071
+ };
2072
+ function isSDKUsageError(value) {
2073
+ if (typeof value !== "object" || value == null) return false;
2074
+ const candidate = value;
2075
+ return candidate[SDK_USAGE_ERROR_BRAND] === true && typeof candidate.message === "string";
2076
+ }
2077
+ var SerializationError = class extends TensorlakeApplicationError {
2078
+ constructor(message, options) {
2079
+ super(message, options);
2080
+ this.name = "SerializationError";
2081
+ }
2082
+ };
2083
+ var DeserializationError = class extends TensorlakeApplicationError {
2084
+ constructor(message, options) {
2085
+ super(message, options);
2086
+ this.name = "DeserializationError";
2087
+ }
2088
+ };
2089
+ var FunctionError = class _FunctionError extends TensorlakeApplicationError {
2090
+ [FUNCTION_ERROR_BRAND] = true;
2091
+ static [Symbol.hasInstance](value) {
2092
+ if (this !== _FunctionError) {
2093
+ return Function.prototype[Symbol.hasInstance].call(this, value);
2094
+ }
2095
+ return isFunctionError(value);
2096
+ }
2097
+ constructor(message, options) {
2098
+ super(message, options);
2099
+ this.name = "FunctionError";
2100
+ }
2101
+ };
2102
+ var TimeoutError = class _TimeoutError extends TensorlakeApplicationError {
2103
+ [TIMEOUT_ERROR_BRAND] = true;
2104
+ static [Symbol.hasInstance](value) {
2105
+ if (this !== _TimeoutError) {
2106
+ return Function.prototype[Symbol.hasInstance].call(this, value);
2107
+ }
2108
+ return isTimeoutError(value);
2109
+ }
2110
+ constructor() {
2111
+ super("Timed out.");
2112
+ this.name = "TimeoutError";
2113
+ }
2114
+ };
2115
+ function isTimeoutError(value) {
2116
+ if (typeof value !== "object" || value == null) return false;
2117
+ const candidate = value;
2118
+ return candidate[TIMEOUT_ERROR_BRAND] === true && typeof candidate.message === "string";
2119
+ }
2120
+ function isFunctionError(value) {
2121
+ if (typeof value !== "object" || value == null) return false;
2122
+ const candidate = value;
2123
+ return candidate[FUNCTION_ERROR_BRAND] === true && typeof candidate.message === "string";
2124
+ }
2125
+ var RequestError = class _RequestError extends TensorlakeApplicationError {
2126
+ [REQUEST_ERROR_BRAND] = true;
2127
+ static [Symbol.hasInstance](value) {
2128
+ if (this !== _RequestError) {
2129
+ return Function.prototype[Symbol.hasInstance].call(this, value);
2130
+ }
2131
+ return isRequestError(value);
2132
+ }
2133
+ constructor(message, options) {
2134
+ super(message, options);
2135
+ this.name = "RequestError";
2136
+ }
2137
+ };
2138
+ function isRequestError(value) {
2139
+ if (typeof value !== "object" || value == null) return false;
2140
+ const candidate = value;
2141
+ return candidate[REQUEST_ERROR_BRAND] === true && typeof candidate.message === "string";
2142
+ }
2143
+ var ReplayMismatchError = class extends TensorlakeApplicationError {
2144
+ constructor(message = "Function execution diverged from its durable event history") {
2145
+ super(message);
2146
+ this.name = "ReplayMismatchError";
2147
+ }
2148
+ };
2149
+
2150
+ // src/applications/schema.ts
2151
+ init_cjs_shims();
2152
+ var import_ajv = __toESM(require("ajv"), 1);
2153
+ var import__ = __toESM(require("ajv/dist/2020.js"), 1);
2154
+
2155
+ // src/applications/file.ts
2156
+ init_cjs_shims();
2157
+ var FILE_BRAND = /* @__PURE__ */ Symbol.for("tensorlake.applications.file.v1");
2158
+ var File = class _File {
2159
+ [FILE_BRAND] = true;
2160
+ content;
2161
+ contentType;
2162
+ static [Symbol.hasInstance](value) {
2163
+ if (this !== _File) {
2164
+ return Function.prototype[Symbol.hasInstance].call(this, value);
2165
+ }
2166
+ return isFile(value);
2167
+ }
2168
+ constructor(content, contentType) {
2169
+ if (!contentType.trim()) {
2170
+ throw new SDKUsageError("File contentType cannot be empty");
2171
+ }
2172
+ this.content = content instanceof Uint8Array ? content : new Uint8Array(content);
2173
+ this.contentType = contentType;
2174
+ }
2175
+ };
2176
+ function isFile(value) {
2177
+ if (typeof value !== "object" || value == null) return false;
2178
+ const candidate = value;
2179
+ return candidate[FILE_BRAND] === true && candidate.content instanceof Uint8Array && typeof candidate.contentType === "string" && candidate.contentType.trim().length > 0;
2180
+ }
2181
+
2182
+ // src/applications/http-body.ts
2183
+ init_cjs_shims();
2184
+ var HTTP_BODY_BRAND = /* @__PURE__ */ Symbol.for("tensorlake.applications.http-body.v1");
2185
+ var HttpBody = class _HttpBody {
2186
+ [HTTP_BODY_BRAND] = true;
2187
+ content;
2188
+ contentType;
2189
+ static [Symbol.hasInstance](value) {
2190
+ if (this !== _HttpBody) {
2191
+ return Function.prototype[Symbol.hasInstance].call(this, value);
2192
+ }
2193
+ return isHttpBody(value);
2194
+ }
2195
+ constructor(content, contentType) {
2196
+ this.content = content instanceof Uint8Array ? content : new Uint8Array(content);
2197
+ this.contentType = contentType;
2198
+ }
2199
+ text(encoding = "utf-8") {
2200
+ return new TextDecoder(encoding, { fatal: true }).decode(this.content);
2201
+ }
2202
+ json() {
2203
+ return JSON.parse(this.text());
2204
+ }
2205
+ };
2206
+ function isHttpBody(value) {
2207
+ if (typeof value !== "object" || value == null) return false;
2208
+ const candidate = value;
2209
+ return candidate[HTTP_BODY_BRAND] === true && candidate.content instanceof Uint8Array && (candidate.contentType === void 0 || typeof candidate.contentType === "string");
2210
+ }
2211
+
2212
+ // src/applications/schema.ts
2213
+ var ajvDraft7 = new import_ajv.default({ allErrors: true, strict: false });
2214
+ var ajv2020 = new import__.default({ allErrors: true, strict: false });
2215
+ function snapshotJSONValue(value, label, ancestors, freeze) {
2216
+ if (value == null || typeof value === "string" || typeof value === "boolean") {
2217
+ return value;
2218
+ }
2219
+ if (typeof value === "number") {
2220
+ if (!Number.isFinite(value)) {
2221
+ throw new SDKUsageError(`${label} contains a non-finite number`);
2222
+ }
2223
+ return value;
2224
+ }
2225
+ if (typeof value !== "object") {
2226
+ throw new SDKUsageError(`${label} contains unsupported ${typeof value}`);
2227
+ }
2228
+ if (ancestors.has(value)) {
2229
+ throw new SDKUsageError(`${label} contains a cycle`);
2230
+ }
2231
+ if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype) {
2232
+ throw new SDKUsageError(
2233
+ `${label} contains unsupported ${value.constructor?.name ?? "object"}`
2234
+ );
2235
+ }
2236
+ ancestors.add(value);
2237
+ let result;
2238
+ if (Array.isArray(value)) {
2239
+ result = [];
2240
+ for (let index = 0; index < value.length; index += 1) {
2241
+ if (!Object.prototype.hasOwnProperty.call(value, index)) {
2242
+ throw new SDKUsageError(`${label} contains a sparse array entry at index ${index}`);
2243
+ }
2244
+ result.push(snapshotJSONValue(
2245
+ value[index],
2246
+ `${label}[${index}]`,
2247
+ ancestors,
2248
+ freeze
2249
+ ));
2250
+ }
2251
+ } else {
2252
+ result = Object.fromEntries(
2253
+ Object.entries(value).map(([key, item]) => [
2254
+ key,
2255
+ snapshotJSONValue(item, `${label}.${key}`, ancestors, freeze)
2256
+ ])
2257
+ );
2258
+ }
2259
+ ancestors.delete(value);
2260
+ return freeze ? Object.freeze(result) : result;
2261
+ }
2262
+ function snapshotJSONSchema(jsonSchema) {
2263
+ return snapshotJSONValue(
2264
+ jsonSchema,
2265
+ "JSON schema",
2266
+ /* @__PURE__ */ new Set(),
2267
+ true
2268
+ );
2269
+ }
2270
+ function snapshotDefault(valueSchema, value) {
2271
+ if (valueSchema._file) {
2272
+ if (!isFile(value)) {
2273
+ throw new SDKUsageError("parameter default must be a Tensorlake File");
2274
+ }
2275
+ return new File(new Uint8Array(value.content), value.contentType);
2276
+ }
2277
+ if (valueSchema._httpBody) {
2278
+ if (!isHttpBody(value)) {
2279
+ throw new SDKUsageError("parameter default must be a Tensorlake HttpBody");
2280
+ }
2281
+ return new HttpBody(new Uint8Array(value.content), value.contentType);
2282
+ }
2283
+ return snapshotJSONValue(
2284
+ value,
2285
+ "parameter default",
2286
+ /* @__PURE__ */ new Set(),
2287
+ false
2288
+ );
2289
+ }
2290
+ function makeSchema(jsonSchema, rawBody) {
2291
+ return Object.freeze({
2292
+ jsonSchema: snapshotJSONSchema(jsonSchema),
2293
+ _file: rawBody === "file",
2294
+ _httpBody: rawBody === "httpBody"
2295
+ });
2296
+ }
2297
+ function rejectRawBodyComposition(operation, values) {
2298
+ const rawBody = values.find((value) => value._file || value._httpBody);
2299
+ if (rawBody != null) {
2300
+ const factory = rawBody._httpBody ? "httpBody" : "file";
2301
+ const type = rawBody._httpBody ? "HttpBody" : "File";
2302
+ const supportedPosition = rawBody._httpBody ? "as a direct application parameter" : "as a direct parameter or return value";
2303
+ throw new SDKUsageError(
2304
+ `schema.${operation} cannot contain schema.${factory}(); ${type} is only supported ${supportedPosition}`
2305
+ );
2306
+ }
2307
+ }
2308
+ function parameter(name, valueSchema, options = {}) {
2309
+ if (!/^[A-Za-z_$][\w$]*$/.test(name)) {
2310
+ throw new SDKUsageError(`Invalid parameter name '${name}'`);
2311
+ }
2312
+ const hasDefault = Object.prototype.hasOwnProperty.call(options, "default");
2313
+ if (hasDefault) validateWithSchema(valueSchema, options.default, `default for '${name}'`);
2314
+ const defaultSnapshot = hasDefault ? snapshotDefault(valueSchema, options.default) : void 0;
2315
+ return Object.freeze({
2316
+ name,
2317
+ schema: valueSchema,
2318
+ description: options.description,
2319
+ required: options.optional !== true && !hasDefault,
2320
+ hasDefault,
2321
+ // Defaults cross two public boundaries: callers can inspect the registered
2322
+ // definition, and every invocation receives the default when an argument is
2323
+ // omitted. Return a fresh boundary copy so neither path can mutate the
2324
+ // registration snapshot, later invocations, or generated manifests.
2325
+ get defaultValue() {
2326
+ return hasDefault ? snapshotDefault(valueSchema, defaultSnapshot) : void 0;
2327
+ }
2328
+ });
2329
+ }
2330
+ var schema = {
2331
+ /** Any JSON-serializable value. Useful when strict runtime validation is not needed. */
2332
+ json: () => makeSchema({}),
2333
+ string: (options = {}) => makeSchema({ ...options, type: "string" }),
2334
+ number: (options = {}) => makeSchema({ ...options, type: "number" }),
2335
+ integer: (options = {}) => makeSchema({ ...options, type: "integer" }),
2336
+ boolean: () => makeSchema({ type: "boolean" }),
2337
+ null: () => makeSchema({ type: "null" }),
2338
+ literal: (value) => makeSchema({ const: value }),
2339
+ enum: (values) => makeSchema({ enum: [...values] }),
2340
+ array: (item, options = {}) => {
2341
+ rejectRawBodyComposition("array", [item]);
2342
+ return makeSchema({ ...options, type: "array", items: item.jsonSchema });
2343
+ },
2344
+ tuple: (items) => {
2345
+ rejectRawBodyComposition("tuple", items);
2346
+ return makeSchema({
2347
+ type: "array",
2348
+ prefixItems: items.map((item) => item.jsonSchema),
2349
+ minItems: items.length,
2350
+ maxItems: items.length
2351
+ });
2352
+ },
2353
+ record: (value) => {
2354
+ rejectRawBodyComposition("record", [value]);
2355
+ return makeSchema({
2356
+ type: "object",
2357
+ additionalProperties: value.jsonSchema
2358
+ });
2359
+ },
2360
+ object: (properties) => {
2361
+ rejectRawBodyComposition("object", Object.values(properties));
2362
+ return makeSchema({
2363
+ type: "object",
2364
+ properties: Object.fromEntries(
2365
+ Object.entries(properties).map(([key, item]) => [key, item.jsonSchema])
2366
+ ),
2367
+ required: Object.keys(properties),
2368
+ additionalProperties: false
2369
+ });
2370
+ },
2371
+ union: (...choices) => {
2372
+ rejectRawBodyComposition("union", choices);
2373
+ return makeSchema({ anyOf: choices.map((choice) => choice.jsonSchema) });
2374
+ },
2375
+ nullable: (value) => {
2376
+ rejectRawBodyComposition("nullable", [value]);
2377
+ return makeSchema({ anyOf: [value.jsonSchema, { type: "null" }] });
2378
+ },
2379
+ file: () => makeSchema({ type: "tensorlake_file" }, "file"),
2380
+ httpBody: () => makeSchema({ type: "tensorlake_http_body" }, "httpBody"),
2381
+ custom: (jsonSchema) => makeSchema({ ...jsonSchema }),
2382
+ parameter
2383
+ };
2384
+ var validatorCache = /* @__PURE__ */ new WeakMap();
2385
+ function compileValidator(jsonSchema) {
2386
+ const dialect = jsonSchema.$schema;
2387
+ const engine = typeof dialect === "string" && /\/draft-07\/schema#?$/.test(dialect) ? ajvDraft7 : ajv2020;
2388
+ const validate = engine.compile(jsonSchema);
2389
+ return {
2390
+ validate,
2391
+ errorsText: (errors) => engine.errorsText(errors, { separator: "; " })
2392
+ };
2393
+ }
2394
+ function validateWithSchema(valueSchema, value, label) {
2395
+ if (valueSchema._file) {
2396
+ if (!isFile(value)) {
2397
+ throw new SDKUsageError(`${label} must be a Tensorlake File`);
2398
+ }
2399
+ return value;
2400
+ }
2401
+ if (valueSchema._httpBody) {
2402
+ if (!isHttpBody(value)) {
2403
+ throw new SDKUsageError(`${label} must be a Tensorlake HttpBody`);
2404
+ }
2405
+ return value;
2406
+ }
2407
+ if (isFile(value)) {
2408
+ throw new SDKUsageError(`${label} must use schema.file() for a Tensorlake File`);
2409
+ }
2410
+ if (isHttpBody(value)) {
2411
+ throw new SDKUsageError(
2412
+ `${label} must use schema.httpBody() for a Tensorlake HttpBody`
2413
+ );
2414
+ }
2415
+ let cached = validatorCache.get(valueSchema);
2416
+ if (cached == null) {
2417
+ try {
2418
+ cached = compileValidator(valueSchema.jsonSchema);
2419
+ } catch (error) {
2420
+ const details = error instanceof Error ? error.message : String(error);
2421
+ throw new SDKUsageError(`${label} uses an invalid JSON schema: ${details}`);
2422
+ }
2423
+ validatorCache.set(valueSchema, cached);
2424
+ }
2425
+ if (!cached.validate(value)) {
2426
+ const details = cached.errorsText(cached.validate.errors);
2427
+ throw new SDKUsageError(`${label} does not match its schema: ${details}`);
2428
+ }
2429
+ return value;
2430
+ }
2431
+ function parameterJSONSchema(parameter2) {
2432
+ const result = {
2433
+ ...parameter2.schema.jsonSchema,
2434
+ title: parameter2.name,
2435
+ parameter_kind: "POSITIONAL_OR_KEYWORD"
2436
+ };
2437
+ if (parameter2.description != null) result.description = parameter2.description;
2438
+ if (parameter2.hasDefault) {
2439
+ result.default = parameter2.schema._file || parameter2.schema._httpBody ? true : parameter2.defaultValue;
2440
+ }
2441
+ return result;
2442
+ }
2443
+
2444
+ // src/applications/registry.ts
2445
+ init_cjs_shims();
2446
+ var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("tensorlake.applications.registry.v1");
2447
+ function registry() {
2448
+ const target = globalThis;
2449
+ target[REGISTRY_KEY] ??= { functions: /* @__PURE__ */ new Map(), applications: /* @__PURE__ */ new Map() };
2450
+ return target[REGISTRY_KEY];
2451
+ }
2452
+ function registerDefinition(definition, isApplication) {
2453
+ const state = registry();
2454
+ const existing = state.functions.get(definition.name);
2455
+ if (existing != null && existing !== definition) {
2456
+ throw new SDKUsageError(`Multiple Tensorlake functions are named '${definition.name}'`);
2457
+ }
2458
+ state.functions.set(definition.name, definition);
2459
+ if (isApplication) {
2460
+ const app = state.applications.get(definition.name);
2461
+ if (app != null && app !== definition) {
2462
+ throw new SDKUsageError(`Multiple Tensorlake applications are named '${definition.name}'`);
2463
+ }
2464
+ state.applications.set(definition.name, definition);
2465
+ }
2466
+ }
2467
+ function getFunction(name) {
2468
+ const result = registry().functions.get(name);
2469
+ if (result == null) throw new SDKUsageError(`Tensorlake function '${name}' is not registered`);
2470
+ return result;
2471
+ }
2472
+ function getFunctions() {
2473
+ return [...registry().functions.values()];
2474
+ }
2475
+ function getApplications() {
2476
+ return [...registry().applications.values()];
2477
+ }
2478
+
2479
+ // src/applications/function.ts
2480
+ function retries(options) {
2481
+ if (typeof options !== "object" || options == null || !Number.isInteger(options.maxRetries) || options.maxRetries < 0 || options.maxRetries > 10) {
2482
+ throw new SDKUsageError("maxRetries must be an integer between 0 and 10");
2483
+ }
2484
+ return Object.freeze({ ...options });
2485
+ }
2486
+ var TAIL_CALL_BRAND = /* @__PURE__ */ Symbol.for(
2487
+ "tensorlake.applications.tail-call.v1"
2488
+ );
2489
+ var DURABLE_PROMISE_OBSERVER = /* @__PURE__ */ Symbol.for(
2490
+ "tensorlake.applications.durable-promise-observer.v1"
2491
+ );
2492
+ var DURABLE_PROMISE_INTERNAL_THEN = /* @__PURE__ */ Symbol.for(
2493
+ "tensorlake.applications.durable-promise-internal-then.v1"
2494
+ );
2495
+ var FUNCTION_RUNTIME_STORAGE_KEY = /* @__PURE__ */ Symbol.for(
2496
+ "tensorlake.applications.function-runtime-storage.v1"
2497
+ );
2498
+ var DURABLE_THENABLE_REGISTRY_KEY = /* @__PURE__ */ Symbol.for(
2499
+ "tensorlake.applications.durable-thenable-registry.v2"
2500
+ );
2501
+ var INTERNAL_PROMISE_AGGREGATE_DEPTH_KEY = /* @__PURE__ */ Symbol.for(
2502
+ "tensorlake.applications.internal-promise-aggregate-depth.v1"
2503
+ );
2504
+ var futureCompletionCounter = 0;
2505
+ function runtimeStorage() {
2506
+ const target = globalThis;
2507
+ target[FUNCTION_RUNTIME_STORAGE_KEY] ??= new import_node_async_hooks.AsyncLocalStorage();
2508
+ return target[FUNCTION_RUNTIME_STORAGE_KEY];
2509
+ }
2510
+ function currentFunctionRuntime() {
2511
+ return runtimeStorage().getStore();
2512
+ }
2513
+ function runWithFunctionRuntime(runtime, callback) {
2514
+ return runtimeStorage().run(runtime, callback);
2515
+ }
2516
+ var FunctionFuture = class _FunctionFuture {
2517
+ id = (0, import_node_crypto.randomUUID)();
2518
+ definition;
2519
+ args;
2520
+ promise;
2521
+ startDelaySeconds = 0;
2522
+ completionOrder;
2523
+ failed = false;
2524
+ exception;
2525
+ done = false;
2526
+ constructor(definition, args) {
2527
+ this.definition = definition;
2528
+ this.args = args;
2529
+ registerDurableThenable(this);
2530
+ }
2531
+ run() {
2532
+ if (this.promise != null) throw new SDKUsageError(`Future ${this.id} is already running`);
2533
+ const runtime = currentFunctionRuntime();
2534
+ const promise = runtime == null ? executeHandler(this.definition, this.args) : runtime.runFuture(this);
2535
+ registerDurableThenable(promise, this);
2536
+ this.promise = promise;
2537
+ const onfulfilled = (value) => {
2538
+ this.done = true;
2539
+ this.completionOrder = futureCompletionCounter;
2540
+ futureCompletionCounter += 1;
2541
+ return value;
2542
+ };
2543
+ const onrejected = (error) => {
2544
+ this.done = true;
2545
+ this.failed = true;
2546
+ this.exception = error;
2547
+ this.completionOrder = futureCompletionCounter;
2548
+ futureCompletionCounter += 1;
2549
+ };
2550
+ const observer = promise[DURABLE_PROMISE_OBSERVER];
2551
+ if (observer != null) {
2552
+ observer.call(promise, onfulfilled, onrejected);
2553
+ } else {
2554
+ void promise.then(
2555
+ (value) => {
2556
+ onfulfilled(value);
2557
+ },
2558
+ (error) => {
2559
+ onrejected(error);
2560
+ }
2561
+ );
2562
+ }
2563
+ return this;
2564
+ }
2565
+ runLater(delaySeconds) {
2566
+ if (!Number.isFinite(delaySeconds) || delaySeconds < 0) {
2567
+ throw new SDKUsageError("Future delay must be a non-negative finite number");
2568
+ }
2569
+ if (this.promise != null) {
2570
+ throw new SDKUsageError(`Future ${this.id} is already running`);
2571
+ }
2572
+ this.startDelaySeconds = delaySeconds;
2573
+ return this.run();
2574
+ }
2575
+ get delaySeconds() {
2576
+ return this.startDelaySeconds;
2577
+ }
2578
+ result() {
2579
+ if (this.promise == null) this.run();
2580
+ return this.promise;
2581
+ }
2582
+ then(onfulfilled, onrejected) {
2583
+ return this.result().then(onfulfilled, onrejected);
2584
+ }
2585
+ static wait(futures, options = {}) {
2586
+ const completion = _FunctionFuture.waitForFutures(futures, options);
2587
+ return currentFunctionRuntime()?.wrapFutureWait?.(completion) ?? completion;
2588
+ }
2589
+ static async waitForFutures(futures, options) {
2590
+ const returnWhen = options.returnWhen ?? "all_completed";
2591
+ if (!["all_completed", "first_completed", "first_failure"].includes(returnWhen)) {
2592
+ throw new SDKUsageError(`Unsupported Future.wait returnWhen value '${returnWhen}'`);
2593
+ }
2594
+ if (options.timeout != null && (!Number.isFinite(options.timeout) || options.timeout < 0)) {
2595
+ throw new SDKUsageError("Future.wait timeout must be a non-negative finite number");
2596
+ }
2597
+ futures.forEach((future) => {
2598
+ if (future.promise == null) future.run();
2599
+ });
2600
+ const alreadyDone = futures.filter((future) => future.done);
2601
+ if (alreadyDone.length > 0 && (returnWhen === "first_completed" || returnWhen === "first_failure" && alreadyDone.some((future) => future.failed))) {
2602
+ return {
2603
+ done: alreadyDone,
2604
+ notDone: futures.filter((future) => !future.done)
2605
+ };
2606
+ }
2607
+ const pending = futures.filter((future) => !future.done);
2608
+ if (pending.length === 0) {
2609
+ return { done: [...futures], notDone: [] };
2610
+ }
2611
+ let wait;
2612
+ if (returnWhen === "all_completed") {
2613
+ wait = internalPromiseAll(
2614
+ pending.map((future) => internalDurableThen(
2615
+ future.result(),
2616
+ () => void 0,
2617
+ () => void 0
2618
+ ))
2619
+ ).then(() => ({ kind: "all_completed" }));
2620
+ } else if (returnWhen === "first_completed") {
2621
+ wait = internalPromiseRace(
2622
+ pending.map((future) => internalDurableThen(
2623
+ future.result(),
2624
+ () => ({ kind: "cutoff", future }),
2625
+ () => ({ kind: "cutoff", future })
2626
+ ))
2627
+ );
2628
+ } else {
2629
+ wait = new Promise((resolve) => {
2630
+ let remaining = pending.length;
2631
+ for (const future of pending) {
2632
+ void internalDurableThen(
2633
+ future.result(),
2634
+ () => {
2635
+ remaining -= 1;
2636
+ if (remaining === 0) resolve({ kind: "all_completed" });
2637
+ },
2638
+ () => resolve({ kind: "cutoff", future })
2639
+ );
2640
+ }
2641
+ });
2642
+ }
2643
+ const outcome = await waitUntilOrTimeout(wait, options.timeout);
2644
+ if (outcome.kind === "cutoff") {
2645
+ const completionCutoff = outcome.future.completionOrder;
2646
+ if (completionCutoff == null) {
2647
+ throw new SDKUsageError("Future.wait winner has no completion order");
2648
+ }
2649
+ const doneSet = new Set(alreadyDone);
2650
+ for (const future of pending) {
2651
+ if (future.done && future.completionOrder != null && future.completionOrder <= completionCutoff) {
2652
+ doneSet.add(future);
2653
+ }
2654
+ }
2655
+ return {
2656
+ done: futures.filter((future) => doneSet.has(future)),
2657
+ notDone: futures.filter((future) => !doneSet.has(future))
2658
+ };
2659
+ }
2660
+ return {
2661
+ done: futures.filter((future) => future.done),
2662
+ notDone: futures.filter((future) => !future.done)
2663
+ };
2664
+ }
2665
+ };
2666
+ async function waitUntilOrTimeout(promise, timeoutSeconds) {
2667
+ if (timeoutSeconds == null) {
2668
+ return promise;
2669
+ }
2670
+ let timer;
2671
+ try {
2672
+ return await internalPromiseRace([
2673
+ promise,
2674
+ new Promise((resolve) => {
2675
+ timer = setTimeout(() => resolve({ kind: "timeout" }), timeoutSeconds * 1e3);
2676
+ })
2677
+ ]);
2678
+ } finally {
2679
+ if (timer != null) clearTimeout(timer);
2680
+ }
2681
+ }
2682
+ function durableThenableRegistry() {
2683
+ const target = globalThis;
2684
+ target[DURABLE_THENABLE_REGISTRY_KEY] ??= /* @__PURE__ */ new WeakMap();
2685
+ return target[DURABLE_THENABLE_REGISTRY_KEY];
2686
+ }
2687
+ function newDurableThenableMetadata() {
2688
+ return {
2689
+ aggregateExpectations: [],
2690
+ provenanceExpectations: []
2691
+ };
2692
+ }
2693
+ function registerDurableThenable(value, source) {
2694
+ const registry2 = durableThenableRegistry();
2695
+ const metadata = source == null ? registry2.get(value)?.metadata ?? newDurableThenableMetadata() : registry2.get(source)?.metadata ?? newDurableThenableMetadata();
2696
+ registry2.set(value, { metadata });
2697
+ if (source != null && !registry2.has(source)) registry2.set(source, { metadata });
2698
+ return value;
2699
+ }
2700
+ function internalDurableThen(promise, onfulfilled, onrejected) {
2701
+ const internalThen = promise[DURABLE_PROMISE_INTERNAL_THEN];
2702
+ if (internalThen != null) {
2703
+ return internalThen.call(
2704
+ promise,
2705
+ onfulfilled,
2706
+ onrejected
2707
+ );
2708
+ }
2709
+ return promise.then(onfulfilled, onrejected);
2710
+ }
2711
+ function internalAwaitable(value) {
2712
+ if ((typeof value === "object" || typeof value === "function") && value != null) {
2713
+ const internalThen = value[DURABLE_PROMISE_INTERNAL_THEN];
2714
+ if (internalThen != null) {
2715
+ return internalThen.call(
2716
+ value,
2717
+ (resolved) => resolved,
2718
+ (error) => {
2719
+ throw error;
2720
+ }
2721
+ );
2722
+ }
2723
+ }
2724
+ return Promise.resolve(value);
2725
+ }
2726
+ async function resolveAwaitableIterable(items) {
2727
+ const iterable = await internalAwaitable(items);
2728
+ return internalPromiseAll([...iterable].map((item) => internalAwaitable(item)));
2729
+ }
2730
+ function wrapDurableAggregate(completion) {
2731
+ return currentFunctionRuntime()?.wrapFutureWait?.(completion) ?? completion;
2732
+ }
2733
+ function runInternalPromiseAggregate(callback) {
2734
+ const target = globalThis;
2735
+ target[INTERNAL_PROMISE_AGGREGATE_DEPTH_KEY] = (target[INTERNAL_PROMISE_AGGREGATE_DEPTH_KEY] ?? 0) + 1;
2736
+ try {
2737
+ return callback();
2738
+ } finally {
2739
+ const remaining = (target[INTERNAL_PROMISE_AGGREGATE_DEPTH_KEY] ?? 1) - 1;
2740
+ if (remaining === 0) delete target[INTERNAL_PROMISE_AGGREGATE_DEPTH_KEY];
2741
+ else target[INTERNAL_PROMISE_AGGREGATE_DEPTH_KEY] = remaining;
2742
+ }
2743
+ }
2744
+ function internalPromiseAll(values) {
2745
+ return runInternalPromiseAggregate(() => Promise.all(values));
2746
+ }
2747
+ function internalPromiseRace(values) {
2748
+ return runInternalPromiseAggregate(() => Promise.race(values));
2749
+ }
2750
+ function normalizeOptions(options) {
2751
+ validateGPUOption(options.gpu);
2752
+ if (options.secrets != null && !Array.isArray(options.secrets)) {
2753
+ throw new SDKUsageError("secrets must be an array of non-empty strings");
2754
+ }
2755
+ const normalizedRetries = options.retries == null ? void 0 : retries(options.retries);
2756
+ const result = {
2757
+ description: options.description ?? "",
2758
+ cpu: options.cpu ?? 1,
2759
+ memory: options.memory ?? 1,
2760
+ ephemeralDisk: options.ephemeralDisk ?? 10,
2761
+ gpu: Array.isArray(options.gpu) ? [...options.gpu] : options.gpu ?? null,
2762
+ timeout: options.timeout ?? 300,
2763
+ image: options.image,
2764
+ secrets: [...options.secrets ?? []],
2765
+ retries: normalizedRetries,
2766
+ region: options.region,
2767
+ warmContainers: options.warmContainers,
2768
+ minContainers: options.minContainers,
2769
+ maxContainers: options.maxContainers
2770
+ };
2771
+ if (!Number.isFinite(result.cpu) || result.cpu <= 0) throw new SDKUsageError("cpu must be greater than zero");
2772
+ if (!Number.isFinite(result.memory) || result.memory <= 0) throw new SDKUsageError("memory must be greater than zero");
2773
+ if (!Number.isFinite(result.ephemeralDisk) || result.ephemeralDisk <= 0) throw new SDKUsageError("ephemeralDisk must be greater than zero");
2774
+ if (!Number.isInteger(result.timeout) || result.timeout <= 0 || result.timeout > 86400) {
2775
+ throw new SDKUsageError("timeout must be an integer between 1 and 86400 seconds");
2776
+ }
2777
+ for (const [label, value] of [
2778
+ ["warmContainers", result.warmContainers],
2779
+ ["minContainers", result.minContainers],
2780
+ ["maxContainers", result.maxContainers]
2781
+ ]) {
2782
+ if (value != null && (!Number.isInteger(value) || value < 0)) {
2783
+ throw new SDKUsageError(`${label} must be a non-negative integer`);
2784
+ }
2785
+ }
2786
+ if (result.minContainers != null && result.maxContainers != null && result.minContainers > result.maxContainers) {
2787
+ throw new SDKUsageError("minContainers cannot exceed maxContainers");
2788
+ }
2789
+ if (result.warmContainers != null && result.maxContainers != null && result.warmContainers > result.maxContainers) {
2790
+ throw new SDKUsageError("warmContainers cannot exceed maxContainers");
2791
+ }
2792
+ if (result.region != null && !["us-east-1", "eu-west-1"].includes(result.region)) {
2793
+ throw new SDKUsageError(`Unsupported region '${result.region}'`);
2794
+ }
2795
+ if (result.secrets.some((secret) => typeof secret !== "string" || secret.length === 0)) {
2796
+ throw new SDKUsageError("secrets must contain non-empty strings");
2797
+ }
2798
+ return result;
2799
+ }
2800
+ function validateGPUOption(value) {
2801
+ if (value == null) return;
2802
+ const values = Array.isArray(value) ? value : [value];
2803
+ for (const setting of values) {
2804
+ if (typeof setting !== "string") {
2805
+ throw new SDKUsageError("gpu must be a GPU model or an array of GPU models");
2806
+ }
2807
+ const [model, countText, ...extra] = setting.split(":");
2808
+ const count = countText == null ? 1 : Number(countText);
2809
+ if (!model || extra.length > 0 || !Number.isInteger(count) || count <= 0 || countText != null && String(count) !== countText) {
2810
+ throw new SDKUsageError(`Invalid GPU setting '${setting}'`);
2811
+ }
2812
+ }
2813
+ }
2814
+ function validateArguments(definition, supplied) {
2815
+ const args = [...supplied];
2816
+ if (args.length > definition.parameters.length) {
2817
+ throw new SDKUsageError(`${definition.name} expected at most ${definition.parameters.length} arguments, received ${args.length}`);
2818
+ }
2819
+ definition.parameters.forEach((parameter2, index) => {
2820
+ if (index >= args.length || args[index] === void 0) {
2821
+ if (parameter2.hasDefault) args[index] = parameter2.defaultValue;
2822
+ else if (parameter2.required) throw new SDKUsageError(`${definition.name} is missing argument '${parameter2.name}'`);
2823
+ return;
2824
+ }
2825
+ validateWithSchema(parameter2.schema, args[index], `${definition.name}.${parameter2.name}`);
2826
+ });
2827
+ return args;
2828
+ }
2829
+ async function executeHandler(definition, suppliedArgs) {
2830
+ const output = await executeHandlerResult(definition, suppliedArgs);
2831
+ if (isTailCall(output)) {
2832
+ const runtime = currentFunctionRuntime();
2833
+ if (runtime == null) return executeHandler(output.definition, output.args);
2834
+ return runtime.invoke(output.definition, output.args);
2835
+ }
2836
+ return output;
2837
+ }
2838
+ async function executeHandlerResult(definition, suppliedArgs) {
2839
+ const args = validateArguments(definition, suppliedArgs);
2840
+ const result = definition.handler(...args);
2841
+ if (result == null || typeof result.then !== "function") {
2842
+ throw new SDKUsageError(`Tensorlake handler '${definition.name}' must be async and return a Promise`);
2843
+ }
2844
+ const output = await result;
2845
+ if (isTailCall(output)) {
2846
+ return output;
2847
+ }
2848
+ validateWithSchema(definition.returns, output, `${definition.name} return value`);
2849
+ return output;
2850
+ }
2851
+ function isTailCall(value) {
2852
+ if (typeof value !== "object" || value == null) return false;
2853
+ const candidate = value;
2854
+ return candidate[TAIL_CALL_BRAND] === true && candidate.kind === "tensorlake-tail-call" && typeof candidate.definition === "object" && candidate.definition != null && Array.isArray(candidate.args);
2855
+ }
2856
+ function createRegisteredFunction(definition) {
2857
+ const callable = ((...args) => {
2858
+ const runtime = currentFunctionRuntime();
2859
+ return runtime == null ? executeHandler(definition, args) : runtime.invoke(definition, args);
2860
+ });
2861
+ Object.defineProperties(callable, {
2862
+ definition: { value: definition, enumerable: true },
2863
+ future: { value: (...args) => new FunctionFuture(definition, args) },
2864
+ map: {
2865
+ value: (items) => {
2866
+ const completion = (async () => {
2867
+ const resolvedItems = await resolveAwaitableIterable(items);
2868
+ return internalPromiseAll(
2869
+ resolvedItems.map(
2870
+ (item) => internalAwaitable(callable(...[item]))
2871
+ )
2872
+ );
2873
+ })();
2874
+ return wrapDurableAggregate(completion);
2875
+ }
2876
+ },
2877
+ reduce: {
2878
+ value: (items, ...initialValues) => {
2879
+ const completion = (async () => {
2880
+ let values = await resolveAwaitableIterable(items);
2881
+ const hasInitial = initialValues.length > 0;
2882
+ let initial = initialValues[0];
2883
+ const runtime = currentFunctionRuntime();
2884
+ if (runtime != null) {
2885
+ return internalAwaitable(
2886
+ runtime.reduce(definition, values, initial, hasInitial)
2887
+ );
2888
+ }
2889
+ if (!hasInitial) {
2890
+ if (values.length === 0) {
2891
+ throw new SDKUsageError("reduce of empty iterable with no initial value");
2892
+ }
2893
+ [initial, ...values] = values;
2894
+ }
2895
+ let accumulator = initial;
2896
+ for (const item of values) {
2897
+ accumulator = await internalAwaitable(
2898
+ callable(...[accumulator, item])
2899
+ );
2900
+ }
2901
+ return accumulator;
2902
+ })();
2903
+ return wrapDurableAggregate(completion);
2904
+ }
2905
+ },
2906
+ tailCall: {
2907
+ value: (...args) => ({
2908
+ [TAIL_CALL_BRAND]: true,
2909
+ kind: "tensorlake-tail-call",
2910
+ definition,
2911
+ args
2912
+ })
2913
+ }
2914
+ });
2915
+ return callable;
2916
+ }
2917
+ function register(handler, options, application) {
2918
+ const name = options.name ?? handler.name;
2919
+ if (!name) throw new SDKUsageError("Anonymous Tensorlake handlers require an explicit name");
2920
+ if (!/^[A-Za-z_$][\w$]*$/.test(name)) throw new SDKUsageError(`Invalid Tensorlake function name '${name}'`);
2921
+ let applicationRetries;
2922
+ if (application) {
2923
+ const appOptions = options;
2924
+ applicationRetries = retries(appOptions.applicationRetries ?? { maxRetries: 0 });
2925
+ if (appOptions.allow != null && (!Array.isArray(appOptions.allow) || appOptions.allow.some(
2926
+ (capability) => capability !== "unauthenticated_requests"
2927
+ ))) {
2928
+ throw new SDKUsageError(
2929
+ "Application allow must contain only 'unauthenticated_requests'"
2930
+ );
2931
+ }
2932
+ const tags = appOptions.tags;
2933
+ const tagsPrototype = tags == null || typeof tags !== "object" ? void 0 : Object.getPrototypeOf(tags);
2934
+ if (tags != null && (typeof tags !== "object" || Array.isArray(tags) || tagsPrototype !== Object.prototype && tagsPrototype !== null || Reflect.ownKeys(tags).some(
2935
+ (key) => typeof key !== "string" || !key || typeof tags[key] !== "string"
2936
+ ))) {
2937
+ throw new SDKUsageError("Application tags require non-empty string keys and string values");
2938
+ }
2939
+ }
2940
+ if (!Array.isArray(options.parameters)) {
2941
+ throw new SDKUsageError("Tensorlake registration parameters must be an array");
2942
+ }
2943
+ if (typeof options.returns !== "object" || options.returns == null || typeof options.returns.jsonSchema !== "object" || options.returns.jsonSchema == null) {
2944
+ throw new SDKUsageError("Tensorlake registration returns must be a schema");
2945
+ }
2946
+ const parameterNames = /* @__PURE__ */ new Set();
2947
+ for (const parameter2 of options.parameters) {
2948
+ if (typeof parameter2 !== "object" || parameter2 == null || typeof parameter2.name !== "string" || typeof parameter2.schema !== "object" || parameter2.schema == null || typeof parameter2.schema.jsonSchema !== "object" || parameter2.schema.jsonSchema == null || typeof parameter2.required !== "boolean" || typeof parameter2.hasDefault !== "boolean") {
2949
+ throw new SDKUsageError(
2950
+ "Tensorlake registration parameters must be created with schema.parameter()"
2951
+ );
2952
+ }
2953
+ if (parameterNames.has(parameter2.name)) {
2954
+ throw new SDKUsageError(`Duplicate Tensorlake parameter name '${parameter2.name}'`);
2955
+ }
2956
+ parameterNames.add(parameter2.name);
2957
+ }
2958
+ const httpBodyParameter = options.parameters.find(
2959
+ (parameter2) => parameter2.schema._httpBody
2960
+ );
2961
+ if (httpBodyParameter != null && !application) {
2962
+ throw new SDKUsageError(
2963
+ "HttpBody is only supported for application parameters"
2964
+ );
2965
+ }
2966
+ if (options.returns._httpBody) {
2967
+ throw new SDKUsageError(
2968
+ "HttpBody is only supported for application parameters; use schema.file() or a JSON-compatible return schema instead"
2969
+ );
2970
+ }
2971
+ const definition = {
2972
+ name,
2973
+ handler,
2974
+ parameters: [...options.parameters],
2975
+ returns: options.returns,
2976
+ options: normalizeOptions(options),
2977
+ application: application ? {
2978
+ tags: { ...options.tags ?? {} },
2979
+ retries: applicationRetries,
2980
+ allow: [...options.allow ?? []],
2981
+ version: (0, import_node_crypto.randomUUID)().replaceAll("-", "")
2982
+ } : void 0
2983
+ };
2984
+ registerDefinition(definition, application);
2985
+ return createRegisteredFunction(definition);
2986
+ }
2987
+ function hasExplicitSchemas(value) {
2988
+ if (typeof value !== "object" || value == null) return false;
2989
+ const hasParameters = Object.prototype.hasOwnProperty.call(value, "parameters");
2990
+ const hasReturns = Object.prototype.hasOwnProperty.call(value, "returns");
2991
+ if (hasParameters !== hasReturns) {
2992
+ throw new SDKUsageError("Tensorlake registrations must specify both parameters and returns");
2993
+ }
2994
+ return hasParameters;
2995
+ }
2996
+ function skipJavaScriptLiteral(source, start) {
2997
+ const quote = source[start];
2998
+ let escaped = false;
2999
+ for (let index = start + 1; index < source.length; index += 1) {
3000
+ const character = source[index];
3001
+ if (escaped) {
3002
+ escaped = false;
3003
+ } else if (character === "\\") {
3004
+ escaped = true;
3005
+ } else if (character === quote) {
3006
+ return index;
3007
+ }
3008
+ }
3009
+ return source.length - 1;
3010
+ }
3011
+ function skipJavaScriptComment(source, start) {
3012
+ if (source[start] !== "/") return void 0;
3013
+ if (source[start + 1] === "/") {
3014
+ const newline = source.indexOf("\n", start + 2);
3015
+ return newline < 0 ? source.length - 1 : newline;
3016
+ }
3017
+ if (source[start + 1] === "*") {
3018
+ const end = source.indexOf("*/", start + 2);
3019
+ return end < 0 ? source.length - 1 : end + 1;
3020
+ }
3021
+ return void 0;
3022
+ }
3023
+ function skipJavaScriptTrivia(source, start) {
3024
+ let index = start;
3025
+ while (index < source.length) {
3026
+ while (index < source.length && /\s/.test(source[index])) index += 1;
3027
+ const commentEnd = skipJavaScriptComment(source, index);
3028
+ if (commentEnd == null) break;
3029
+ index = commentEnd + 1;
3030
+ }
3031
+ return index;
3032
+ }
3033
+ var REGEX_PREFIX_KEYWORDS = /* @__PURE__ */ new Set([
3034
+ "await",
3035
+ "case",
3036
+ "delete",
3037
+ "in",
3038
+ "instanceof",
3039
+ "new",
3040
+ "return",
3041
+ "throw",
3042
+ "typeof",
3043
+ "void",
3044
+ "yield"
3045
+ ]);
3046
+ function regexLiteralStartsAt(source, start) {
3047
+ let expectsExpression = true;
3048
+ for (let index = 0; index < start; index += 1) {
3049
+ const character = source[index];
3050
+ if (/\s/.test(character)) continue;
3051
+ if (character === '"' || character === "'" || character === "`") {
3052
+ index = skipJavaScriptLiteral(source, index);
3053
+ expectsExpression = false;
3054
+ continue;
3055
+ }
3056
+ const commentEnd = skipJavaScriptComment(source, index);
3057
+ if (commentEnd != null) {
3058
+ index = commentEnd;
3059
+ continue;
3060
+ }
3061
+ if (/[A-Za-z_$]/.test(character)) {
3062
+ let tokenEnd = index + 1;
3063
+ while (tokenEnd < start && /[A-Za-z0-9_$]/.test(source[tokenEnd])) tokenEnd += 1;
3064
+ expectsExpression = REGEX_PREFIX_KEYWORDS.has(source.slice(index, tokenEnd));
3065
+ index = tokenEnd - 1;
3066
+ continue;
3067
+ }
3068
+ if (/[0-9]/.test(character) || character === "." && /[0-9]/.test(source[index + 1])) {
3069
+ while (index + 1 < start && /[A-Za-z0-9_.]/.test(source[index + 1])) index += 1;
3070
+ expectsExpression = false;
3071
+ continue;
3072
+ }
3073
+ if (character === "/") {
3074
+ if (expectsExpression) {
3075
+ index = skipJavaScriptRegex(source, index);
3076
+ expectsExpression = false;
3077
+ } else {
3078
+ if (source[index + 1] === "=") index += 1;
3079
+ expectsExpression = true;
3080
+ }
3081
+ continue;
3082
+ }
3083
+ if (character === ")" || character === "]" || character === "}") {
3084
+ expectsExpression = false;
3085
+ continue;
3086
+ }
3087
+ if (character === ".") {
3088
+ if (source.slice(index, index + 3) === "...") {
3089
+ index += 2;
3090
+ expectsExpression = true;
3091
+ } else {
3092
+ expectsExpression = false;
3093
+ }
3094
+ continue;
3095
+ }
3096
+ if ((character === "+" || character === "-") && source[index + 1] === character) {
3097
+ index += 1;
3098
+ continue;
3099
+ }
3100
+ expectsExpression = true;
3101
+ }
3102
+ return expectsExpression;
3103
+ }
3104
+ function skipJavaScriptRegex(source, start) {
3105
+ let escaped = false;
3106
+ let characterClass = false;
3107
+ for (let index = start + 1; index < source.length; index += 1) {
3108
+ const character = source[index];
3109
+ if (escaped) {
3110
+ escaped = false;
3111
+ } else if (character === "\\") {
3112
+ escaped = true;
3113
+ } else if (character === "[") {
3114
+ characterClass = true;
3115
+ } else if (character === "]") {
3116
+ characterClass = false;
3117
+ } else if (character === "/" && !characterClass) {
3118
+ while (index + 1 < source.length && /[A-Za-z]/.test(source[index + 1])) index += 1;
3119
+ return index;
3120
+ }
3121
+ }
3122
+ return source.length - 1;
3123
+ }
3124
+ function skipJavaScriptValue(source, index) {
3125
+ const character = source[index];
3126
+ if (character === '"' || character === "'" || character === "`") {
3127
+ return skipJavaScriptLiteral(source, index);
3128
+ }
3129
+ const commentEnd = skipJavaScriptComment(source, index);
3130
+ if (commentEnd != null) return commentEnd;
3131
+ if (character === "/" && regexLiteralStartsAt(source, index)) {
3132
+ return skipJavaScriptRegex(source, index);
3133
+ }
3134
+ return void 0;
3135
+ }
3136
+ function findTopLevelArrow(source) {
3137
+ let parentheses = 0;
3138
+ let brackets = 0;
3139
+ let braces = 0;
3140
+ for (let index = 0; index < source.length - 1; index += 1) {
3141
+ const character = source[index];
3142
+ const valueEnd = skipJavaScriptValue(source, index);
3143
+ if (valueEnd != null) {
3144
+ index = valueEnd;
3145
+ continue;
3146
+ }
3147
+ if (character === "(") parentheses += 1;
3148
+ else if (character === ")") parentheses -= 1;
3149
+ else if (character === "[") brackets += 1;
3150
+ else if (character === "]") brackets -= 1;
3151
+ else if (character === "{") {
3152
+ if (parentheses === 0 && brackets === 0 && braces === 0) return -1;
3153
+ braces += 1;
3154
+ } else if (character === "}") braces -= 1;
3155
+ else if (character === "=" && source[index + 1] === ">" && parentheses === 0 && brackets === 0 && braces === 0) {
3156
+ return index;
3157
+ }
3158
+ }
3159
+ return -1;
3160
+ }
3161
+ function findClosingParenthesis(source, open) {
3162
+ let depth = 0;
3163
+ for (let index = open; index < source.length; index += 1) {
3164
+ const character = source[index];
3165
+ const valueEnd = skipJavaScriptValue(source, index);
3166
+ if (valueEnd != null) {
3167
+ index = valueEnd;
3168
+ continue;
3169
+ }
3170
+ if (character === "(") depth += 1;
3171
+ else if (character === ")" && --depth === 0) return index;
3172
+ }
3173
+ return -1;
3174
+ }
3175
+ function findOpeningParenthesis(source) {
3176
+ for (let index = 0; index < source.length; index += 1) {
3177
+ const valueEnd = skipJavaScriptValue(source, index);
3178
+ if (valueEnd != null) {
3179
+ index = valueEnd;
3180
+ continue;
3181
+ }
3182
+ if (source[index] === "(") return index;
3183
+ }
3184
+ return -1;
3185
+ }
3186
+ function splitTopLevelParameters(source) {
3187
+ if (source.trim() === "") return [];
3188
+ const result = [];
3189
+ let start = 0;
3190
+ let parentheses = 0;
3191
+ let brackets = 0;
3192
+ let braces = 0;
3193
+ for (let index = 0; index < source.length; index += 1) {
3194
+ const character = source[index];
3195
+ const valueEnd = skipJavaScriptValue(source, index);
3196
+ if (valueEnd != null) {
3197
+ index = valueEnd;
3198
+ continue;
3199
+ }
3200
+ if (character === "(") parentheses += 1;
3201
+ else if (character === ")") parentheses -= 1;
3202
+ else if (character === "[") brackets += 1;
3203
+ else if (character === "]") brackets -= 1;
3204
+ else if (character === "{") braces += 1;
3205
+ else if (character === "}") braces -= 1;
3206
+ else if (character === "," && parentheses === 0 && brackets === 0 && braces === 0) {
3207
+ result.push(source.slice(start, index).trim());
3208
+ start = index + 1;
3209
+ }
3210
+ }
3211
+ const final = source.slice(start).trim();
3212
+ if (final !== "") result.push(final);
3213
+ return result;
3214
+ }
3215
+ function hasTopLevelDefault(source) {
3216
+ let parentheses = 0;
3217
+ let brackets = 0;
3218
+ let braces = 0;
3219
+ for (let index = 0; index < source.length; index += 1) {
3220
+ const character = source[index];
3221
+ const valueEnd = skipJavaScriptValue(source, index);
3222
+ if (valueEnd != null) {
3223
+ index = valueEnd;
3224
+ continue;
3225
+ }
3226
+ if (character === "(") parentheses += 1;
3227
+ else if (character === ")") parentheses -= 1;
3228
+ else if (character === "[") brackets += 1;
3229
+ else if (character === "]") brackets -= 1;
3230
+ else if (character === "{") braces += 1;
3231
+ else if (character === "}") braces -= 1;
3232
+ else if (character === "=" && parentheses === 0 && brackets === 0 && braces === 0) return true;
3233
+ }
3234
+ return false;
3235
+ }
3236
+ function declaredHandlerParameters(handler) {
3237
+ const source = Function.prototype.toString.call(handler).trim();
3238
+ if (source.includes("[native code]")) {
3239
+ throw new SDKUsageError("Schema-free registration cannot inspect a native or bound handler; specify parameters and returns");
3240
+ }
3241
+ const arrow = findTopLevelArrow(source);
3242
+ if (arrow >= 0) {
3243
+ let header = source.slice(0, arrow).trim();
3244
+ if (header.startsWith("async") && !/[A-Za-z0-9_$]/.test(header["async".length] ?? "")) {
3245
+ header = header.slice(skipJavaScriptTrivia(header, "async".length));
3246
+ }
3247
+ if (!header.startsWith("(")) return [header];
3248
+ const close2 = findClosingParenthesis(header, 0);
3249
+ if (close2 < 0) throw new SDKUsageError("Schema-free registration could not inspect handler parameters");
3250
+ return splitTopLevelParameters(header.slice(1, close2));
3251
+ }
3252
+ const open = findOpeningParenthesis(source);
3253
+ const close = open < 0 ? -1 : findClosingParenthesis(source, open);
3254
+ if (open < 0 || close < 0) {
3255
+ throw new SDKUsageError("Schema-free registration could not inspect handler parameters");
3256
+ }
3257
+ return splitTopLevelParameters(source.slice(open + 1, close));
3258
+ }
3259
+ function inferredJSONParameters(handler) {
3260
+ const parameters = declaredHandlerParameters(handler);
3261
+ if (parameters.some((parameter2) => {
3262
+ let index = 0;
3263
+ while (index < parameter2.length) {
3264
+ while (index < parameter2.length && /\s/.test(parameter2[index])) index += 1;
3265
+ const commentEnd = skipJavaScriptComment(parameter2, index);
3266
+ if (commentEnd == null) break;
3267
+ index = commentEnd + 1;
3268
+ }
3269
+ return parameter2.slice(index).startsWith("...");
3270
+ })) {
3271
+ throw new SDKUsageError(
3272
+ "Schema-free registration does not support rest parameters; specify explicit parameters and returns"
3273
+ );
3274
+ }
3275
+ return parameters.map((parameter2, index) => schema.parameter(
3276
+ parameters.length === 1 ? "input" : `arg${index}`,
3277
+ schema.json(),
3278
+ hasTopLevelDefault(parameter2) ? { optional: true } : {}
3279
+ ));
3280
+ }
3281
+ function registerWithDefaults(name, handler, options, application) {
3282
+ return register(
3283
+ handler,
3284
+ {
3285
+ ...options,
3286
+ name,
3287
+ parameters: inferredJSONParameters(handler),
3288
+ returns: schema.json()
3289
+ },
3290
+ application
3291
+ );
3292
+ }
3293
+ function registerFunction(handlerOrName, handlerOrOptions, options = {}) {
3294
+ if (typeof handlerOrName === "string") {
3295
+ if (typeof handlerOrOptions !== "function") {
3296
+ throw new SDKUsageError("registerFunction(name, handler) requires an async handler");
3297
+ }
3298
+ return registerWithDefaults(
3299
+ handlerOrName,
3300
+ handlerOrOptions,
3301
+ options,
3302
+ false
3303
+ );
3304
+ }
3305
+ if (typeof handlerOrName !== "function") {
3306
+ throw new SDKUsageError("registerFunction requires an async handler");
3307
+ }
3308
+ const handler = handlerOrName;
3309
+ if (typeof handlerOrOptions === "function") {
3310
+ throw new SDKUsageError("registerFunction received an unexpected second handler");
3311
+ }
3312
+ if (hasExplicitSchemas(handlerOrOptions)) {
3313
+ return register(
3314
+ handler,
3315
+ handlerOrOptions,
3316
+ false
3317
+ );
3318
+ }
3319
+ throw new SDKUsageError(
3320
+ "Schema-free functions require an explicit stable name: registerFunction(name, handler)"
3321
+ );
3322
+ }
3323
+ function registerApplication(handlerOrName, handlerOrOptions, options = {}) {
3324
+ if (typeof handlerOrName === "string") {
3325
+ if (typeof handlerOrOptions !== "function") {
3326
+ throw new SDKUsageError("registerApplication(name, handler) requires an async handler");
3327
+ }
3328
+ return registerWithDefaults(
3329
+ handlerOrName,
3330
+ handlerOrOptions,
3331
+ options,
3332
+ true
3333
+ );
3334
+ }
3335
+ if (typeof handlerOrName !== "function") {
3336
+ throw new SDKUsageError("registerApplication requires an async handler");
3337
+ }
3338
+ const handler = handlerOrName;
3339
+ if (typeof handlerOrOptions === "function") {
3340
+ throw new SDKUsageError("registerApplication received an unexpected second handler");
3341
+ }
3342
+ if (hasExplicitSchemas(handlerOrOptions)) {
3343
+ return register(
3344
+ handler,
3345
+ handlerOrOptions,
3346
+ true
3347
+ );
3348
+ }
3349
+ throw new SDKUsageError(
3350
+ "Schema-free applications require an explicit stable name: registerApplication(name, handler)"
3351
+ );
3352
+ }
3353
+
3354
+ // src/applications/headers.ts
3355
+ init_cjs_shims();
3356
+ var HEADERS_BRAND = /* @__PURE__ */ Symbol.for("tensorlake.applications.headers.v1");
3357
+ var Headers = class _Headers {
3358
+ [HEADERS_BRAND] = true;
3359
+ #items;
3360
+ #lookup;
3361
+ static [Symbol.hasInstance](value) {
3362
+ if (this !== _Headers) {
3363
+ return Function.prototype[Symbol.hasInstance].call(this, value);
3364
+ }
3365
+ return isHeaders(value);
3366
+ }
3367
+ constructor(headers = []) {
3368
+ const entries = headers instanceof _Headers ? [...headers] : Symbol.iterator in Object(headers) ? [...headers] : Object.entries(headers);
3369
+ const lookup = /* @__PURE__ */ new Map();
3370
+ this.#items = Object.freeze(entries.map(([name, value]) => {
3371
+ if (typeof name !== "string" || typeof value !== "string") {
3372
+ throw new TypeError("Headers require string names and values");
3373
+ }
3374
+ const item = Object.freeze([name, value]);
3375
+ const key = name.toLowerCase();
3376
+ lookup.set(key, [...lookup.get(key) ?? [], value]);
3377
+ return item;
3378
+ }));
3379
+ this.#lookup = lookup;
3380
+ Object.freeze(this);
3381
+ }
3382
+ get(name) {
3383
+ return this.#lookup.get(name.toLowerCase())?.at(-1);
3384
+ }
3385
+ getAll(name) {
3386
+ return Object.freeze([...this.#lookup.get(name.toLowerCase()) ?? []]);
3387
+ }
3388
+ has(name) {
3389
+ return this.#lookup.has(name.toLowerCase());
3390
+ }
3391
+ entries() {
3392
+ return this.#items[Symbol.iterator]();
3393
+ }
3394
+ [Symbol.iterator]() {
3395
+ return this.entries();
3396
+ }
3397
+ };
3398
+ function isHeaders(value) {
3399
+ if (typeof value !== "object" || value == null) return false;
3400
+ const candidate = value;
3401
+ return candidate[HEADERS_BRAND] === true && typeof candidate.get === "function" && typeof candidate.getAll === "function" && typeof candidate.has === "function" && typeof candidate[Symbol.iterator] === "function";
3402
+ }
3403
+
3404
+ // src/applications/index.ts
3405
+ init_image();
3406
+ init_defaults();
3407
+
3408
+ // src/applications/context.ts
3409
+ init_cjs_shims();
3410
+ var import_node_async_hooks2 = require("async_hooks");
3411
+
3412
+ // src/applications/serialization.ts
3413
+ init_cjs_shims();
3414
+ var import_node_crypto3 = require("crypto");
3415
+ var textEncoder = new TextEncoder();
3416
+ var textDecoder = new TextDecoder("utf-8", { fatal: true });
3417
+ function assertJSONValue(value, path3, seen) {
3418
+ if (value === null || typeof value === "string" || typeof value === "boolean") return;
3419
+ if (typeof value === "number") {
3420
+ if (!Number.isFinite(value)) throw new SerializationError(`${path3} contains a non-finite number`);
3421
+ return;
3422
+ }
3423
+ if (typeof value !== "object") {
3424
+ throw new SerializationError(`${path3} contains unsupported ${typeof value}`);
3425
+ }
3426
+ if (isFile(value)) {
3427
+ throw new SerializationError(`${path3} contains a nested File; File is only supported as a direct value`);
3428
+ }
3429
+ if (isHttpBody(value)) {
3430
+ throw new SerializationError(
3431
+ `${path3} contains a nested HttpBody; HttpBody is only supported as a direct value`
3432
+ );
3433
+ }
3434
+ if (seen.has(value)) throw new SerializationError(`${path3} contains a cycle`);
3435
+ if (Object.getPrototypeOf(value) !== Object.prototype && !Array.isArray(value)) {
3436
+ throw new SerializationError(`${path3} contains unsupported ${value.constructor?.name ?? "object"}`);
3437
+ }
3438
+ seen.add(value);
3439
+ if (Array.isArray(value)) {
3440
+ for (let index = 0; index < value.length; index += 1) {
3441
+ if (!Object.prototype.hasOwnProperty.call(value, index)) {
3442
+ throw new SerializationError(`${path3} contains a sparse array entry at index ${index}`);
3443
+ }
3444
+ assertJSONValue(value[index], `${path3}[${index}]`, seen);
3445
+ }
3446
+ } else {
3447
+ for (const [key, item] of Object.entries(value)) {
3448
+ assertJSONValue(item, `${path3}.${key}`, seen);
3449
+ }
3450
+ }
3451
+ seen.delete(value);
3452
+ }
3453
+ function serializeValue(value) {
3454
+ if (isFile(value)) {
3455
+ return { data: value.content, contentType: value.contentType, encoding: "raw" };
3456
+ }
3457
+ if (isHttpBody(value)) {
3458
+ return {
3459
+ data: value.content,
3460
+ contentType: value.contentType ?? "",
3461
+ encoding: "raw"
3462
+ };
3463
+ }
3464
+ try {
3465
+ assertJSONValue(value, "value", /* @__PURE__ */ new Set());
3466
+ return {
3467
+ data: textEncoder.encode(JSON.stringify(value)),
3468
+ contentType: "application/json; charset=UTF-8",
3469
+ encoding: "json"
3470
+ };
3471
+ } catch (error) {
3472
+ if (error instanceof SerializationError) throw error;
3473
+ throw new SerializationError("Failed to serialize JSON value", { cause: error });
3474
+ }
3475
+ }
3476
+ function deserializeJSON(data) {
3477
+ try {
3478
+ return JSON.parse(textDecoder.decode(data));
3479
+ } catch (error) {
3480
+ throw new DeserializationError("Failed to deserialize JSON value", { cause: error });
3481
+ }
3482
+ }
3483
+ function jsonRoundTrip(value) {
3484
+ const serialized = serializeValue(value);
3485
+ if (serialized.encoding !== "json") return value;
3486
+ return deserializeJSON(serialized.data);
3487
+ }
3488
+
3489
+ // src/applications/context.ts
3490
+ function validateRequestStateKey(key) {
3491
+ if (typeof key !== "string") {
3492
+ throw new SDKUsageError(`State key must be a string, got: ${String(key)}`);
3493
+ }
3494
+ }
3495
+ function serializeRequestStateValue(value) {
3496
+ const serialized = serializeValue(value);
3497
+ if (serialized.encoding !== "json") {
3498
+ throw new SDKUsageError("Request state values must be JSON values");
3499
+ }
3500
+ return serialized.data;
3501
+ }
3502
+ function validateCounterMetric(name, value) {
3503
+ if (typeof name !== "string") {
3504
+ throw new SDKUsageError(`Counter name must be a string, got: ${String(name)}`);
3505
+ }
3506
+ if (typeof value !== "number" || !Number.isInteger(value)) {
3507
+ throw new SDKUsageError(`Counter value must be an int, got: ${String(value)}`);
3508
+ }
3509
+ if (!Number.isSafeInteger(value)) {
3510
+ throw new SDKUsageError(`Counter value must be a safe int, got: ${String(value)}`);
3511
+ }
3512
+ }
3513
+ function validateTimerMetric(name, value) {
3514
+ if (typeof name !== "string") {
3515
+ throw new SDKUsageError(`Timer name must be a string, got: ${String(name)}`);
3516
+ }
3517
+ if (typeof value !== "number" || !Number.isFinite(value)) {
3518
+ throw new SDKUsageError(`Timer value must be a finite number, got: ${String(value)}`);
3519
+ }
3520
+ }
3521
+ function isPlainRecord(value) {
3522
+ if (value == null || typeof value !== "object" || Array.isArray(value)) return false;
3523
+ const prototype = Object.getPrototypeOf(value);
3524
+ return prototype === Object.prototype || prototype === null;
3525
+ }
3526
+ function validateProgressUpdate(current, total, options) {
3527
+ if (!Number.isFinite(current) || !Number.isFinite(total) || total < 0 || current < 0) {
3528
+ throw new SDKUsageError("Progress current and total must be non-negative finite numbers");
3529
+ }
3530
+ if (options != null && !isPlainRecord(options)) {
3531
+ throw new SDKUsageError("Progress options must be an object");
3532
+ }
3533
+ if (options?.message != null && typeof options.message !== "string") {
3534
+ throw new SDKUsageError("Progress message must be a string");
3535
+ }
3536
+ if (options?.attributes != null) {
3537
+ if (!isPlainRecord(options.attributes)) {
3538
+ throw new SDKUsageError("Progress attributes must be an object of string key/value pairs");
3539
+ }
3540
+ for (const key of Reflect.ownKeys(options.attributes)) {
3541
+ if (typeof key !== "string") {
3542
+ throw new SDKUsageError("Progress attributes must contain only string keys and values");
3543
+ }
3544
+ const value = options.attributes[key];
3545
+ if (typeof value !== "string") {
3546
+ throw new SDKUsageError("Progress attributes must contain only string keys and values");
3547
+ }
3548
+ }
3549
+ }
3550
+ }
3551
+ var REQUEST_CONTEXT_STORAGE_KEY = /* @__PURE__ */ Symbol.for(
3552
+ "tensorlake.applications.request-context-storage.v1"
3553
+ );
3554
+ function requestContextStorage() {
3555
+ const target = globalThis;
3556
+ target[REQUEST_CONTEXT_STORAGE_KEY] ??= new import_node_async_hooks2.AsyncLocalStorage();
3557
+ return target[REQUEST_CONTEXT_STORAGE_KEY];
3558
+ }
3559
+ var RequestContext = class {
3560
+ static get() {
3561
+ const context = requestContextStorage().getStore();
3562
+ if (context == null) {
3563
+ throw new SDKUsageError("RequestContext.get() can only be called from a running Tensorlake function");
3564
+ }
3565
+ return context;
3566
+ }
3567
+ };
3568
+ function runWithRequestContext(context, callback) {
3569
+ return requestContextStorage().run(context, callback);
3570
+ }
3571
+ async function waitWithAbortSignal(value, signal) {
3572
+ if (signal.aborted) throw signal.reason;
3573
+ let onAbort;
3574
+ try {
3575
+ return await Promise.race([
3576
+ value,
3577
+ new Promise((_resolve, reject) => {
3578
+ onAbort = () => reject(signal.reason);
3579
+ signal.addEventListener("abort", onAbort, { once: true });
3580
+ })
3581
+ ]);
3582
+ } finally {
3583
+ if (onAbort != null) signal.removeEventListener("abort", onAbort);
3584
+ }
3585
+ }
3586
+ var MemoryRequestContext = class {
3587
+ constructor(requestId, options = {}) {
3588
+ this.requestId = requestId;
3589
+ this.headers = new Headers(options.headers);
3590
+ this.signal = options.signal ?? new AbortController().signal;
3591
+ }
3592
+ headers;
3593
+ signal;
3594
+ values = /* @__PURE__ */ new Map();
3595
+ counters = /* @__PURE__ */ new Map();
3596
+ timers = /* @__PURE__ */ new Map();
3597
+ lastProgress;
3598
+ state = {
3599
+ set: async (key, value) => {
3600
+ validateRequestStateKey(key);
3601
+ this.values.set(key, serializeRequestStateValue(value).slice());
3602
+ },
3603
+ get: async (key, defaultValue) => {
3604
+ validateRequestStateKey(key);
3605
+ const value = this.values.get(key);
3606
+ return value == null ? defaultValue : deserializeJSON(value);
3607
+ }
3608
+ };
3609
+ metrics = {
3610
+ counter: async (name, value = 1) => {
3611
+ validateCounterMetric(name, value);
3612
+ this.counters.set(name, (this.counters.get(name) ?? 0) + value);
3613
+ },
3614
+ timer: async (name, value) => {
3615
+ validateTimerMetric(name, value);
3616
+ const values = this.timers.get(name) ?? [];
3617
+ values.push(value);
3618
+ this.timers.set(name, values);
3619
+ }
3620
+ };
3621
+ progress = {
3622
+ update: async (current, total, options) => {
3623
+ validateProgressUpdate(current, total, options);
3624
+ this.lastProgress = { current, total, options };
3625
+ }
3626
+ };
3627
+ };
3628
+
3629
+ // src/applications/local.ts
3630
+ init_cjs_shims();
3631
+ var import_node_crypto4 = require("crypto");
3632
+ var LocalRequest = class {
3633
+ constructor(id, value, cancelRequest) {
3634
+ this.id = id;
3635
+ this.value = value;
3636
+ this.cancelRequest = cancelRequest;
3637
+ }
3638
+ output() {
3639
+ return this.value;
3640
+ }
3641
+ cancel(reason) {
3642
+ this.cancelRequest(reason);
3643
+ }
3644
+ };
3645
+ function boundaryCopy(value) {
3646
+ if (isFile(value)) {
3647
+ return new File(new Uint8Array(value.content), value.contentType);
3648
+ }
3649
+ if (isHttpBody(value)) {
3650
+ return new HttpBody(new Uint8Array(value.content), value.contentType);
3651
+ }
3652
+ return jsonRoundTrip(value);
3653
+ }
3654
+ var LocalRuntime = class {
3655
+ requestContext;
3656
+ application;
3657
+ controller = new AbortController();
3658
+ constructor(application, requestId = `local-${(0, import_node_crypto4.randomUUID)()}`) {
3659
+ this.application = application;
3660
+ this.requestContext = new MemoryRequestContext(requestId, {
3661
+ signal: this.controller.signal
3662
+ });
3663
+ }
3664
+ cancel(reason = new FunctionError("Local request was cancelled")) {
3665
+ if (!this.controller.signal.aborted) this.controller.abort(reason);
3666
+ }
3667
+ invoke(definition, args) {
3668
+ return this.execute(definition, args);
3669
+ }
3670
+ async runFuture(future) {
3671
+ if (future.delaySeconds > 0) {
3672
+ let timer;
3673
+ try {
3674
+ await waitWithAbortSignal(
3675
+ new Promise((resolve) => {
3676
+ timer = setTimeout(resolve, future.delaySeconds * 1e3);
3677
+ }),
3678
+ this.requestContext.signal
3679
+ );
3680
+ } finally {
3681
+ if (timer != null) clearTimeout(timer);
3682
+ }
3683
+ }
3684
+ return this.execute(future.definition, future.args);
3685
+ }
3686
+ async reduce(definition, items, initial, hasInitial) {
3687
+ let reduceItems = items;
3688
+ let reduceInitial = initial;
3689
+ if (!hasInitial) {
3690
+ if (items.length === 0) {
3691
+ throw new SDKUsageError("reduce of empty iterable with no initial value");
3692
+ }
3693
+ [reduceInitial, ...reduceItems] = items;
3694
+ }
3695
+ let accumulator = boundaryCopy(reduceInitial);
3696
+ for (const item of reduceItems) {
3697
+ accumulator = await this.execute(definition, [accumulator, item]);
3698
+ }
3699
+ return accumulator;
3700
+ }
3701
+ async execute(definition, rawArgs) {
3702
+ const originalArgs = rawArgs.map(boundaryCopy);
3703
+ const maxRetries = definition.options.retries?.maxRetries ?? this.application.application?.retries.maxRetries ?? 0;
3704
+ let lastError;
3705
+ for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
3706
+ const args = originalArgs.map(boundaryCopy);
3707
+ try {
3708
+ const value = await runWithFunctionRuntime(
3709
+ this,
3710
+ () => runWithRequestContext(
3711
+ this.requestContext,
3712
+ () => waitWithAbortSignal(
3713
+ this.withTimeout(executeHandler(definition, args), definition.options.timeout),
3714
+ this.controller.signal
3715
+ )
3716
+ )
3717
+ );
3718
+ return boundaryCopy(value);
3719
+ } catch (error) {
3720
+ if (isRequestError(error)) throw error;
3721
+ if (this.controller.signal.aborted) throw this.controller.signal.reason;
3722
+ lastError = error;
3723
+ }
3724
+ }
3725
+ throw lastError instanceof Error ? new FunctionError(`${definition.name} failed: ${lastError.message}`, { cause: lastError }) : new FunctionError(`${definition.name} failed`);
3726
+ }
3727
+ async withTimeout(promise, timeoutSeconds) {
3728
+ let timer;
3729
+ try {
3730
+ return await Promise.race([
3731
+ promise,
3732
+ new Promise((_, reject) => {
3733
+ timer = setTimeout(
3734
+ () => reject(new TimeoutError()),
3735
+ timeoutSeconds * 1e3
3736
+ );
3737
+ })
3738
+ ]);
3739
+ } finally {
3740
+ if (timer != null) clearTimeout(timer);
3741
+ }
3742
+ }
3743
+ };
3744
+ async function runLocal(application, ...args) {
3745
+ if (application.definition.application == null) {
3746
+ throw new SDKUsageError(`${application.definition.name} is not a Tensorlake application`);
3747
+ }
3748
+ const runtime = new LocalRuntime(application.definition);
3749
+ const output = runtime.invoke(application.definition, args);
3750
+ return new LocalRequest(
3751
+ runtime.requestContext.requestId,
3752
+ output,
3753
+ (reason) => runtime.cancel(reason)
3754
+ );
3755
+ }
3756
+
3757
+ // src/applications/remote.ts
3758
+ init_cjs_shims();
3759
+
3760
+ // src/api-client.ts
3761
+ init_cjs_shims();
3762
+ init_cloud_client();
3763
+
3764
+ // src/filesystem.ts
3765
+ init_cjs_shims();
3766
+ var import_node_crypto5 = require("crypto");
3767
+
3768
+ // src/mount-cli.ts
3769
+ init_cjs_shims();
3770
+ var import_node_child_process = require("child_process");
3771
+ var import_node_fs2 = require("fs");
3772
+ var import_node_os2 = require("os");
3773
+ var import_node_path3 = require("path");
3774
+ var import_node_util2 = require("util");
3775
+
3776
+ // src/filesystem-models.ts
3777
+ init_cjs_shims();
3778
+ var GIT_MODE_DIR = 16384;
3779
+ var GIT_MODE_SYMLINK = 40960;
3780
+ function trimSlashes(path3) {
3781
+ let start = 0;
3782
+ let end = path3.length;
3783
+ while (start < end && path3.charCodeAt(start) === 47) start += 1;
3784
+ while (end > start && path3.charCodeAt(end - 1) === 47) end -= 1;
3785
+ return path3.slice(start, end);
3786
+ }
3787
+ function fileEntryFromWire(entry, dirPath) {
3788
+ const mode = entry.mode ?? 33188;
3789
+ const prefix = trimSlashes(dirPath);
3790
+ return {
3791
+ name: entry.name,
3792
+ path: prefix ? `${prefix}/${entry.name}` : entry.name,
3793
+ contentId: entry.oid ?? "",
3794
+ kind: mode === GIT_MODE_DIR ? "directory" : mode === GIT_MODE_SYMLINK ? "symlink" : "file",
3795
+ executable: mode === 33261,
3796
+ size: entry.size ?? null,
3797
+ isDir: mode === GIT_MODE_DIR,
3798
+ isSymlink: mode === GIT_MODE_SYMLINK
3799
+ };
3800
+ }
3801
+ function mountStatusFromRaw(raw, localPath) {
3802
+ const mounted = "mounted" in raw ? Boolean(raw.mounted) : "active" in raw ? Boolean(raw.active) : true;
3803
+ const path3 = String(raw.path || raw.mount_path || localPath || "");
3804
+ const filesystem = raw.filesystem || raw.file_system || raw.repository || null;
3805
+ return { path: path3, filesystem, mounted, raw };
3806
+ }
3807
+ var FilesystemError = class extends Error {
3808
+ constructor(message) {
3809
+ super(message);
3810
+ this.name = "FilesystemError";
3811
+ }
3812
+ };
3813
+ var FilesystemNotFoundError = class extends FilesystemError {
3814
+ filesystemName;
3815
+ constructor(name) {
3816
+ super(`Filesystem not found: ${name}`);
3817
+ this.name = "FilesystemNotFoundError";
3818
+ this.filesystemName = name;
3819
+ }
3820
+ };
3821
+ var FileNotFoundInFilesystemError = class extends FilesystemError {
3822
+ filesystem;
3823
+ path;
3824
+ constructor(filesystem, path3) {
3825
+ super(`File not found in filesystem ${filesystem}: ${path3}`);
3826
+ this.name = "FileNotFoundInFilesystemError";
3827
+ this.filesystem = filesystem;
3828
+ this.path = path3;
3829
+ }
3830
+ };
3831
+ var FilesystemAPIError = class extends FilesystemError {
3832
+ statusCode;
3833
+ constructor(statusCode, message) {
3834
+ super(`API error (status ${statusCode}): ${message}`);
3835
+ this.name = "FilesystemAPIError";
3836
+ this.statusCode = statusCode;
3837
+ }
3838
+ };
3839
+ var MountError = class extends FilesystemError {
3840
+ constructor(message) {
3841
+ super(message);
3842
+ this.name = "MountError";
3843
+ }
3844
+ };
3845
+ var ReadOnlyMountNotSupportedError = class extends MountError {
3846
+ constructor() {
3847
+ super(
3848
+ "read-only local mounts are not supported: `tl fs mount` has no --ro mode. Mount the filesystem into a sandbox read-only instead (readOnly: true / `tl sbx create -f NAME:PATH:ro`), or use `tl git mount --ro` for repositories."
3849
+ );
3850
+ this.name = "ReadOnlyMountNotSupportedError";
3851
+ }
3852
+ };
3853
+ var CliNotFoundError = class extends MountError {
3854
+ constructor(detail, command = "fs") {
3855
+ super(
3856
+ `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`
3857
+ );
3858
+ this.name = "CliNotFoundError";
3859
+ }
3860
+ };
3861
+
3862
+ // src/mount-cli.ts
3863
+ var execFileAsync = (0, import_node_util2.promisify)(import_node_child_process.execFile);
3864
+ var MountCli = class {
3865
+ constructor(command, envOverrides) {
3866
+ this.command = command;
3867
+ this.envOverrides = envOverrides;
3868
+ }
3869
+ binary = null;
3870
+ async findCli() {
3871
+ const candidates = [];
3872
+ if (process.env.TENSORLAKE_CLI) candidates.push(process.env.TENSORLAKE_CLI);
3873
+ candidates.push("tl");
3874
+ const installed = (0, import_node_path3.join)((0, import_node_os2.homedir)(), ".tensorlake", "bin", "tl");
3875
+ try {
3876
+ (0, import_node_fs2.accessSync)(installed, import_node_fs2.constants.F_OK);
3877
+ candidates.push(installed);
3878
+ } catch {
3879
+ }
3880
+ const support = this.command === "git" ? "git mount" : "fs";
3881
+ const probe = this.command === "git" ? ["git", "mount", "--help"] : ["fs", "--help"];
3882
+ let unsupported = null;
3883
+ for (const candidate of candidates) {
3884
+ try {
3885
+ await execFileAsync(candidate, probe, { timeout: 15e3 });
3886
+ return candidate;
3887
+ } catch (error) {
3888
+ if (error.code !== "ENOENT") unsupported = candidate;
3889
+ }
3890
+ }
3891
+ throw new CliNotFoundError(
3892
+ unsupported ? `\`tl\` at ${unsupported} does not support \`tl ${support}\` (upgrade required)` : "`tl` was not found on PATH",
3893
+ support
3894
+ );
3895
+ }
3896
+ async run(args, timeoutMs = 3e5) {
3897
+ if (this.binary === null) this.binary = await this.findCli();
3898
+ try {
3899
+ const { stdout } = await execFileAsync(this.binary, [this.command, ...args], {
3900
+ timeout: timeoutMs,
3901
+ env: { ...process.env, ...this.envOverrides },
3902
+ maxBuffer: 16 * 1024 * 1024
3903
+ });
3904
+ return stdout;
3905
+ } catch (error) {
3906
+ const failure = error;
3907
+ if (failure.killed) {
3908
+ throw new MountError(`\`tl ${this.command} ${args[0]}\` timed out after ${timeoutMs}ms`);
3909
+ }
3910
+ const detail = (failure.stderr || failure.stdout || String(error)).trim();
3911
+ throw new MountError(`\`tl ${this.command} ${args.join(" ")}\` failed: ${detail}`);
3912
+ }
3913
+ }
3914
+ };
3915
+
3916
+ // src/filesystem.ts
3917
+ init_defaults();
3918
+ init_native_sandbox();
3919
+ init_sandbox_image();
3920
+ var FILESYSTEM_REPO_KIND = "filesystem";
3921
+ function translateNativeError2(error, notFound) {
3922
+ const message = error instanceof Error ? error.message : String(error);
3923
+ let payload;
3924
+ try {
3925
+ payload = JSON.parse(message);
3926
+ } catch {
3927
+ return error instanceof Error ? error : new FilesystemError(message);
3928
+ }
3929
+ if (!payload || typeof payload.category !== "string") {
3930
+ return error instanceof Error ? error : new FilesystemError(message);
3931
+ }
3932
+ const detail = typeof payload.message === "string" ? payload.message : message;
3933
+ if (payload.category === "connection") {
3934
+ return new FilesystemError(detail);
3935
+ }
3936
+ if (payload.status === 404 && notFound !== void 0) {
3937
+ return notFound;
3938
+ }
3939
+ if (typeof payload.status === "number") {
3940
+ return new FilesystemAPIError(payload.status, detail);
3941
+ }
3942
+ return new FilesystemError(detail);
3943
+ }
3944
+ async function callNative2(fn, notFound) {
3945
+ try {
3946
+ return await fn();
3947
+ } catch (error) {
3948
+ throw translateNativeError2(error, notFound);
3949
+ }
3950
+ }
3951
+ var FsCli = class extends MountCli {
3952
+ constructor(envOverrides) {
3953
+ super("fs", envOverrides);
3954
+ }
3955
+ // Flags always precede a `--` end-of-options separator so caller-supplied
3956
+ // names/paths can never be parsed as CLI flags (e.g. a path literally
3957
+ // named "--discard" must stay a path, not become the destructive flag).
3958
+ async mount(filesystem, localPath, readonly) {
3959
+ if (readonly) {
3960
+ throw new ReadOnlyMountNotSupportedError();
3961
+ }
3962
+ await this.run(["mount", "--", filesystem, localPath]);
3963
+ }
3964
+ async unmount(localPath, discard) {
3965
+ const args = ["unmount"];
3966
+ if (discard) args.push("--discard");
3967
+ args.push("--", localPath);
3968
+ await this.run(args);
3969
+ }
3970
+ async snapshot(localPath, message) {
3971
+ const args = ["snapshot"];
3972
+ if (message) args.push(`--message=${message}`);
3973
+ args.push("--", localPath);
3974
+ await this.run(args);
3975
+ }
3976
+ async status(localPath) {
3977
+ const args = ["status", "--json"];
3978
+ if (localPath) args.push("--", localPath);
3979
+ const output = await this.run(args, 6e4);
3980
+ try {
3981
+ const payload = JSON.parse(output);
3982
+ return typeof payload === "object" && payload !== null ? payload : { status: payload };
3983
+ } catch {
3984
+ throw new MountError(
3985
+ `\`tl fs status --json\` returned invalid JSON: ${output.slice(0, 200)}`
3986
+ );
3987
+ }
3988
+ }
3989
+ };
3990
+ var FilesystemClient = class {
3991
+ native;
3992
+ cli;
3993
+ /**
3994
+ * The SDK authenticates with `apiKey` or `TENSORLAKE_API_KEY`. Project scope is selected by
3995
+ * ingress from the API key; no organization/project lookup is performed. Organization/project
3996
+ * options are retained only for the separately installed `tl` CLI used by local mounts.
3997
+ */
3998
+ constructor(options = {}) {
3999
+ const context = buildContextFromEnv();
4000
+ const token = options.apiKey ?? context.apiKey;
4001
+ if (!token) {
4002
+ if (context.personalAccessToken) {
4003
+ throw new FilesystemError(
4004
+ "Filesystem SDKs require TENSORLAKE_API_KEY. Personal access tokens are CLI-only."
4005
+ );
4006
+ }
4007
+ throw new FilesystemError(
4008
+ "Missing TENSORLAKE_API_KEY credentials."
4009
+ );
4010
+ }
4011
+ const organizationId = options.organizationId ?? context.organizationId;
4012
+ const projectId = options.projectId ?? context.projectId;
4013
+ if (options.nativeClient) {
4014
+ this.native = options.nativeClient;
4015
+ } else {
4016
+ const binding = loadNativeSandboxBinding();
4017
+ if (typeof binding.NativeRepositoryClient !== "function") {
4018
+ throw new FilesystemError(
4019
+ "native binding does not export the repository client; rebuild with 'npm run build:native'"
4020
+ );
4021
+ }
4022
+ this.native = new binding.NativeRepositoryClient(
4023
+ options.apiUrl ?? context.apiUrl,
4024
+ token,
4025
+ null,
4026
+ null,
4027
+ `tensorlake-typescript-sdk/${SDK_VERSION}`,
4028
+ null
4029
+ );
4030
+ }
4031
+ const envOverrides = {
4032
+ TENSORLAKE_API_KEY: token,
4033
+ // The CLI must target the same deployment the data plane does, or a
4034
+ // mount could resolve a same-named filesystem in the wrong environment.
4035
+ TENSORLAKE_API_URL: options.apiUrl ?? context.apiUrl
4036
+ };
4037
+ if (organizationId) envOverrides.TENSORLAKE_ORGANIZATION_ID = organizationId;
4038
+ if (projectId) envOverrides.TENSORLAKE_PROJECT_ID = projectId;
4039
+ this.cli = new FsCli(envOverrides);
4040
+ }
4041
+ // -- lifecycle --------------------------------------------------------------
4042
+ /** Create a filesystem; region fixes its storage placement. Forks inherit placement. */
4043
+ async create(name, options = {}) {
4044
+ if (typeof name !== "string") {
4045
+ throw new TypeError("name must be a string");
4046
+ }
4047
+ if (name.length === 0) {
4048
+ throw new FilesystemError("filesystem name must not be empty");
4049
+ }
4050
+ const { region } = options;
4051
+ if (region !== void 0 && (typeof region !== "string" || region.length === 0 || region.trim() !== region)) {
4052
+ throw new FilesystemError(
4053
+ "region must be a nonempty string without surrounding whitespace"
4054
+ );
4055
+ }
4056
+ const raw = await callNative2(() => region === void 0 ? this.native.createFilesystem(name) : this.native.createFilesystem(name, region));
4057
+ const created = JSON.parse(raw);
4058
+ return new Filesystem(
4059
+ this,
4060
+ this.native,
4061
+ this.cli,
4062
+ name,
4063
+ created.default_branch || "main"
4064
+ );
4065
+ }
4066
+ /**
4067
+ * Fork a filesystem at its live head or an explicit retained snapshot.
4068
+ * The server shares immutable content and publishes only metadata.
4069
+ */
4070
+ async fork(name, baseFilesystem, snapshot) {
4071
+ if (!name || !baseFilesystem) {
4072
+ throw new FilesystemError(
4073
+ "fork and base filesystem names must not be empty"
4074
+ );
4075
+ }
4076
+ await callNative2(
4077
+ () => this.native.forkFilesystem(
4078
+ name,
4079
+ baseFilesystem,
4080
+ snapshot ?? null
4081
+ ),
4082
+ new FilesystemNotFoundError(baseFilesystem)
4083
+ );
4084
+ return new Filesystem(this, this.native, this.cli, name, "main");
4085
+ }
4086
+ /** Return a handle to an existing filesystem (verifies it exists). */
4087
+ async get(name) {
4088
+ const traced = await callNative2(
4089
+ () => this.native.filesystemMeta(name),
4090
+ new FilesystemNotFoundError(name)
4091
+ );
4092
+ const meta = JSON.parse(traced.json);
4093
+ if ((meta.kind ?? FILESYSTEM_REPO_KIND) !== FILESYSTEM_REPO_KIND) {
4094
+ throw new FilesystemNotFoundError(name);
4095
+ }
4096
+ return new Filesystem(
4097
+ this,
4098
+ this.native,
4099
+ this.cli,
4100
+ name,
4101
+ meta.default_branch || "main"
4102
+ );
4103
+ }
4104
+ /** List all filesystems in the project. */
4105
+ async list() {
4106
+ const traced = await callNative2(() => this.native.listFilesystems());
4107
+ const page = JSON.parse(traced.json);
4108
+ return (page.repos ?? []).map((repo) => ({
4109
+ name: String(repo.name ?? ""),
4110
+ fullName: String(repo.full_name ?? ""),
4111
+ status: String(repo.status ?? ""),
4112
+ kind: String(repo.kind ?? FILESYSTEM_REPO_KIND)
4113
+ }));
4114
+ }
4115
+ /** Permanently delete a filesystem and all its snapshots. */
4116
+ async delete(name) {
4117
+ await callNative2(
4118
+ () => this.native.deleteFilesystem(name),
4119
+ new FilesystemNotFoundError(name)
4120
+ );
4121
+ }
4122
+ // -- local mounts -------------------------------------------------------------
4123
+ /**
4124
+ * Mount a filesystem to a local path (requires the `tl` CLI).
4125
+ *
4126
+ * `readonly: true` is not supported for local mounts and throws
4127
+ * {@link ReadOnlyMountNotSupportedError}; use a sandbox read-only mount
4128
+ * (`readOnly: true`) or `tl git mount --ro` instead.
4129
+ */
4130
+ async mount(name, localPath, readonly = false) {
4131
+ await this.cli.mount(name, localPath, readonly);
4132
+ return new FilesystemMount(this, this.cli, name, localPath, readonly);
4133
+ }
4134
+ /**
4135
+ * Unmount a locally mounted filesystem.
4136
+ *
4137
+ * `discard: true` drops local changes that were not yet uploaded.
4138
+ */
4139
+ async unmount(localPath, discard = false) {
4140
+ await this.cli.unmount(localPath, discard);
4141
+ }
4142
+ /** Status of a local mount (defaults to the mount containing CWD). */
4143
+ async mountStatus(localPath) {
4144
+ return mountStatusFromRaw(await this.cli.status(localPath), localPath);
4145
+ }
4146
+ };
4147
+ function toBuffer(data) {
4148
+ return typeof data === "string" ? Buffer.from(data, "utf-8") : Buffer.from(data);
4149
+ }
4150
+ var Filesystem = class {
4151
+ client;
4152
+ native;
4153
+ cli;
4154
+ name;
4155
+ defaultBranch;
4156
+ /** @internal — obtain instances via `FilesystemClient.create()` / `.get()`. */
4157
+ constructor(client, native, cli, name, defaultBranch = null) {
4158
+ this.client = client;
4159
+ this.native = native;
4160
+ this.cli = cli;
4161
+ this.name = name;
4162
+ this.defaultBranch = defaultBranch;
4163
+ }
4164
+ /**
4165
+ * The filesystem's default branch — the target of every write and the
4166
+ * default version of every read, so writes and `status()` can never
4167
+ * silently disagree on a non-"main" filesystem.
4168
+ */
4169
+ async branch() {
4170
+ if (!this.defaultBranch) {
4171
+ const traced = await callNative2(
4172
+ () => this.native.filesystemMeta(this.name),
4173
+ new FilesystemNotFoundError(this.name)
4174
+ );
4175
+ const meta = JSON.parse(traced.json);
4176
+ this.defaultBranch = meta.default_branch || "main";
4177
+ }
4178
+ return this.defaultBranch;
4179
+ }
4180
+ // -- writes -------------------------------------------------------------------
4181
+ /** Write one file. Returns the snapshot (version) the write produced. */
4182
+ async writeFile(path3, data, message) {
4183
+ return await this.writeFiles(/* @__PURE__ */ new Map([[path3, data]]), message);
4184
+ }
4185
+ /** Write several files (and/or delete paths) in one atomic snapshot. */
4186
+ async writeFiles(files, message, deletes = []) {
4187
+ const entries = files instanceof Map ? [...files.entries()] : Object.entries(files);
4188
+ if (entries.length === 0 && deletes.length === 0) {
4189
+ throw new FilesystemError("nothing to write: no files or deletions given");
4190
+ }
4191
+ const writes = entries.map(([path3, data]) => ({
4192
+ path: path3,
4193
+ content: toBuffer(data)
4194
+ }));
4195
+ const resolvedMessage = message || `write ${writes.length} file(s) via SDK`;
4196
+ return await this.publishChanges(
4197
+ writes,
4198
+ deletes,
4199
+ [],
4200
+ [],
4201
+ resolvedMessage
4202
+ );
4203
+ }
4204
+ /**
4205
+ * Stream one local file directly to object storage in bounded parts.
4206
+ * This is the memory-bounded API for multi-GiB files.
4207
+ */
4208
+ async writeFileFromPath(path3, localPath, message) {
4209
+ return await this.writeFilesFromPaths(
4210
+ /* @__PURE__ */ new Map([[path3, localPath]]),
4211
+ message
4212
+ );
4213
+ }
4214
+ /**
4215
+ * Atomically publish local files without loading their complete payloads
4216
+ * into JavaScript or Rust memory.
4217
+ */
4218
+ async writeFilesFromPaths(files, message) {
4219
+ const entries = files instanceof Map ? [...files.entries()] : Object.entries(files);
4220
+ if (entries.length === 0) {
4221
+ throw new FilesystemError("nothing to write: no local files given");
4222
+ }
4223
+ const writes = entries.map(([path3, localPath]) => ({ path: path3, localPath }));
4224
+ const resolvedMessage = message || `write ${writes.length} local file(s) via SDK`;
4225
+ const branch = await this.branch();
4226
+ const traced = await callNative2(
4227
+ () => this.native.pushFilesystemPaths(
4228
+ this.name,
4229
+ writes,
4230
+ resolvedMessage,
4231
+ branch,
4232
+ (0, import_node_crypto5.randomBytes)(16).toString("hex")
4233
+ ),
4234
+ new FilesystemNotFoundError(this.name)
4235
+ );
4236
+ const report = JSON.parse(traced.json);
4237
+ const versionId = String(report.version_id ?? "");
4238
+ const previousVersionId = report.previous_version_id == null ? null : String(report.previous_version_id);
4239
+ return {
4240
+ versionId,
4241
+ previousVersionId,
4242
+ created: previousVersionId !== versionId,
4243
+ message: resolvedMessage
4244
+ };
4245
+ }
4246
+ /**
4247
+ * Move a file or directory without downloading or re-uploading its bytes.
4248
+ * The source removal and destination creation publish as one atomic snapshot.
4249
+ */
4250
+ async moveFile(from, to, message) {
4251
+ return await this.publishChanges(
4252
+ [],
4253
+ [],
4254
+ [{ from, to }],
4255
+ [],
4256
+ message || `move ${from} to ${to} via SDK`
4257
+ );
4258
+ }
4259
+ /**
4260
+ * Copy a file or directory by reusing immutable content references. No
4261
+ * payload bytes traverse the client, API server, or object store.
4262
+ */
4263
+ async copyFile(from, to, message) {
4264
+ return await this.publishChanges(
4265
+ [],
4266
+ [],
4267
+ [],
4268
+ [{ from, to }],
4269
+ message || `copy ${from} to ${to} via SDK`
4270
+ );
4271
+ }
4272
+ async publishChanges(writes, deletes, moves, copies, message) {
4273
+ const branch = await this.branch();
4274
+ const traced = await callNative2(
4275
+ () => this.native.pushFilesystemFiles(
4276
+ this.name,
4277
+ writes,
4278
+ deletes,
4279
+ moves,
4280
+ copies,
4281
+ message,
4282
+ branch,
4283
+ // One key per logical write: a retried submit reattaches to the
4284
+ // same durable commit job instead of double-committing.
4285
+ (0, import_node_crypto5.randomBytes)(16).toString("hex")
4286
+ ),
4287
+ new FilesystemNotFoundError(this.name)
4288
+ );
4289
+ const report = JSON.parse(traced.json);
4290
+ const versionId = String(report.version_id ?? "");
4291
+ const previousVersionId = report.previous_version_id == null ? null : String(report.previous_version_id);
4292
+ return {
4293
+ versionId,
4294
+ previousVersionId,
4295
+ created: previousVersionId !== versionId,
4296
+ message
4297
+ };
4298
+ }
4299
+ /** Delete one file. Returns the durable version the deletion produced. */
4300
+ async deleteFile(path3, message) {
4301
+ return await this.writeFiles(
4302
+ /* @__PURE__ */ new Map(),
4303
+ message || `delete ${path3} via SDK`,
4304
+ [path3]
4305
+ );
4306
+ }
4307
+ /**
4308
+ * Return the filesystem's current version as a snapshot.
4309
+ *
4310
+ * Writes publish durable live versions. This retains the current head
4311
+ * permanently in one metadata-only server operation without changing or
4312
+ * copying any content.
4313
+ */
4314
+ async snapshot(message = "snapshot via SDK") {
4315
+ const resolvedMessage = message || "snapshot via SDK";
4316
+ const traced = await callNative2(
4317
+ () => this.native.retainFilesystemSnapshot(
4318
+ this.name,
4319
+ resolvedMessage,
4320
+ (0, import_node_crypto5.randomBytes)(16).toString("hex")
4321
+ ),
4322
+ new FilesystemNotFoundError(this.name)
4323
+ );
4324
+ const retained = JSON.parse(traced.json);
4325
+ return {
4326
+ id: String(retained.snapshot_id ?? ""),
4327
+ message: retained.message || resolvedMessage
4328
+ };
4329
+ }
4330
+ /** List explicitly retained snapshots without reading filesystem contents. */
4331
+ async listSnapshots() {
4332
+ const traced = await callNative2(
4333
+ () => this.native.listFilesystemSnapshots(this.name),
4334
+ new FilesystemNotFoundError(this.name)
4335
+ );
4336
+ const payload = JSON.parse(traced.json);
4337
+ return (payload.snapshots ?? []).map((snapshot) => ({
4338
+ id: String(snapshot.snapshot_id ?? ""),
4339
+ createdAt: new Date(Number(snapshot.created_at_ms ?? 0)),
4340
+ message: String(snapshot.message ?? "")
4341
+ }));
4342
+ }
4343
+ /** Delete one permanent retention point; shared/head-reachable bytes remain. */
4344
+ async deleteSnapshot(snapshot) {
4345
+ await callNative2(
4346
+ () => this.native.deleteFilesystemSnapshot(this.name, snapshot),
4347
+ new FilesystemNotFoundError(this.name)
4348
+ );
4349
+ }
4350
+ // -- reads --------------------------------------------------------------------
4351
+ /**
4352
+ * Read a file's bytes at `version` (the current `main` head or a retained
4353
+ * snapshot id; defaults to the filesystem's current head).
4354
+ */
4355
+ async readFile(path3, version) {
4356
+ return (await this.readFileWithMetadata(path3, { version })).data;
4357
+ }
4358
+ /**
4359
+ * Read bytes and immutable metadata in one request. A range is executed by
4360
+ * Artifact Storage, so callers never download the unrequested remainder.
4361
+ */
4362
+ async readFileWithMetadata(path3, options = {}) {
4363
+ if (trimSlashes(path3) === "") {
4364
+ throw new FilesystemError("file path must not be empty");
4365
+ }
4366
+ const range = options.range;
4367
+ if (range !== void 0 && (!Number.isSafeInteger(range.offset) || range.offset < 0 || !Number.isSafeInteger(range.length) || range.length <= 0)) {
4368
+ throw new FilesystemError(
4369
+ "range requires a non-negative integer offset and positive integer length"
4370
+ );
4371
+ }
4372
+ const resolvedVersion = options.version || await this.branch();
4373
+ const traced = await callNative2(
4374
+ () => this.native.readFilesystemFile(
4375
+ this.name,
4376
+ path3,
4377
+ resolvedVersion,
4378
+ range?.offset,
4379
+ range?.length
4380
+ ),
4381
+ new FileNotFoundInFilesystemError(this.name, path3)
4382
+ );
4383
+ const fullSize = traced.fullSize;
4384
+ if (!traced.contentId || fullSize === void 0 || !Number.isSafeInteger(fullSize) || fullSize < 0 || traced.data.byteLength > fullSize) {
4385
+ throw new FilesystemError(
4386
+ "filesystem read response omitted content identity or total size"
4387
+ );
4388
+ }
4389
+ return {
4390
+ data: new Uint8Array(traced.data),
4391
+ contentId: traced.contentId,
4392
+ size: fullSize
4393
+ };
4394
+ }
4395
+ /** Read a file as UTF-8 text at `version`. Throws on non-UTF-8 content. */
4396
+ async readText(path3, version) {
4397
+ return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(
4398
+ await this.readFile(path3, version)
4399
+ );
4400
+ }
4401
+ /** List one directory (non-recursive) at `version`. */
4402
+ async listFiles(dirPath = "", version) {
4403
+ const resolvedVersion = version || await this.branch();
4404
+ const traced = await callNative2(
4405
+ () => this.native.listFilesystemTree(this.name, dirPath, resolvedVersion),
4406
+ new FileNotFoundInFilesystemError(this.name, dirPath || "/")
4407
+ );
4408
+ const page = JSON.parse(traced.json);
4409
+ return (page.entries ?? []).map((entry) => fileEntryFromWire(entry, dirPath));
4410
+ }
4411
+ // -- status -------------------------------------------------------------------
4412
+ /** Remote status: identity plus the current native version. */
4413
+ async status() {
4414
+ const metaTraced = await callNative2(
4415
+ () => this.native.filesystemMeta(this.name),
4416
+ new FilesystemNotFoundError(this.name)
4417
+ );
4418
+ const meta = JSON.parse(metaTraced.json);
4419
+ const defaultBranch = String(meta.default_branch || "main");
4420
+ this.defaultBranch = defaultBranch;
4421
+ let versionId = null;
4422
+ let generation = null;
4423
+ try {
4424
+ const refTraced = await callNative2(
4425
+ () => this.native.filesystemRefStatus(this.name, defaultBranch)
4426
+ );
4427
+ const ref = JSON.parse(refTraced.json);
4428
+ versionId = ref.resolved_commit || ref.oid || null;
4429
+ generation = typeof ref.generation === "number" ? ref.generation : null;
4430
+ } catch (error) {
4431
+ if (!(error instanceof FilesystemAPIError) || error.statusCode !== 404) {
4432
+ throw error;
4433
+ }
4434
+ }
4435
+ return {
4436
+ name: this.name,
4437
+ status: String(meta.status ?? ""),
4438
+ versionId,
4439
+ generation
4440
+ };
4441
+ }
4442
+ // -- mounts -------------------------------------------------------------------
4443
+ /**
4444
+ * Mount this filesystem to a local path (requires the `tl` CLI).
4445
+ *
4446
+ * `readonly: true` is not supported for local mounts and throws
4447
+ * {@link ReadOnlyMountNotSupportedError}; use a sandbox read-only mount
4448
+ * (`readOnly: true`) or `tl git mount --ro` instead.
4449
+ */
4450
+ async mount(localPath, readonly = false) {
4451
+ return await this.client.mount(this.name, localPath, readonly);
4452
+ }
4453
+ };
4454
+ var FilesystemMount = class {
4455
+ client;
4456
+ cli;
4457
+ filesystem;
4458
+ path;
4459
+ readonly;
4460
+ /** @internal — obtain instances via `FilesystemClient.mount()`. */
4461
+ constructor(client, cli, filesystem, path3, readonly) {
4462
+ this.client = client;
4463
+ this.cli = cli;
4464
+ this.filesystem = filesystem;
4465
+ this.path = path3;
4466
+ this.readonly = readonly;
4467
+ }
4468
+ /** Flush pending local changes into a durable snapshot. */
4469
+ async snapshot(message) {
4470
+ await this.cli.snapshot(this.path, message);
4471
+ }
4472
+ /** Local mount status as reported by the mount daemon. */
4473
+ async status() {
4474
+ return await this.client.mountStatus(this.path);
4475
+ }
4476
+ /** Unmount; `discard: true` drops changes not yet uploaded. */
4477
+ async unmount(discard = false) {
4478
+ await this.client.unmount(this.path, discard);
4479
+ }
4480
+ };
4481
+
4482
+ // src/api-client.ts
4483
+ init_errors();
4484
+ var APIClient = class {
4485
+ cloudClient;
4486
+ filesystemOptions;
4487
+ constructor(options) {
4488
+ this.cloudClient = new CloudClient(options);
4489
+ this.filesystemOptions = {
4490
+ apiKey: options?.apiKey,
4491
+ apiUrl: options?.apiUrl,
4492
+ organizationId: options?.organizationId,
4493
+ projectId: options?.projectId
4494
+ };
4495
+ }
4496
+ close() {
4497
+ this.cloudClient.close();
4498
+ }
4499
+ async upsertApplication(manifest, codeZip, upgradeRunningRequests = false) {
4500
+ await this.cloudClient.upsertApplication(
4501
+ manifest,
4502
+ codeZip,
4503
+ upgradeRunningRequests
4504
+ );
4505
+ }
4506
+ async deleteApplication(applicationName) {
4507
+ await this.cloudClient.deleteApplication(applicationName);
4508
+ }
4509
+ async deleteSandboxImage(imageName) {
4510
+ await this.cloudClient.deleteSandboxImage(imageName);
4511
+ }
4512
+ async createFileSystem(name, description, options) {
4513
+ const filesystem = await new FilesystemClient(this.filesystemOptions).create(
4514
+ name,
4515
+ { region: options?.region }
4516
+ );
4517
+ return {
4518
+ id: filesystem.name,
4519
+ name: filesystem.name,
4520
+ description,
4521
+ status: "ready"
4522
+ };
4523
+ }
4524
+ async listFileSystems(_options) {
4525
+ const filesystems = await new FilesystemClient(this.filesystemOptions).list();
4526
+ return filesystems.map((filesystem) => ({
4527
+ id: filesystem.name,
4528
+ name: filesystem.name,
4529
+ status: filesystem.status
4530
+ }));
4531
+ }
4532
+ async deleteFileSystem(fileSystemId, _options) {
4533
+ await new FilesystemClient(this.filesystemOptions).delete(fileSystemId);
4534
+ }
4535
+ async applications() {
4536
+ return this.cloudClient.applications();
4537
+ }
4538
+ async application(applicationName) {
4539
+ return this.cloudClient.applicationManifest(applicationName);
4540
+ }
4541
+ async runRequest(applicationName, inputs) {
4542
+ return this.cloudClient.runRequest(applicationName, inputs);
4543
+ }
4544
+ async waitOnRequestCompletion(applicationName, requestId) {
4545
+ await this.cloudClient.waitOnRequestCompletion(applicationName, requestId);
4546
+ }
4547
+ async requestOutput(applicationName, requestId) {
4548
+ const metadata = await this.cloudClient.requestMetadata(
4549
+ applicationName,
4550
+ requestId
4551
+ );
4552
+ if (metadata.outcome == null) {
4553
+ throw new RequestNotFinishedError();
4554
+ }
4555
+ if (typeof metadata.outcome === "object") {
4556
+ if (metadata.requestError?.message) {
4557
+ throw new RequestExecutionError(
4558
+ metadata.requestError.message,
4559
+ metadata.requestError.functionName
4560
+ );
4561
+ }
4562
+ const failure = typeof metadata.outcome.failure === "string" ? metadata.outcome.failure : JSON.stringify(metadata.outcome);
4563
+ throw new RequestFailedError(failure);
4564
+ }
4565
+ return this.cloudClient.requestOutput(applicationName, requestId);
4566
+ }
4567
+ };
4568
+
4569
+ // src/applications/remote.ts
4570
+ init_errors();
4571
+ var CLOUD_CLIENT_OPTION_KEYS = /* @__PURE__ */ new Set([
4572
+ "apiUrl",
4573
+ "apiKey",
4574
+ "organizationId",
4575
+ "projectId",
4576
+ "namespace",
4577
+ "maxRetries",
4578
+ "retryBackoffMs"
4579
+ ]);
4580
+ var REMOTE_OPTIONS_BRAND = /* @__PURE__ */ Symbol.for(
4581
+ "tensorlake.applications.remote-options.v1"
4582
+ );
4583
+ function isCloudClientOptions(value) {
4584
+ if (typeof value !== "object" || value == null || Array.isArray(value)) return false;
4585
+ const entries = Object.entries(value);
4586
+ return entries.every(([key, option]) => {
4587
+ if (!CLOUD_CLIENT_OPTION_KEYS.has(key)) return false;
4588
+ if (option === void 0) return true;
4589
+ if (key === "maxRetries" || key === "retryBackoffMs") {
4590
+ return typeof option === "number";
4591
+ }
4592
+ return typeof option === "string";
4593
+ });
4594
+ }
4595
+ function isRemoteOptions(value) {
4596
+ if (typeof value !== "object" || value == null) return false;
4597
+ const candidate = value;
4598
+ return candidate[REMOTE_OPTIONS_BRAND] === true && isCloudClientOptions(candidate.clientOptions);
4599
+ }
4600
+ function remoteOptions(options = {}) {
4601
+ if (!isCloudClientOptions(options)) {
4602
+ throw new SDKUsageError("remoteOptions requires valid CloudClientOptions");
4603
+ }
4604
+ return Object.freeze({
4605
+ [REMOTE_OPTIONS_BRAND]: true,
4606
+ clientOptions: Object.freeze({ ...options })
4607
+ });
4608
+ }
4609
+ var RemoteRequest = class {
4610
+ constructor(id, applicationName, client, outputIsFile) {
4611
+ this.id = id;
4612
+ this.applicationName = applicationName;
4613
+ this.client = client;
4614
+ this.outputIsFile = outputIsFile;
4615
+ }
4616
+ async output() {
4617
+ let output;
4618
+ try {
4619
+ await this.client.waitOnRequestCompletion(this.applicationName, this.id);
4620
+ output = await this.client.requestOutput(this.applicationName, this.id);
4621
+ } catch (error) {
4622
+ if (error instanceof RequestExecutionError) {
4623
+ throw new RequestError(error.message, { cause: error });
4624
+ }
4625
+ if (error instanceof RequestFailedError) {
4626
+ throw new FunctionError(error.message, { cause: error });
4627
+ }
4628
+ throw error;
4629
+ }
4630
+ if (this.outputIsFile === true) {
4631
+ return new File(output.serializedValue, output.contentType);
4632
+ }
4633
+ if (this.outputIsFile === false || output.contentType.toLowerCase().startsWith("application/json")) {
4634
+ return deserializeJSON(output.serializedValue);
4635
+ }
4636
+ return new File(output.serializedValue, output.contentType);
4637
+ }
4638
+ };
4639
+ async function runRemote(application, ...argsAndOptions) {
4640
+ const definition = typeof application === "string" ? void 0 : application.definition;
4641
+ if (definition != null && definition.application == null) {
4642
+ throw new SDKUsageError(`${definition.name} is not a Tensorlake application`);
4643
+ }
4644
+ const applicationName = typeof application === "string" ? application : definition.name;
4645
+ let options;
4646
+ const args = [...argsAndOptions];
4647
+ const candidate = args.at(-1);
4648
+ if (typeof application === "string") {
4649
+ if (isRemoteOptions(candidate)) {
4650
+ options = candidate.clientOptions;
4651
+ args.pop();
4652
+ }
4653
+ } else {
4654
+ const parameters = definition.parameters;
4655
+ const expectedArgs = parameters.length;
4656
+ if (isRemoteOptions(candidate)) {
4657
+ const suppliedApplicationArgs = args.length - 1;
4658
+ const omitted = parameters.slice(suppliedApplicationArgs);
4659
+ if (omitted.some((parameter2) => parameter2.required)) {
4660
+ throw new SDKUsageError(
4661
+ `${definition.name} is missing a required application argument before remoteOptions`
4662
+ );
4663
+ }
4664
+ options = candidate.clientOptions;
4665
+ args.pop();
4666
+ } else if (args.length === expectedArgs + 1) {
4667
+ if (candidate !== void 0 && !isCloudClientOptions(candidate)) {
4668
+ throw new SDKUsageError("The trailing runRemote argument must be CloudClientOptions");
4669
+ }
4670
+ options = args.pop();
4671
+ }
4672
+ }
4673
+ const client = new APIClient(options);
4674
+ const inputs = args.map((value, index) => {
4675
+ const serialized = serializeValue(value);
4676
+ return { name: String(index), data: serialized.data, contentType: serialized.contentType };
4677
+ });
4678
+ const id = await client.runRequest(applicationName, inputs);
4679
+ return new RemoteRequest(id, applicationName, client, definition?.returns._file);
4680
+ }
4681
+
4682
+ // src/applications/manifest.ts
4683
+ init_cjs_shims();
4684
+ var import_node_buffer = require("buffer");
4685
+ var TYPESCRIPT_DESCRIPTOR_FORMAT = "tensorlake.typescript.json-schema.v1";
4686
+ function encodeDescriptor(value) {
4687
+ return import_node_buffer.Buffer.from(JSON.stringify({ format: TYPESCRIPT_DESCRIPTOR_FORMAT, value }), "utf8").toString("base64");
4688
+ }
4689
+ function decodeDescriptor(encoded) {
4690
+ const envelope = JSON.parse(import_node_buffer.Buffer.from(encoded, "base64").toString("utf8"));
4691
+ if (envelope.format !== TYPESCRIPT_DESCRIPTOR_FORMAT) {
4692
+ throw new SDKUsageError("Application manifest does not contain TypeScript schema descriptors");
4693
+ }
4694
+ return envelope.value;
4695
+ }
4696
+ function parseGPU(value) {
4697
+ const [model, countText, ...extra] = value.split(":");
4698
+ if (!model || extra.length > 0) throw new SDKUsageError(`Invalid GPU setting '${value}'`);
4699
+ const count = countText == null ? 1 : Number(countText);
4700
+ if (!Number.isInteger(count) || count <= 0) throw new SDKUsageError(`Invalid GPU count in '${value}'`);
4701
+ return { count, model };
4702
+ }
4703
+ function parameterManifest(parameter2) {
4704
+ return {
4705
+ name: parameter2.name,
4706
+ data_type: parameterJSONSchema(parameter2),
4707
+ description: parameter2.description,
4708
+ required: parameter2.required
4709
+ };
4710
+ }
4711
+ function functionManifest(application, definition) {
4712
+ const retries2 = definition.options.retries ?? application.application?.retries ?? { maxRetries: 0 };
4713
+ const gpu = definition.options.gpu == null ? [] : (Array.isArray(definition.options.gpu) ? definition.options.gpu : [definition.options.gpu]).map(parseGPU);
4714
+ const result = {
4715
+ name: definition.name,
4716
+ description: definition.options.description,
4717
+ docstring: "",
4718
+ secret_names: [...definition.options.secrets],
4719
+ initialization_timeout_sec: definition.options.timeout,
4720
+ timeout_sec: definition.options.timeout,
4721
+ resources: {
4722
+ cpus: definition.options.cpu,
4723
+ memory_mb: Math.ceil(definition.options.memory * 1024),
4724
+ ephemeral_disk_mb: Math.ceil(definition.options.ephemeralDisk * 1024),
4725
+ gpus: gpu
4726
+ },
4727
+ retry_policy: {
4728
+ max_retries: retries2.maxRetries,
4729
+ initial_delay_sec: 1,
4730
+ max_delay_sec: 60,
4731
+ delay_multiplier: 2
4732
+ },
4733
+ cache_key: null,
4734
+ parameters: definition.application == null ? [] : definition.parameters.map(parameterManifest),
4735
+ return_type: definition.application == null ? null : { ...definition.returns.jsonSchema, title: "Return value" },
4736
+ placement_constraints: {
4737
+ filter_expressions: (definition.options.region ?? application.options.region) == null ? [] : [`region==${definition.options.region ?? application.options.region}`]
4738
+ },
4739
+ max_concurrency: 1
4740
+ };
4741
+ if (definition.options.warmContainers != null) result.warm_containers = definition.options.warmContainers;
4742
+ if (definition.options.minContainers != null) result.min_containers = definition.options.minContainers;
4743
+ if (definition.options.maxContainers != null) result.max_containers = definition.options.maxContainers;
4744
+ if (definition.options.image != null) result.image = definition.options.image.name;
4745
+ return result;
4746
+ }
4747
+ function createApplicationManifest(application) {
4748
+ if (application.application == null) throw new SDKUsageError(`${application.name} is not an application`);
4749
+ const functions = Object.fromEntries(
4750
+ getFunctions().map((definition) => [definition.name, functionManifest(application, definition)])
4751
+ );
4752
+ return {
4753
+ name: application.name,
4754
+ description: application.options.description,
4755
+ tags: { ...application.application.tags },
4756
+ allow: [...application.application.allow],
4757
+ version: application.application.version,
4758
+ runtime: "typescript",
4759
+ functions,
4760
+ entrypoint: {
4761
+ function_name: application.name,
4762
+ input_serializer: "json",
4763
+ inputs_base64: encodeDescriptor(application.parameters.map((parameter2) => ({
4764
+ name: parameter2.name,
4765
+ schema: parameter2.schema.jsonSchema,
4766
+ required: parameter2.required,
4767
+ hasDefault: parameter2.hasDefault,
4768
+ defaultValue: parameter2.defaultValue
4769
+ }))),
4770
+ output_serializer: "json",
4771
+ output_type_hints_base64: encodeDescriptor(application.returns.jsonSchema)
4772
+ }
4773
+ };
4774
+ }
4775
+ function createApplicationManifests() {
4776
+ return getApplications().map(createApplicationManifest);
4777
+ }
4778
+ function createCodeManifest(module2 = "runtime.mjs") {
4779
+ return {
4780
+ format_version: 2,
4781
+ runtime: "typescript",
4782
+ minimum_node_major: 24,
4783
+ module: module2,
4784
+ functions: Object.fromEntries(getFunctions().map((definition) => [definition.name, { name: definition.name }]))
4785
+ };
4786
+ }
4787
+ // Annotate the CommonJS export names for ESM import in node:
4788
+ 0 && (module.exports = {
4789
+ DeserializationError,
4790
+ File,
4791
+ FunctionError,
4792
+ Future,
4793
+ Headers,
4794
+ HttpBody,
4795
+ Image,
4796
+ LocalRequest,
4797
+ RemoteRequest,
4798
+ ReplayMismatchError,
4799
+ RequestContext,
4800
+ RequestError,
4801
+ SDKUsageError,
4802
+ SDK_VERSION,
4803
+ SerializationError,
4804
+ TensorlakeApplicationError,
4805
+ TimeoutError,
4806
+ createApplicationManifest,
4807
+ createApplicationManifests,
4808
+ createCodeManifest,
4809
+ decodeDescriptor,
4810
+ getApplications,
4811
+ getFunction,
4812
+ getFunctions,
4813
+ registerApplication,
4814
+ registerFunction,
4815
+ remoteOptions,
4816
+ retries,
4817
+ runLocal,
4818
+ runRemote,
4819
+ schema
4820
+ });
4821
+ //# sourceMappingURL=index.cjs.map