@tensorlakeai/tensorlake 0.5.152 → 0.5.154

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 (35) hide show
  1. package/dist/applications/index.cjs +3596 -3377
  2. package/dist/applications/index.cjs.map +1 -1
  3. package/dist/applications/index.d.cts +3 -3
  4. package/dist/applications/index.d.ts +3 -3
  5. package/dist/applications/index.js +3559 -3340
  6. package/dist/applications/index.js.map +1 -1
  7. package/dist/function-agent/main.cjs +1 -1
  8. package/dist/function-agent/main.js +1 -1
  9. package/dist/function-executor/main.cjs +2 -2
  10. package/dist/function-executor/main.js +2 -2
  11. package/dist/index.cjs +1502 -880
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.cts +366 -21
  14. package/dist/index.d.ts +366 -21
  15. package/dist/index.js +1475 -871
  16. package/dist/index.js.map +1 -1
  17. package/dist/{remote-CC48cvYP.d.cts → remote-B3vn4tt1.d.cts} +1 -1
  18. package/dist/{remote-BbSrvgUn.d.ts → remote-DqBUuciu.d.ts} +1 -1
  19. package/dist/{sandbox-image-CAK_K7ND.d.cts → sandbox-image-BMiFlzAs.d.cts} +168 -13
  20. package/dist/{sandbox-image-CAK_K7ND.d.ts → sandbox-image-BMiFlzAs.d.ts} +168 -13
  21. package/dist/sandbox-image.cjs +437 -1300
  22. package/dist/sandbox-image.cjs.map +1 -1
  23. package/dist/sandbox-image.d.cts +1 -1
  24. package/dist/sandbox-image.d.ts +1 -1
  25. package/dist/sandbox-image.js +436 -1299
  26. package/dist/sandbox-image.js.map +1 -1
  27. package/package.json +7 -7
  28. package/runtime/function-executor/manifest.json +5 -5
  29. package/runtime/function-executor/package/dist/function-executor/main.js +2 -2
  30. package/runtime/function-executor/package/npm-shrinkwrap.json +2 -2
  31. package/runtime/function-executor/package/package.json +1 -1
  32. package/runtime/typescript-function-runner/manifest.json +5 -5
  33. package/runtime/typescript-function-runner/package/dist/function-agent/main.js +1 -1
  34. package/runtime/typescript-function-runner/package/npm-shrinkwrap.json +26 -26
  35. package/runtime/typescript-function-runner/package/package.json +7 -7
@@ -43,1184 +43,6 @@ var init_cjs_shims = __esm({
43
43
  }
44
44
  });
45
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.152";
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 CommandExitReason;
107
- var init_models = __esm({
108
- "src/models.ts"() {
109
- "use strict";
110
- init_cjs_shims();
111
- CommandExitReason = /* @__PURE__ */ ((CommandExitReason2) => {
112
- CommandExitReason2["EXITED"] = "exited";
113
- CommandExitReason2["SIGNALED"] = "signaled";
114
- CommandExitReason2["OOM_KILLED"] = "oom_killed";
115
- CommandExitReason2["TIMED_OUT"] = "timed_out";
116
- return CommandExitReason2;
117
- })(CommandExitReason || {});
118
- }
119
- });
120
-
121
- // src/errors.ts
122
- function formatErrorDetails(errorDetails) {
123
- if (errorDetails == null) return void 0;
124
- if (typeof errorDetails === "string") {
125
- const detail = errorDetails.trim();
126
- return detail || void 0;
127
- }
128
- if (Array.isArray(errorDetails)) {
129
- const parts = errorDetails.map((item) => formatErrorDetails(item)).filter((item) => Boolean(item));
130
- return parts.length > 0 ? parts.join("; ") : JSON.stringify(errorDetails);
131
- }
132
- if (typeof errorDetails === "object") {
133
- for (const key of ["message", "detail", "error", "reason"]) {
134
- const value = errorDetails[key];
135
- if (typeof value === "string" && value.trim()) {
136
- return value.trim();
137
- }
138
- }
139
- return JSON.stringify(errorDetails);
140
- }
141
- return String(errorDetails);
142
- }
143
- var SandboxException, SandboxError, SandboxResizeError, SandboxConnectionError, SandboxNotFoundError, PoolNotFoundError, PoolInUseError, RemoteAPIError;
144
- var init_errors = __esm({
145
- "src/errors.ts"() {
146
- "use strict";
147
- init_cjs_shims();
148
- SandboxException = class extends Error {
149
- constructor(message) {
150
- super(message);
151
- this.name = "SandboxException";
152
- }
153
- };
154
- SandboxError = class extends SandboxException {
155
- reason;
156
- sandboxId;
157
- constructor(message, options) {
158
- super(message);
159
- this.name = "SandboxError";
160
- if (options?.reason !== void 0) this.reason = options.reason;
161
- if (options?.sandboxId !== void 0) this.sandboxId = options.sandboxId;
162
- }
163
- };
164
- SandboxResizeError = class extends SandboxError {
165
- generation;
166
- info;
167
- constructor(payload) {
168
- const resources = payload.info?.resources;
169
- const allocation = resources ? `${resources.cpus} CPUs, ${resources.memoryMb} MiB memory, ${resources.diskMb} MiB disk` : "unavailable";
170
- super(
171
- `Sandbox ${payload.sandboxId} resize generation ${payload.generation}: ${payload.message}; last confirmed allocation: ${allocation}`,
172
- { reason: payload.reason, sandboxId: payload.sandboxId }
173
- );
174
- this.name = "SandboxResizeError";
175
- this.generation = payload.generation;
176
- this.info = payload.info ?? void 0;
177
- }
178
- /** Last confirmed allocation, if an observation was available. */
179
- get confirmedResources() {
180
- return this.info?.resources;
181
- }
182
- };
183
- SandboxConnectionError = class extends SandboxError {
184
- constructor(message, options) {
185
- super(`Connection error: ${message}`);
186
- this.name = "SandboxConnectionError";
187
- if (options?.cause !== void 0) this.cause = options.cause;
188
- }
189
- };
190
- SandboxNotFoundError = class extends SandboxError {
191
- constructor(sandboxId) {
192
- super(`Sandbox not found: ${sandboxId}`, { sandboxId });
193
- this.name = "SandboxNotFoundError";
194
- }
195
- };
196
- PoolNotFoundError = class extends SandboxError {
197
- poolId;
198
- constructor(poolId) {
199
- super(`Sandbox pool not found: ${poolId}`);
200
- this.name = "PoolNotFoundError";
201
- this.poolId = poolId;
202
- }
203
- };
204
- PoolInUseError = class extends SandboxError {
205
- poolId;
206
- constructor(poolId, message) {
207
- const base = `Cannot delete pool ${poolId}: pool is in use`;
208
- super(message ? `${base} - ${message}` : base);
209
- this.name = "PoolInUseError";
210
- this.poolId = poolId;
211
- }
212
- };
213
- RemoteAPIError = class extends SandboxError {
214
- statusCode;
215
- /** Original response body, retained for compatibility and diagnostics. */
216
- responseMessage;
217
- errorDetails;
218
- constructor(statusCode, message) {
219
- let failure;
220
- try {
221
- const payload = JSON.parse(message);
222
- if (payload && typeof payload === "object" && !Array.isArray(payload)) {
223
- const record = payload;
224
- if (typeof record.sandbox_id === "string" && record.sandbox_id.trim() && (record.status === "failed" || record.status === "terminated"))
225
- failure = record;
226
- }
227
- } catch {
228
- }
229
- const sandboxId = failure?.sandbox_id;
230
- const rawReason = failure?.reason ?? failure?.termination_reason;
231
- const reason = typeof rawReason === "string" ? rawReason : void 0;
232
- const errorDetails = failure?.error_details;
233
- let displayMessage = message;
234
- if (failure) {
235
- displayMessage = `Sandbox ${sandboxId} ${failure.status}`;
236
- if (reason) displayMessage += ` (${reason})`;
237
- const detail = formatErrorDetails(errorDetails);
238
- if (detail) displayMessage += `: ${detail}`;
239
- if (!reason && !detail) displayMessage = message;
240
- }
241
- super(`API error (status ${statusCode}): ${displayMessage}`, {
242
- reason,
243
- sandboxId
244
- });
245
- this.errorDetails = errorDetails;
246
- this.name = "RemoteAPIError";
247
- this.statusCode = statusCode;
248
- this.responseMessage = message;
249
- }
250
- };
251
- }
252
- });
253
-
254
- // src/native-worker-protocol.ts
255
- var cancelNativeCall, closeNativeHandle;
256
- var init_native_worker_protocol = __esm({
257
- "src/native-worker-protocol.ts"() {
258
- "use strict";
259
- init_cjs_shims();
260
- cancelNativeCall = /* @__PURE__ */ Symbol.for("tensorlake.native.cancel.v1");
261
- closeNativeHandle = /* @__PURE__ */ Symbol.for("tensorlake.native.close.v1");
262
- }
263
- });
264
-
265
- // src/url.ts
266
- function trimTrailingSlashes(url) {
267
- return url.endsWith("/") ? url.slice(0, -1) : url;
268
- }
269
- function resolveProxyTarget(proxyUrl, sandboxId) {
270
- try {
271
- const parsed = new URL(proxyUrl);
272
- const host = parsed.hostname;
273
- if (host === "localhost" || host === "127.0.0.1") {
274
- return {
275
- baseUrl: trimTrailingSlashes(proxyUrl),
276
- hostHeader: `${sandboxId}.local`,
277
- sandboxIdHeader: void 0
278
- };
279
- }
280
- const port = parsed.port ? `:${parsed.port}` : "";
281
- return {
282
- baseUrl: `${parsed.protocol}//${host}${port}`,
283
- hostHeader: void 0,
284
- sandboxIdHeader: sandboxId
285
- };
286
- } catch {
287
- return {
288
- baseUrl: `${trimTrailingSlashes(proxyUrl)}/${sandboxId}`,
289
- hostHeader: void 0,
290
- sandboxIdHeader: void 0
291
- };
292
- }
293
- }
294
- var init_url = __esm({
295
- "src/url.ts"() {
296
- "use strict";
297
- init_cjs_shims();
298
- init_defaults();
299
- }
300
- });
301
-
302
- // src/native-worker-client.ts
303
- function createWorkerBinding(runtime) {
304
- return {
305
- NativeCloudClient: class {
306
- constructor(...args) {
307
- return runtime.handle("NativeCloudClient", args);
308
- }
309
- },
310
- NativeSandboxClient: class {
311
- constructor(...args) {
312
- return runtime.handle("NativeSandboxClient", args);
313
- }
314
- },
315
- NativeSandboxProxyClient: class {
316
- constructor(...args) {
317
- return runtime.handle("NativeSandboxProxyClient", args);
318
- }
319
- },
320
- NativeRepositoryClient: class {
321
- constructor(...args) {
322
- return runtime.handle("NativeRepositoryClient", args);
323
- }
324
- },
325
- NativeTcpTunnel: class {
326
- constructor() {
327
- return runtime.handle("NativeTcpTunnel", []);
328
- }
329
- },
330
- validateManagedName: (name) => runtime.call(void 0, "validateManagedName", [name])
331
- };
332
- }
333
- function workerBinding() {
334
- return createWorkerBinding(
335
- runtimes[runtimeKey] ??= new NativeWorkerClient()
336
- );
337
- }
338
- function releaseNativeHandle(handle) {
339
- handle?.[closeNativeHandle]?.();
340
- }
341
- var import_node_module, import_node_worker_threads, NativeWorkerClient, runtimeKey, runtimes;
342
- var init_native_worker_client = __esm({
343
- "src/native-worker-client.ts"() {
344
- "use strict";
345
- init_cjs_shims();
346
- import_node_module = require("module");
347
- import_node_worker_threads = require("worker_threads");
348
- init_native_worker_protocol();
349
- init_url();
350
- NativeWorkerClient = class {
351
- constructor(workerPath = () => (0, import_node_module.createRequire)(importMetaUrl).resolve(
352
- "@tensorlakeai/tensorlake/internal/native-worker"
353
- )) {
354
- this.workerPath = workerPath;
355
- }
356
- worker;
357
- nextId = 1;
358
- registered = /* @__PURE__ */ new Set();
359
- pending = /* @__PURE__ */ new Map();
360
- finalizers = new FinalizationRegistry(
361
- (id) => this.release(id)
362
- );
363
- handle(kind, args, parent) {
364
- const handle = { id: this.nextId++, kind, args, parent };
365
- this.finalizers.register(handle, handle.id);
366
- let closed = false;
367
- return new Proxy(
368
- {},
369
- {
370
- get: (_target, method) => {
371
- if (method === "then") return void 0;
372
- if (method === closeNativeHandle)
373
- return () => {
374
- closed = true;
375
- this.release(handle.id);
376
- };
377
- if (method === "connectProxy")
378
- return (...proxyArgs) => {
379
- if (closed) throw new Error("Tensorlake native client is closed");
380
- return this.handle("NativeSandboxProxyClient", proxyArgs, handle);
381
- };
382
- if (method === "baseUrl")
383
- return () => resolveProxyTarget(String(args[0]), String(args[1])).baseUrl;
384
- if (typeof method !== "string") return void 0;
385
- return (...callArgs) => {
386
- if (closed)
387
- return Promise.reject(
388
- new Error("Tensorlake native client is closed")
389
- );
390
- const emit = typeof callArgs.at(-1) === "function" ? callArgs.pop() : void 0;
391
- return this.call(handle, method, callArgs, emit);
392
- };
393
- }
394
- }
395
- );
396
- }
397
- call(handle, method, args, emit) {
398
- const id = this.nextId++;
399
- let worker;
400
- const promise = new Promise((resolve, reject) => {
401
- try {
402
- worker = this.getWorker();
403
- this.pending.set(id, { resolve, reject, emit, handle });
404
- worker.ref();
405
- if (handle) this.register(handle, worker);
406
- this.send(worker, {
407
- type: "call",
408
- id,
409
- handleId: handle?.id,
410
- method,
411
- args,
412
- stream: !!emit
413
- });
414
- } catch (error) {
415
- this.pending.delete(id);
416
- this.unrefIfIdle();
417
- reject(error);
418
- }
419
- });
420
- promise[cancelNativeCall] = () => {
421
- const pending = this.pending.get(id);
422
- if (pending && worker) {
423
- pending.emit = void 0;
424
- this.send(worker, { type: "cancel", id });
425
- }
426
- };
427
- return promise;
428
- }
429
- getWorker() {
430
- if (this.worker) return this.worker;
431
- const worker = new import_node_worker_threads.Worker(this.workerPath(), {
432
- // The bundled worker needs no application loaders or telemetry preloads.
433
- // NODE_OPTIONS is parsed independently of execArgv by Node.
434
- execArgv: [],
435
- env: { ...process.env, NODE_OPTIONS: "" },
436
- name: "tensorlake-native"
437
- });
438
- this.worker = worker;
439
- worker.on("message", (message) => {
440
- const pending = this.pending.get(message.id);
441
- if (!pending || this.worker !== worker) return;
442
- if (message.type === "event") {
443
- Promise.resolve().then(() => pending.emit?.(message.value)).then(
444
- () => {
445
- if (this.worker === worker)
446
- this.send(worker, { type: "ack", id: message.id });
447
- },
448
- (error) => {
449
- this.send(worker, { type: "cancel", id: message.id });
450
- pending.reject(error);
451
- }
452
- );
453
- return;
454
- }
455
- this.pending.delete(message.id);
456
- if (message.type === "error") {
457
- const error = new Error(message.error.message);
458
- error.name = message.error.name;
459
- error.stack = message.error.stack ?? error.stack;
460
- pending.reject(error);
461
- } else {
462
- pending.resolve(message.value);
463
- }
464
- this.unrefIfIdle();
465
- });
466
- const fail = (error) => {
467
- if (this.worker !== worker) return;
468
- this.worker = void 0;
469
- this.registered.clear();
470
- for (const pending of this.pending.values()) pending.reject(error);
471
- this.pending.clear();
472
- void worker.terminate();
473
- };
474
- worker.on("error", fail);
475
- worker.on("messageerror", fail);
476
- worker.on(
477
- "exit",
478
- (code) => fail(
479
- new Error(
480
- `Tensorlake native worker exited (${code}); in-flight operations were not retried`
481
- )
482
- )
483
- );
484
- worker.unref();
485
- return worker;
486
- }
487
- register(handle, worker) {
488
- if (this.registered.has(handle.id)) return;
489
- if (handle.parent) this.register(handle.parent, worker);
490
- this.send(worker, {
491
- type: "create",
492
- handle: { id: handle.id, kind: handle.kind, args: handle.args },
493
- parentId: handle.parent?.id
494
- });
495
- this.registered.add(handle.id);
496
- }
497
- release(handleId) {
498
- if (this.worker && this.registered.delete(handleId))
499
- this.send(this.worker, { type: "release", handleId });
500
- }
501
- send(worker, message) {
502
- worker.postMessage(message);
503
- }
504
- unrefIfIdle() {
505
- if (this.pending.size === 0) this.worker?.unref();
506
- }
507
- };
508
- runtimeKey = /* @__PURE__ */ Symbol.for(
509
- `tensorlake.native.worker.${false ? "source" : "0.5.152"}.v1`
510
- );
511
- runtimes = globalThis;
512
- }
513
- });
514
-
515
- // src/native-sandbox.ts
516
- function loadNativeSandboxBinding() {
517
- return cachedBinding ??= workerBinding();
518
- }
519
- function parseNativeError(error) {
520
- const message = error instanceof Error ? error.message : typeof error === "string" ? error : "";
521
- if (!message) return null;
522
- try {
523
- const parsed = JSON.parse(message);
524
- if (parsed && typeof parsed.category === "string") {
525
- return {
526
- category: parsed.category,
527
- status: typeof parsed.status === "number" ? parsed.status : null,
528
- message: typeof parsed.message === "string" ? parsed.message : message
529
- };
530
- }
531
- } catch {
532
- }
533
- return null;
534
- }
535
- function translateNativeError(error, context) {
536
- const payload = parseNativeError(error);
537
- if (!payload) {
538
- if (error instanceof Error) return error;
539
- return new SandboxError(String(error));
540
- }
541
- const { category, status, message } = payload;
542
- if (category === "resize") {
543
- return new SandboxResizeError(
544
- fromSnakeKeys(JSON.parse(message), "sandboxId")
545
- );
546
- }
547
- if (category === "connection") {
548
- return new SandboxConnectionError(message, { cause: error });
549
- }
550
- if (status === 404) {
551
- if (context?.notFoundKind === "pool" && context.poolId) {
552
- return new PoolNotFoundError(context.poolId);
553
- }
554
- if (context?.notFoundKind === "sandbox" && context.sandboxId) {
555
- return new SandboxNotFoundError(context.sandboxId);
556
- }
557
- return new RemoteAPIError(404, message);
558
- }
559
- if (status === 409 && context?.poolId) {
560
- return new PoolInUseError(context.poolId, message);
561
- }
562
- if (typeof status === "number") {
563
- return new RemoteAPIError(status, message);
564
- }
565
- return new SandboxError(message);
566
- }
567
- async function callNative(fn, context) {
568
- try {
569
- return await fn();
570
- } catch (error) {
571
- throw translateNativeError(error, context);
572
- }
573
- }
574
- async function* nativeEventStream(start, context, signal) {
575
- if (signal?.aborted) return;
576
- const queue = [];
577
- let wake;
578
- let finished = false;
579
- let stopped = false;
580
- let failure;
581
- const notify = () => {
582
- const resolve = wake;
583
- wake = void 0;
584
- resolve?.();
585
- };
586
- const emit = (value) => {
587
- if (stopped) return Promise.resolve();
588
- return new Promise((consumed) => {
589
- queue.push({ value, consumed });
590
- notify();
591
- });
592
- };
593
- let call;
594
- const onAbort = () => {
595
- stopped = true;
596
- call?.[cancelNativeCall]?.();
597
- notify();
598
- };
599
- signal?.addEventListener("abort", onAbort, { once: true });
600
- try {
601
- call = start(emit);
602
- void call.catch((error) => {
603
- failure = error;
604
- }).finally(() => {
605
- finished = true;
606
- notify();
607
- });
608
- while (!stopped) {
609
- const event = queue.shift();
610
- if (event) {
611
- try {
612
- yield JSON.parse(event.value);
613
- } finally {
614
- event.consumed();
615
- }
616
- } else if (finished) {
617
- break;
618
- } else {
619
- await new Promise((resolve) => {
620
- wake = resolve;
621
- });
622
- }
623
- }
624
- if (!stopped && failure !== void 0) throw translateNativeError(failure, context);
625
- } finally {
626
- stopped = true;
627
- signal?.removeEventListener("abort", onAbort);
628
- call?.[cancelNativeCall]?.();
629
- for (const event of queue) event.consumed();
630
- }
631
- }
632
- var cachedBinding, KNOWN_EXIT_REASONS;
633
- var init_native_sandbox = __esm({
634
- "src/native-sandbox.ts"() {
635
- "use strict";
636
- init_cjs_shims();
637
- init_models();
638
- init_errors();
639
- init_native_worker_client();
640
- init_native_worker_protocol();
641
- KNOWN_EXIT_REASONS = new Set(Object.values(CommandExitReason));
642
- }
643
- });
644
-
645
- // src/native-cloud.ts
646
- async function serializeRequest(method, path3, options) {
647
- const headers = { ...options?.headers };
648
- let body = options?.body;
649
- if (options?.json !== void 0) {
650
- body = JSON.stringify(options.json);
651
- if (!Object.keys(headers).some((key) => key.toLowerCase() === "content-type")) {
652
- headers["Content-Type"] = "application/json";
653
- }
654
- }
655
- const request = {
656
- method,
657
- path: path3,
658
- headersJson: JSON.stringify(headers),
659
- statusOnlyCodes: [...options?.statusOnlyCodes ?? []]
660
- };
661
- if (body instanceof FormData) {
662
- request.parts = [];
663
- for (const [name, value] of body.entries()) {
664
- 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" });
665
- }
666
- } else if (body !== void 0) {
667
- if (body instanceof Blob) request.body = Buffer.from(await body.arrayBuffer());
668
- else if (typeof body === "string") request.body = Buffer.from(body);
669
- else if (body instanceof ArrayBuffer) request.body = Buffer.from(new Uint8Array(body));
670
- else request.body = Buffer.from(body);
671
- }
672
- return request;
673
- }
674
- var NativeCloudTransport;
675
- var init_native_cloud = __esm({
676
- "src/native-cloud.ts"() {
677
- "use strict";
678
- init_cjs_shims();
679
- init_native_sandbox();
680
- init_native_worker_client();
681
- NativeCloudTransport = class {
682
- constructor(options) {
683
- this.options = options;
684
- if (!Number.isSafeInteger(options.maxRetries) || options.maxRetries < 0 || options.maxRetries > 4294967295) {
685
- throw new RangeError("maxRetries must be a non-negative 32-bit integer");
686
- }
687
- if (!Number.isFinite(options.retryBackoffMs) || options.retryBackoffMs < 0) {
688
- throw new RangeError("retryBackoffMs must be a non-negative finite number");
689
- }
690
- }
691
- native;
692
- closed = false;
693
- client() {
694
- if (this.closed) throw new Error("Tensorlake native client is closed");
695
- if (this.native) return this.native;
696
- const ctor = loadNativeSandboxBinding().NativeCloudClient;
697
- if (!ctor) throw new Error("Native binding does not export NativeCloudClient; rebuild with 'npm run build:native'");
698
- return this.native = new ctor(JSON.stringify(this.options));
699
- }
700
- close() {
701
- this.closed = true;
702
- releaseNativeHandle(this.native ?? null);
703
- this.native = void 0;
704
- }
705
- async requestResponse(method, path3, options) {
706
- const request = await serializeRequest(method, path3, options);
707
- const raw = await callNative(() => this.client().request(request));
708
- const response = new Response(
709
- [204, 205, 304].includes(raw.status) ? null : Uint8Array.from(raw.data).buffer,
710
- { status: raw.status, headers: JSON.parse(raw.headersJson) }
711
- );
712
- return Object.assign(response, { traceId: raw.traceId });
713
- }
714
- async requestJson(method, path3) {
715
- const response = await this.requestResponse(method, path3);
716
- const text = await response.text();
717
- const value = text ? JSON.parse(text) : null;
718
- return Object.assign(value ?? {}, { traceId: response.traceId });
719
- }
720
- async *stream(method, path3, signal) {
721
- if (signal?.aborted) return;
722
- const request = await serializeRequest(method, path3, { headers: { Accept: "text/event-stream" } });
723
- yield* nativeEventStream((emit) => this.client().stream(request, emit), void 0, signal);
724
- }
725
- };
726
- }
727
- });
728
-
729
- // src/cloud-client.ts
730
- function secretFromMetadata(metadata) {
731
- return {
732
- id: metadata.id,
733
- name: metadata.name,
734
- createdAt: new Date(metadata.created_at_ms)
735
- };
736
- }
737
- function applicationAllowsUnauthenticatedRequests(manifest) {
738
- return Array.isArray(manifest.allow) && manifest.allow.includes(UNAUTHENTICATED_REQUESTS);
739
- }
740
- function publicEndpointIdFromManifest(manifest) {
741
- for (const key of ["public_endpoint_id", "publicEndpointId"]) {
742
- const value = manifest[key];
743
- if (typeof value === "string" && value.length > 0) {
744
- return value;
745
- }
746
- }
747
- return void 0;
748
- }
749
- function generatePublicEndpointId() {
750
- return `endpoint_${(0, import_nanoid.nanoid)()}`;
751
- }
752
- function createApplicationBuildForm(request, imageContexts) {
753
- const contextsByPartName = /* @__PURE__ */ new Map();
754
- for (const context of imageContexts) {
755
- if (contextsByPartName.has(context.contextTarPartName)) {
756
- throw new Error(
757
- `duplicate image context part name '${context.contextTarPartName}'`
758
- );
759
- }
760
- contextsByPartName.set(context.contextTarPartName, context);
761
- }
762
- const form = new FormData();
763
- form.append(
764
- "app_version",
765
- new Blob([JSON.stringify(request)], { type: "application/json" }),
766
- "app_version"
767
- );
768
- for (const image of request.images) {
769
- const context = contextsByPartName.get(image.contextTarPartName);
770
- if (!context) {
771
- throw new Error(
772
- `missing image context for part '${image.contextTarPartName}'`
773
- );
774
- }
775
- form.append(
776
- image.contextTarPartName,
777
- new Blob([toBlobPart(context.contextTarGz)]),
778
- `${image.contextTarPartName}.tar.gz`
779
- );
780
- }
781
- for (const context of imageContexts) {
782
- if (!request.images.some((image) => image.contextTarPartName === context.contextTarPartName)) {
783
- throw new Error(
784
- `unexpected image context for part '${context.contextTarPartName}'`
785
- );
786
- }
787
- }
788
- return form;
789
- }
790
- function trimTrailingSlashes2(value) {
791
- return value.endsWith("/") ? value.slice(0, -1) : value;
792
- }
793
- function nextRequestPath(next) {
794
- const schemeIndex = next.indexOf("://");
795
- if (schemeIndex !== -1) {
796
- const afterScheme = next.slice(schemeIndex + 3);
797
- const slashIndex = afterScheme.indexOf("/");
798
- return slashIndex === -1 ? "/" : afterScheme.slice(slashIndex);
799
- }
800
- return next.startsWith("/") ? next : `/${next}`;
801
- }
802
- function toBlobPart(data) {
803
- if (typeof data === "string" || data instanceof Blob) {
804
- return data;
805
- }
806
- if (data instanceof Uint8Array) {
807
- return Uint8Array.from(data).buffer;
808
- }
809
- return data;
810
- }
811
- function toRequestBody(data) {
812
- return toBlobPart(data);
813
- }
814
- async function parseJsonResponse(response) {
815
- const text = await response.text();
816
- if (!text) {
817
- return void 0;
818
- }
819
- return JSON.parse(text);
820
- }
821
- var import_nanoid, CloudClient, UNAUTHENTICATED_REQUESTS;
822
- var init_cloud_client = __esm({
823
- "src/cloud-client.ts"() {
824
- "use strict";
825
- init_cjs_shims();
826
- import_nanoid = require("nanoid");
827
- init_defaults();
828
- init_native_cloud();
829
- init_models();
830
- CloudClient = class _CloudClient {
831
- transport;
832
- organizationId;
833
- projectId;
834
- namespace;
835
- constructor(options) {
836
- this.organizationId = options?.organizationId;
837
- this.projectId = options?.projectId;
838
- this.namespace = options?.namespace ?? NAMESPACE;
839
- this.transport = new NativeCloudTransport({
840
- baseUrl: options?.apiUrl ?? API_URL,
841
- apiKey: options?.apiKey ?? API_KEY,
842
- organizationId: this.organizationId,
843
- projectId: this.projectId,
844
- maxRetries: options?.maxRetries ?? MAX_RETRIES,
845
- retryBackoffMs: options?.retryBackoffMs ?? RETRY_BACKOFF_MS,
846
- timeoutMs: DEFAULT_HTTP_TIMEOUT_MS,
847
- userAgent: `tensorlake-typescript-sdk/${SDK_VERSION}`
848
- });
849
- }
850
- static forCloud(options) {
851
- return new _CloudClient(options);
852
- }
853
- close() {
854
- this.transport.close();
855
- }
856
- async upsertApplication(manifest, codeZip, upgradeRunningRequests = false) {
857
- const applicationManifest = { ...manifest };
858
- let publicEndpointId = publicEndpointIdFromManifest(applicationManifest);
859
- if (applicationAllowsUnauthenticatedRequests(applicationManifest) && publicEndpointId === void 0) {
860
- const applicationName = applicationManifest.name;
861
- if (typeof applicationName === "string" && applicationName.length > 0) {
862
- publicEndpointId = await this.existingApplicationPublicEndpointId(applicationName);
863
- }
864
- publicEndpointId ??= generatePublicEndpointId();
865
- }
866
- if (publicEndpointId !== void 0) {
867
- applicationManifest.public_endpoint_id = publicEndpointId;
868
- delete applicationManifest.publicEndpointId;
869
- }
870
- const form = new FormData();
871
- form.append(
872
- "code",
873
- new Blob([toBlobPart(codeZip)], { type: "application/zip" }),
874
- "code.zip"
875
- );
876
- form.append("code_content_type", "application/zip");
877
- form.append("application", JSON.stringify(applicationManifest));
878
- form.append(
879
- "upgrade_requests_to_latest_code",
880
- String(upgradeRunningRequests)
881
- );
882
- await this.transport.requestResponse("POST", this.namespacePath("applications"), {
883
- body: form
884
- });
885
- }
886
- async deleteApplication(applicationName) {
887
- await this.transport.requestResponse(
888
- "DELETE",
889
- this.namespacePath(`applications/${encodeURIComponent(applicationName)}`)
890
- );
891
- }
892
- async deleteSandboxImage(imageName) {
893
- await this.transport.requestResponse(
894
- "DELETE",
895
- this.namespacePath(`sandbox-images/${encodeURIComponent(imageName)}`)
896
- );
897
- }
898
- /**
899
- * Look up a registered sandbox image (template) by its registered name.
900
- *
901
- * Returns the template, or `null` when no image with that name exists.
902
- * API-key clients may omit organization/project IDs and use the
903
- * token-scoped Platform API route directly. Explicit scope remains
904
- * available for PAT callers.
905
- */
906
- async findSandboxImageByName(imageName, options) {
907
- const base = this.platformProjectPath(
908
- "sandbox-templates",
909
- options?.organizationId,
910
- options?.projectId
911
- );
912
- const response = await this.transport.requestResponse(
913
- "GET",
914
- `${base}/by-name/${encodeURIComponent(imageName)}`,
915
- { statusOnlyCodes: /* @__PURE__ */ new Set([404]) }
916
- );
917
- if (response.status === 404) {
918
- return null;
919
- }
920
- const raw = await parseJsonResponse(response);
921
- return fromSnakeKeys(raw);
922
- }
923
- /**
924
- * List all registered sandbox images (templates), following pagination to
925
- * the end. API-key clients may omit organization/project IDs and use the
926
- * token-scoped Platform API route directly.
927
- */
928
- async listSandboxImages(options) {
929
- const base = this.platformProjectPath(
930
- "sandbox-templates",
931
- options?.organizationId,
932
- options?.projectId
933
- );
934
- let path3 = `${base}?pageSize=100`;
935
- const templates = [];
936
- while (path3 !== null) {
937
- const page = await this.transport.requestJson(
938
- "GET",
939
- path3
940
- );
941
- for (const item of page.items ?? []) {
942
- templates.push(fromSnakeKeys(item));
943
- }
944
- const next = page.pagination?.next;
945
- path3 = next ? nextRequestPath(next) : null;
946
- }
947
- return templates;
948
- }
949
- async applications() {
950
- const raw = await this.transport.requestJson(
951
- "GET",
952
- this.namespacePath("applications")
953
- );
954
- return (raw.applications ?? []).map(
955
- (application) => fromSnakeKeys(application)
956
- );
957
- }
958
- async applicationManifest(applicationName) {
959
- const raw = await this.transport.requestJson(
960
- "GET",
961
- this.namespacePath(`applications/${encodeURIComponent(applicationName)}`)
962
- );
963
- return fromSnakeKeys(raw);
964
- }
965
- async runRequest(applicationName, inputs = []) {
966
- const path3 = this.namespacePath(
967
- `applications/${encodeURIComponent(applicationName)}`
968
- );
969
- const response = inputs.length === 0 ? await this.transport.requestResponse("POST", path3, {
970
- body: new Uint8Array(),
971
- headers: { Accept: "application/json" }
972
- }) : inputs.length === 1 && inputs[0].name === "0" ? await this.transport.requestResponse("POST", path3, {
973
- body: toRequestBody(inputs[0].data),
974
- headers: {
975
- Accept: "application/json",
976
- "Content-Type": inputs[0].contentType
977
- }
978
- }) : await this.runMultipartRequest(path3, inputs);
979
- const body = await parseJsonResponse(response);
980
- const requestId = body?.request_id;
981
- if (!requestId) {
982
- throw new Error("missing request_id in run request response body");
983
- }
984
- return requestId;
985
- }
986
- async waitOnRequestCompletion(applicationName, requestId) {
987
- const stream = this.transport.stream(
988
- "GET",
989
- this.namespacePath(
990
- `applications/${encodeURIComponent(applicationName)}/requests/${encodeURIComponent(requestId)}/progress`
991
- )
992
- );
993
- for await (const event of stream) {
994
- if (Object.prototype.hasOwnProperty.call(event, "RequestFinished")) {
995
- return;
996
- }
997
- }
998
- throw new Error("progress stream ended before request completion");
999
- }
1000
- async requestMetadata(applicationName, requestId) {
1001
- const raw = await this.transport.requestJson(
1002
- "GET",
1003
- this.namespacePath(
1004
- `applications/${encodeURIComponent(applicationName)}/requests/${encodeURIComponent(requestId)}`
1005
- )
1006
- );
1007
- return fromSnakeKeys(raw);
1008
- }
1009
- async requestOutput(applicationName, requestId) {
1010
- const response = await this.transport.requestResponse(
1011
- "GET",
1012
- this.namespacePath(
1013
- `applications/${encodeURIComponent(applicationName)}/requests/${encodeURIComponent(requestId)}/output`
1014
- )
1015
- );
1016
- const serializedValue = new Uint8Array(await response.arrayBuffer());
1017
- const contentType = response.headers.get("content-type") ?? "";
1018
- return {
1019
- serializedValue,
1020
- contentType
1021
- };
1022
- }
1023
- async listSecrets(options) {
1024
- const base = this.secretCollectionPath(
1025
- options?.organizationId,
1026
- options?.projectId
1027
- );
1028
- const raw = await this.transport.requestJson("GET", base);
1029
- const pageSize = Math.max(0, options?.pageSize ?? 100);
1030
- return Object.assign(
1031
- {
1032
- items: raw.slice(0, pageSize).map(secretFromMetadata),
1033
- pagination: { total: raw.length }
1034
- },
1035
- { traceId: raw.traceId }
1036
- );
1037
- }
1038
- async getSecret(secretId, options) {
1039
- const base = this.secretCollectionPath(
1040
- options?.organizationId,
1041
- options?.projectId
1042
- );
1043
- const raw = await this.transport.requestJson(
1044
- "GET",
1045
- `${base}/${encodeURIComponent(secretId)}`
1046
- );
1047
- return Object.assign(secretFromMetadata(raw), { traceId: raw.traceId });
1048
- }
1049
- async upsertSecrets(secrets, options) {
1050
- const base = this.secretCollectionPath(
1051
- options?.organizationId,
1052
- options?.projectId
1053
- );
1054
- if (Array.isArray(secrets)) {
1055
- const results = [];
1056
- for (const secret of secrets) {
1057
- results.push(await this.upsertSecret(base, secret));
1058
- }
1059
- return results;
1060
- }
1061
- return this.upsertSecret(base, secrets);
1062
- }
1063
- async deleteSecret(secretId, options) {
1064
- const base = this.secretCollectionPath(
1065
- options?.organizationId,
1066
- options?.projectId
1067
- );
1068
- await this.transport.requestResponse(
1069
- "DELETE",
1070
- `${base}/${encodeURIComponent(secretId)}`
1071
- );
1072
- }
1073
- async upsertSecret(base, secret) {
1074
- let response = await this.transport.requestResponse("POST", base, {
1075
- json: secret,
1076
- headers: { "Idempotency-Key": (0, import_nanoid.nanoid)() },
1077
- statusOnlyCodes: /* @__PURE__ */ new Set([409])
1078
- });
1079
- if (response.status === 409) {
1080
- const prefix = base.slice(0, -"/secrets".length);
1081
- const existing = await this.transport.requestJson(
1082
- "GET",
1083
- `${prefix}/secret-names/${encodeURIComponent(secret.name)}`
1084
- );
1085
- response = await this.transport.requestResponse(
1086
- "POST",
1087
- `${base}/${encodeURIComponent(existing.id)}/versions`,
1088
- {
1089
- json: { value: secret.value },
1090
- headers: { "Idempotency-Key": (0, import_nanoid.nanoid)() }
1091
- }
1092
- );
1093
- }
1094
- const metadata = await parseJsonResponse(response);
1095
- return Object.assign(secretFromMetadata(metadata), {
1096
- traceId: response.traceId
1097
- });
1098
- }
1099
- async startImageBuild(buildServicePath, request) {
1100
- const form = new FormData();
1101
- form.append("graph_name", request.applicationName);
1102
- form.append("graph_version", request.applicationVersion);
1103
- form.append("graph_function_name", request.functionName);
1104
- form.append("image_name", request.imageName);
1105
- form.append("image_id", request.imageId);
1106
- form.append(
1107
- "context",
1108
- new Blob([toBlobPart(request.buildContext)]),
1109
- "context.tar.gz"
1110
- );
1111
- const response = await this.transport.requestResponse(
1112
- "PUT",
1113
- `${trimTrailingSlashes2(buildServicePath)}/builds`,
1114
- { body: form }
1115
- );
1116
- const raw = await parseJsonResponse(response);
1117
- return fromSnakeKeys(raw);
1118
- }
1119
- async createApplicationBuild(buildServicePath, request, imageContexts) {
1120
- const form = createApplicationBuildForm(request, imageContexts);
1121
- const response = await this.transport.requestResponse(
1122
- "POST",
1123
- trimTrailingSlashes2(buildServicePath),
1124
- { body: form }
1125
- );
1126
- const raw = await parseJsonResponse(response);
1127
- return fromSnakeKeys(raw);
1128
- }
1129
- async applicationBuildInfo(buildServicePath, applicationBuildId) {
1130
- const raw = await this.transport.requestJson(
1131
- "GET",
1132
- `${trimTrailingSlashes2(buildServicePath)}/${encodeURIComponent(applicationBuildId)}`
1133
- );
1134
- return fromSnakeKeys(raw);
1135
- }
1136
- async cancelApplicationBuild(buildServicePath, applicationBuildId) {
1137
- const raw = await this.transport.requestJson(
1138
- "POST",
1139
- `${trimTrailingSlashes2(buildServicePath)}/${encodeURIComponent(applicationBuildId)}/cancel`
1140
- );
1141
- return fromSnakeKeys(raw);
1142
- }
1143
- async buildInfo(buildServicePath, buildId) {
1144
- const raw = await this.transport.requestJson(
1145
- "GET",
1146
- `${trimTrailingSlashes2(buildServicePath)}/builds/${encodeURIComponent(buildId)}`
1147
- );
1148
- return fromSnakeKeys(raw);
1149
- }
1150
- async cancelBuild(buildServicePath, buildId) {
1151
- await this.transport.requestResponse(
1152
- "POST",
1153
- `${trimTrailingSlashes2(buildServicePath)}/builds/${encodeURIComponent(buildId)}/cancel`
1154
- );
1155
- }
1156
- async *streamBuildLogs(buildServicePath, buildId, signal) {
1157
- const stream = this.transport.stream(
1158
- "GET",
1159
- `${trimTrailingSlashes2(buildServicePath)}/builds/${encodeURIComponent(buildId)}/logs`,
1160
- signal
1161
- );
1162
- for await (const event of stream) {
1163
- yield fromSnakeKeys(event);
1164
- }
1165
- }
1166
- async runMultipartRequest(path3, inputs) {
1167
- const form = new FormData();
1168
- for (const input of inputs) {
1169
- form.append(
1170
- input.name,
1171
- new Blob([toBlobPart(input.data)], { type: input.contentType }),
1172
- input.name
1173
- );
1174
- }
1175
- return this.transport.requestResponse("POST", path3, {
1176
- body: form,
1177
- headers: { Accept: "application/json" }
1178
- });
1179
- }
1180
- namespacePath(subpath) {
1181
- return `/v1/namespaces/${encodeURIComponent(this.namespace)}/${subpath.replace(/^\/+/, "")}`;
1182
- }
1183
- async existingApplicationPublicEndpointId(applicationName) {
1184
- const response = await this.transport.requestResponse(
1185
- "GET",
1186
- this.namespacePath(`applications/${encodeURIComponent(applicationName)}`),
1187
- { statusOnlyCodes: /* @__PURE__ */ new Set([404]) }
1188
- );
1189
- if (response.status === 404) {
1190
- return void 0;
1191
- }
1192
- const application = await parseJsonResponse(response);
1193
- return publicEndpointIdFromManifest(application);
1194
- }
1195
- platformProjectPath(resource, organizationId, projectId) {
1196
- const resolvedOrganizationId = organizationId ?? this.organizationId;
1197
- const resolvedProjectId = projectId ?? this.projectId;
1198
- if (!resolvedOrganizationId && !resolvedProjectId) {
1199
- return `/platform/v1/${resource}`;
1200
- }
1201
- if (!resolvedOrganizationId || !resolvedProjectId) {
1202
- throw new Error(
1203
- "organizationId and projectId must be provided together"
1204
- );
1205
- }
1206
- return `/platform/v1/organizations/${encodeURIComponent(resolvedOrganizationId)}/projects/${encodeURIComponent(resolvedProjectId)}/${resource}`;
1207
- }
1208
- secretCollectionPath(organizationId, projectId) {
1209
- const resolvedOrganizationId = organizationId ?? this.organizationId;
1210
- const resolvedProjectId = projectId ?? this.projectId;
1211
- if (!resolvedOrganizationId && !resolvedProjectId) {
1212
- return this.namespacePath("secrets");
1213
- }
1214
- if (!resolvedOrganizationId || !resolvedProjectId) {
1215
- throw new Error("organizationId and projectId must be provided together");
1216
- }
1217
- return this.namespacePath("secrets");
1218
- }
1219
- };
1220
- UNAUTHENTICATED_REQUESTS = "unauthenticated_requests";
1221
- }
1222
- });
1223
-
1224
46
  // src/image.ts
1225
47
  function cloneOperation(op) {
1226
48
  return {
@@ -1452,7 +274,7 @@ function nativePackageName(platform = process.platform, arch = process.arch, opt
1452
274
  function loadNative() {
1453
275
  const target = nativeTargetId();
1454
276
  const bindingPath = nativeBindingPath();
1455
- const require2 = (0, import_node_module2.createRequire)(importMetaUrl);
277
+ const require2 = (0, import_node_module.createRequire)(importMetaUrl);
1456
278
  if (fs.existsSync(bindingPath)) return require2(bindingPath);
1457
279
  const packageName = nativePackageName();
1458
280
  if (!packageName) {
@@ -1471,14 +293,14 @@ function loadNative() {
1471
293
  }
1472
294
  return require2(packageEntry);
1473
295
  }
1474
- var import_libc, fs, import_node_module2, import_node_path, import_node_url, NATIVE_PACKAGES, cachedLinuxLibc;
296
+ var import_libc, fs, import_node_module, import_node_path, import_node_url, NATIVE_PACKAGES, cachedLinuxLibc;
1475
297
  var init_native_binding = __esm({
1476
298
  "src/native-binding.ts"() {
1477
299
  "use strict";
1478
300
  init_cjs_shims();
1479
301
  import_libc = __toESM(require_libc(), 1);
1480
302
  fs = __toESM(require("fs"), 1);
1481
- import_node_module2 = require("module");
303
+ import_node_module = require("module");
1482
304
  import_node_path = __toESM(require("path"), 1);
1483
305
  import_node_url = require("url");
1484
306
  NATIVE_PACKAGES = {
@@ -1492,16 +314,284 @@ var init_native_binding = __esm({
1492
314
  }
1493
315
  });
1494
316
 
317
+ // src/enum.ts
318
+ function enumValue(values, value) {
319
+ return typeof value === "string" && Object.values(values).includes(value) ? value : values.UNKNOWN;
320
+ }
321
+ function withRaw(value, raw) {
322
+ return Object.defineProperty(value, "raw", { value: raw, enumerable: false, configurable: true });
323
+ }
324
+ var init_enum = __esm({
325
+ "src/enum.ts"() {
326
+ "use strict";
327
+ init_cjs_shims();
328
+ }
329
+ });
330
+
331
+ // src/image-builds.ts
332
+ function isConfirmedCancellation(outcome) {
333
+ return outcome === "cancelled" /* CANCELLED */ || outcome === "already_cancelled" /* ALREADY_CANCELLED */ || outcome === "already_failed" /* ALREADY_FAILED */;
334
+ }
335
+ function camelize(key) {
336
+ return key.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
337
+ }
338
+ function toImageBuildError(error) {
339
+ if (!(error instanceof Error)) return error;
340
+ let payload;
341
+ try {
342
+ payload = JSON.parse(error.message);
343
+ } catch {
344
+ return error;
345
+ }
346
+ if (!payload || payload.category !== "image_build") return error;
347
+ const details = {};
348
+ for (const [key, value] of Object.entries(payload)) {
349
+ if (key === "category") continue;
350
+ details[camelize(key)] = value;
351
+ }
352
+ details.code = enumValue(ImageBuildErrorCode, details.code || "internal" /* INTERNAL */);
353
+ if ("activeKind" in details) details.activeKind = details.activeKind ? enumValue(ImageBuildKind, details.activeKind) : null;
354
+ if ("activeStatus" in details) details.activeStatus = details.activeStatus ? enumValue(ImageBuildStatus, details.activeStatus) : null;
355
+ if ("outcome" in details) details.outcome = details.outcome ? enumValue(ImageBuildCancellationOutcome, details.outcome) : null;
356
+ if ("info" in details) details.info = buildInfoOrNull(details.info);
357
+ const typed = details;
358
+ const errors = {
359
+ not_found: ImageBuildNotFoundError,
360
+ image_build_in_progress: ImageBuildInProgressError,
361
+ failed: ImageBuildFailedError,
362
+ cancelled: ImageBuildCancelledError,
363
+ timeout: ImageBuildTimeoutError,
364
+ interrupted: ImageBuildInterruptedError
365
+ };
366
+ const ErrorClass = errors[typed.code] ?? ImageBuildError;
367
+ return withRaw(new ErrorClass(typed), payload);
368
+ }
369
+ function camelizeRecord(value) {
370
+ const out = {};
371
+ for (const [key, inner] of Object.entries(value)) out[camelize(key)] = inner;
372
+ return out;
373
+ }
374
+ function buildInfoOrNull(value) {
375
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
376
+ try {
377
+ return parseBuildInfo(value);
378
+ } catch (error) {
379
+ if (error instanceof ImageBuildError) return null;
380
+ throw error;
381
+ }
382
+ }
383
+ function decodeResponse(value) {
384
+ try {
385
+ const raw = typeof value === "string" ? JSON.parse(value) : value;
386
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) throw new TypeError("expected a response object");
387
+ return raw;
388
+ } catch (error) {
389
+ throw withRaw(new ImageBuildError({ code: "service" /* SERVICE */, message: `Invalid image-build response: ${String(error)}` }), { response: value });
390
+ }
391
+ }
392
+ function parseBuildInfo(value) {
393
+ const raw = decodeResponse(value);
394
+ if (raw.status == null) {
395
+ throw withRaw(new ImageBuildError({ code: "service" /* SERVICE */, message: "Invalid image-build response: missing status" }), { response: value });
396
+ }
397
+ const attempt = raw.attempt_no ?? 0;
398
+ const attemptNo = Number(attempt);
399
+ if (typeof attempt !== "number" && typeof attempt !== "string" || typeof attempt === "string" && attempt.trim() === "" || !Number.isSafeInteger(attemptNo)) {
400
+ throw withRaw(new ImageBuildError({ code: "service" /* SERVICE */, message: "Invalid image-build attempt_no" }), { response: value });
401
+ }
402
+ const camel = camelizeRecord(raw);
403
+ const result = raw.result && typeof raw.result === "object" ? camelizeRecord(raw.result) : null;
404
+ return withRaw({
405
+ buildId: String(raw.build_id ?? ""),
406
+ clientRequestId: camel.clientRequestId ?? null,
407
+ kind: raw.kind ? enumValue(ImageBuildKind, raw.kind) : null,
408
+ name: raw.name ?? null,
409
+ status: enumValue(ImageBuildStatus, raw.status),
410
+ phase: raw.phase ? enumValue(ImageBuildPhase, raw.phase) : null,
411
+ attemptNo,
412
+ builderSandboxId: camel.builderSandboxId ?? null,
413
+ error: raw.error ?? null,
414
+ result,
415
+ operationDeadlineMs: camel.operationDeadlineMs ?? null,
416
+ createdAtMs: camel.createdAtMs ?? null,
417
+ updatedAtMs: camel.updatedAtMs ?? null
418
+ }, raw);
419
+ }
420
+ async function __runWithInterrupt(signal, run) {
421
+ const binding = __imageBuildInternals.loadNativeBinding();
422
+ if (signal === void 0) {
423
+ try {
424
+ return await run(void 0);
425
+ } catch (error) {
426
+ throw toImageBuildError(error);
427
+ }
428
+ }
429
+ const interruptId = binding.createImageBuildInterrupt();
430
+ const onAbort = () => binding.triggerImageBuildInterrupt(interruptId);
431
+ if (signal.aborted) onAbort();
432
+ else signal.addEventListener("abort", onAbort, { once: true });
433
+ try {
434
+ return await run(interruptId);
435
+ } catch (error) {
436
+ throw toImageBuildError(error);
437
+ } finally {
438
+ signal.removeEventListener("abort", onAbort);
439
+ binding.releaseImageBuildInterrupt(interruptId);
440
+ }
441
+ }
442
+ var import_node_path2, import_node_os, import_node_fs, ImageBuildStatus, ImageBuildPhase, ImageBuildKind, ImageBuildCancellationOutcome, ImageBuildErrorCode, ImageBuildError, ImageBuildNotFoundError, ImageBuildInProgressError, ImageBuildFailedError, ImageBuildCancelledError, ImageBuildTimeoutError, ImageBuildInterruptedError;
443
+ var init_image_builds = __esm({
444
+ "src/image-builds.ts"() {
445
+ "use strict";
446
+ init_cjs_shims();
447
+ import_node_path2 = __toESM(require("path"), 1);
448
+ init_enum();
449
+ import_node_os = __toESM(require("os"), 1);
450
+ import_node_fs = require("fs");
451
+ init_image();
452
+ init_sandbox_image();
453
+ ImageBuildStatus = /* @__PURE__ */ ((ImageBuildStatus2) => {
454
+ ImageBuildStatus2["PENDING"] = "pending";
455
+ ImageBuildStatus2["RUNNING"] = "running";
456
+ ImageBuildStatus2["SUCCEEDED"] = "succeeded";
457
+ ImageBuildStatus2["FAILED"] = "failed";
458
+ ImageBuildStatus2["CANCELLED"] = "cancelled";
459
+ ImageBuildStatus2["UNKNOWN"] = "unknown";
460
+ return ImageBuildStatus2;
461
+ })(ImageBuildStatus || {});
462
+ ImageBuildPhase = /* @__PURE__ */ ((ImageBuildPhase2) => {
463
+ ImageBuildPhase2["AWAITING_CONTEXT"] = "awaiting_context";
464
+ ImageBuildPhase2["STARTING_BUILDER"] = "starting_builder";
465
+ ImageBuildPhase2["EXECUTING"] = "executing";
466
+ ImageBuildPhase2["SNAPSHOTTING"] = "snapshotting";
467
+ ImageBuildPhase2["PUBLISHING"] = "publishing";
468
+ ImageBuildPhase2["FINISHED"] = "finished";
469
+ ImageBuildPhase2["UNKNOWN"] = "unknown";
470
+ return ImageBuildPhase2;
471
+ })(ImageBuildPhase || {});
472
+ ImageBuildKind = /* @__PURE__ */ ((ImageBuildKind2) => {
473
+ ImageBuildKind2["DOCKERFILE"] = "dockerfile";
474
+ ImageBuildKind2["IMPORT"] = "import";
475
+ ImageBuildKind2["DIRECT"] = "direct";
476
+ ImageBuildKind2["UNKNOWN"] = "unknown";
477
+ return ImageBuildKind2;
478
+ })(ImageBuildKind || {});
479
+ ImageBuildCancellationOutcome = /* @__PURE__ */ ((ImageBuildCancellationOutcome2) => {
480
+ ImageBuildCancellationOutcome2["CANCELLED"] = "cancelled";
481
+ ImageBuildCancellationOutcome2["ALREADY_CANCELLED"] = "already_cancelled";
482
+ ImageBuildCancellationOutcome2["ALREADY_COMPLETED"] = "already_completed";
483
+ ImageBuildCancellationOutcome2["ALREADY_FAILED"] = "already_failed";
484
+ ImageBuildCancellationOutcome2["NOT_ADMITTED"] = "not_admitted";
485
+ ImageBuildCancellationOutcome2["UNCONFIRMED"] = "unconfirmed";
486
+ ImageBuildCancellationOutcome2["UNKNOWN"] = "unknown";
487
+ return ImageBuildCancellationOutcome2;
488
+ })(ImageBuildCancellationOutcome || {});
489
+ ImageBuildErrorCode = /* @__PURE__ */ ((ImageBuildErrorCode2) => {
490
+ ImageBuildErrorCode2["USAGE"] = "usage";
491
+ ImageBuildErrorCode2["AUTH"] = "auth";
492
+ ImageBuildErrorCode2["NOT_FOUND"] = "not_found";
493
+ ImageBuildErrorCode2["IMAGE_BUILD_IN_PROGRESS"] = "image_build_in_progress";
494
+ ImageBuildErrorCode2["CLIENT_REQUEST_ID_MISMATCH"] = "client_request_id_mismatch";
495
+ ImageBuildErrorCode2["FAILED"] = "failed";
496
+ ImageBuildErrorCode2["CANCELLED"] = "cancelled";
497
+ ImageBuildErrorCode2["TIMEOUT"] = "timeout";
498
+ ImageBuildErrorCode2["INTERRUPTED"] = "interrupted";
499
+ ImageBuildErrorCode2["SERVICE"] = "service";
500
+ ImageBuildErrorCode2["INTERNAL"] = "internal";
501
+ ImageBuildErrorCode2["UNKNOWN"] = "unknown";
502
+ return ImageBuildErrorCode2;
503
+ })(ImageBuildErrorCode || {});
504
+ ImageBuildError = class extends Error {
505
+ code;
506
+ buildId;
507
+ clientRequestId;
508
+ details;
509
+ constructor(details) {
510
+ super(details.message);
511
+ this.name = "ImageBuildError";
512
+ this.code = details.code;
513
+ this.details = { ...details };
514
+ withRaw(this, {});
515
+ if ("confirmed" in details) {
516
+ this.details.confirmed = details.confirmed === true && isConfirmedCancellation(details.outcome);
517
+ }
518
+ if (details.buildId) this.buildId = details.buildId;
519
+ if (details.clientRequestId) this.clientRequestId = details.clientRequestId;
520
+ }
521
+ };
522
+ ImageBuildNotFoundError = class extends ImageBuildError {
523
+ constructor(details) {
524
+ super(details);
525
+ this.name = "ImageBuildNotFoundError";
526
+ }
527
+ };
528
+ ImageBuildInProgressError = class extends ImageBuildError {
529
+ imageName;
530
+ activeBuildId;
531
+ activeKind;
532
+ activeStatus;
533
+ constructor(details) {
534
+ super(details);
535
+ this.name = "ImageBuildInProgressError";
536
+ if (details.imageName) this.imageName = details.imageName;
537
+ if (details.activeBuildId) this.activeBuildId = details.activeBuildId;
538
+ if (details.activeKind) this.activeKind = details.activeKind;
539
+ if (details.activeStatus) this.activeStatus = details.activeStatus;
540
+ }
541
+ };
542
+ ImageBuildFailedError = class extends ImageBuildError {
543
+ error;
544
+ info;
545
+ constructor(details) {
546
+ super(details);
547
+ this.name = "ImageBuildFailedError";
548
+ this.error = details.error ?? "no error recorded";
549
+ if (details.info) this.info = details.info;
550
+ }
551
+ };
552
+ ImageBuildCancelledError = class extends ImageBuildError {
553
+ info;
554
+ constructor(details) {
555
+ super(details);
556
+ this.name = "ImageBuildCancelledError";
557
+ if (details.info) this.info = details.info;
558
+ }
559
+ };
560
+ ImageBuildTimeoutError = class extends ImageBuildError {
561
+ constructor(details) {
562
+ super(details);
563
+ this.name = "ImageBuildTimeoutError";
564
+ }
565
+ };
566
+ ImageBuildInterruptedError = class extends ImageBuildError {
567
+ outcome;
568
+ confirmed;
569
+ result;
570
+ constructor(details) {
571
+ super(details);
572
+ this.name = "ImageBuildInterruptedError";
573
+ this.outcome = details.outcome ?? "unconfirmed" /* UNCONFIRMED */;
574
+ this.confirmed = this.details.confirmed === true;
575
+ if (details.result) this.result = details.result;
576
+ }
577
+ };
578
+ }
579
+ });
580
+
1495
581
  // src/sandbox-image.ts
1496
582
  var sandbox_image_exports = {};
1497
583
  __export(sandbox_image_exports, {
584
+ __imageBuildInternals: () => __imageBuildInternals,
1498
585
  __setNativeBindingForTest: () => __setNativeBindingForTest,
1499
586
  buildContextFromEnv: () => buildContextFromEnv,
1500
587
  createSandboxImage: () => createSandboxImage,
1501
588
  deleteSandboxImage: () => deleteSandboxImage,
589
+ deleteSandboxImageWithCredentials: () => deleteSandboxImageWithCredentials,
1502
590
  findSandboxImageByName: () => findSandboxImageByName,
591
+ findSandboxImageByNameWithCredentials: () => findSandboxImageByNameWithCredentials,
1503
592
  importSandboxImage: () => importSandboxImage,
1504
593
  listSandboxImages: () => listSandboxImages,
594
+ listSandboxImagesWithCredentials: () => listSandboxImagesWithCredentials,
1505
595
  runCreateSandboxImageCli: () => runCreateSandboxImageCli,
1506
596
  runImportSandboxImageCli: () => runImportSandboxImageCli
1507
597
  });
@@ -1538,9 +628,9 @@ function buildContextFromEnv() {
1538
628
  };
1539
629
  }
1540
630
  function defaultRegisteredName(dockerfilePath) {
1541
- const parsed = import_node_path2.default.parse(dockerfilePath);
631
+ const parsed = import_node_path3.default.parse(dockerfilePath);
1542
632
  if (parsed.name.toLowerCase() === "dockerfile") {
1543
- const parentName = import_node_path2.default.basename(import_node_path2.default.dirname(dockerfilePath)).trim();
633
+ const parentName = import_node_path3.default.basename(import_node_path3.default.dirname(dockerfilePath)).trim();
1544
634
  return parentName || "sandbox-image";
1545
635
  }
1546
636
  return parsed.name || "sandbox-image";
@@ -1576,6 +666,15 @@ function eventToEmitDict(event) {
1576
666
  message: event.message
1577
667
  };
1578
668
  if (event.stream != null) out.stream = event.stream;
669
+ if (event.buildId != null) out.build_id = event.buildId;
670
+ if (event.clientRequestId !== void 0 && event.eventType !== "status") {
671
+ out.client_request_id = event.clientRequestId;
672
+ }
673
+ if (event.status != null) out.status = event.status;
674
+ if (event.phase !== void 0 && event.eventType.startsWith("build_")) out.phase = event.phase;
675
+ if (event.attempt != null) out.attempt = event.attempt;
676
+ if (event.outcome != null) out.outcome = event.outcome;
677
+ if (event.confirmed != null) out.confirmed = event.confirmed;
1579
678
  return out;
1580
679
  }
1581
680
  function runOpMountsContext(op) {
@@ -1630,24 +729,24 @@ async function createSandboxImage(source, options = {}, deps = {}) {
1630
729
  }
1631
730
  let resolvedContext;
1632
731
  if (options.contextDir != null) {
1633
- resolvedContext = import_node_path2.default.resolve(options.contextDir);
732
+ resolvedContext = import_node_path3.default.resolve(options.contextDir);
1634
733
  } else if (imageRequiresContext(source)) {
1635
734
  throw new Error(
1636
735
  "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>`."
1637
736
  );
1638
737
  } else {
1639
- tempContextDir = (0, import_node_fs.mkdtempSync)(import_node_path2.default.join(import_node_os.default.tmpdir(), "tl-build-context-"));
738
+ tempContextDir = (0, import_node_fs2.mkdtempSync)(import_node_path3.default.join(import_node_os2.default.tmpdir(), "tl-build-context-"));
1640
739
  resolvedContext = tempContextDir;
1641
740
  }
1642
- dockerfilePath = import_node_path2.default.join(resolvedContext, "Dockerfile");
741
+ dockerfilePath = import_node_path3.default.join(resolvedContext, "Dockerfile");
1643
742
  let text = dockerfileContent(source);
1644
743
  if (!text.endsWith("\n")) text += "\n";
1645
744
  dockerfileText = text;
1646
745
  nativeContextDir = resolvedContext;
1647
746
  effectiveName = options.registeredName ?? source.name;
1648
747
  } else if (typeof source === "string") {
1649
- const resolvedPath = import_node_path2.default.resolve(source);
1650
- if (!(0, import_node_fs.existsSync)(resolvedPath)) {
748
+ const resolvedPath = import_node_path3.default.resolve(source);
749
+ if (!(0, import_node_fs2.existsSync)(resolvedPath)) {
1651
750
  throw new Error(`Dockerfile not found: ${source}`);
1652
751
  }
1653
752
  dockerfilePath = resolvedPath;
@@ -1677,38 +776,47 @@ async function createSandboxImage(source, options = {}, deps = {}) {
1677
776
  deps._allowPat ? "Missing TENSORLAKE_API_KEY or TENSORLAKE_PAT credentials." : "Missing TENSORLAKE_API_KEY credentials."
1678
777
  );
1679
778
  }
779
+ if (options.signal !== void 0 && !options.cas) {
780
+ throw new Error(
781
+ "signal is only supported for CAS image builds (cas: true); a legacy build has no Image Service build operation to cancel"
782
+ );
783
+ }
1680
784
  emit({ type: "status", message: `Building image '${effectiveName}'...` });
1681
785
  const binding = loadNativeBinding();
1682
786
  let emitError;
1683
- const resultJson = await binding.buildSandboxImage(
1684
- {
1685
- apiUrl: context.apiUrl,
1686
- bearerToken,
1687
- dockerfilePath,
1688
- registeredName: effectiveName,
1689
- diskMb: options.diskMb,
1690
- builderDiskMb: options.builderDiskMb,
1691
- cpus: options.cpus,
1692
- memoryMb: options.memoryMb,
1693
- isPublic: options.isPublic ?? false,
1694
- organizationId: usePat ? context.organizationId : void 0,
1695
- projectId: usePat ? context.projectId : void 0,
1696
- namespace: context.namespace,
1697
- useScopeHeaders: usePat,
1698
- userAgent: void 0,
1699
- dockerCompat: options.dockerCompat ?? false,
1700
- dockerConfigJson: options.dockerConfigJson,
1701
- dockerfileText,
1702
- contextDir: nativeContextDir
1703
- },
1704
- (event) => {
1705
- try {
1706
- emit(eventToEmitDict(event));
1707
- } catch (error) {
1708
- emitError ??= error;
1709
- }
787
+ const nativeOptions = {
788
+ apiUrl: context.apiUrl,
789
+ bearerToken,
790
+ dockerfilePath,
791
+ registeredName: effectiveName,
792
+ diskMb: options.diskMb,
793
+ builderDiskMb: options.builderDiskMb,
794
+ cpus: options.cpus,
795
+ memoryMb: options.memoryMb,
796
+ isPublic: options.isPublic ?? false,
797
+ organizationId: usePat ? context.organizationId : void 0,
798
+ projectId: usePat ? context.projectId : void 0,
799
+ namespace: context.namespace,
800
+ useScopeHeaders: usePat,
801
+ userAgent: void 0,
802
+ dockerCompat: options.dockerCompat ?? false,
803
+ dockerConfigJson: options.dockerConfigJson,
804
+ dockerfileText,
805
+ contextDir: nativeContextDir,
806
+ cas: options.cas ?? false,
807
+ buildArgs: options.buildArgs
808
+ };
809
+ const forward = (event) => {
810
+ try {
811
+ emit(eventToEmitDict(event));
812
+ } catch (error) {
813
+ emitError ??= error;
1710
814
  }
1711
- );
815
+ };
816
+ const resultJson = options.cas ? await __runWithInterrupt(
817
+ options.signal,
818
+ (interruptId) => binding.buildSandboxImage(nativeOptions, forward, interruptId)
819
+ ) : await binding.buildSandboxImage(nativeOptions, forward);
1712
820
  if (emitError != null) {
1713
821
  throw emitError;
1714
822
  }
@@ -1725,7 +833,7 @@ async function createSandboxImage(source, options = {}, deps = {}) {
1725
833
  return result;
1726
834
  } finally {
1727
835
  if (tempContextDir != null) {
1728
- (0, import_node_fs.rmSync)(tempContextDir, { recursive: true, force: true });
836
+ (0, import_node_fs2.rmSync)(tempContextDir, { recursive: true, force: true });
1729
837
  }
1730
838
  }
1731
839
  }
@@ -1754,39 +862,47 @@ async function importSandboxImage(imageReference, options = {}, deps = {}) {
1754
862
  deps._allowPat ? "Missing TENSORLAKE_API_KEY or TENSORLAKE_PAT credentials." : "Missing TENSORLAKE_API_KEY credentials."
1755
863
  );
1756
864
  }
865
+ if (options.signal !== void 0 && !options.cas) {
866
+ throw new Error(
867
+ "signal is only supported for CAS image imports (cas: true); a legacy import has no Image Service build operation to cancel"
868
+ );
869
+ }
1757
870
  emit({
1758
871
  type: "status",
1759
872
  message: `Importing image '${reference}' as '${effectiveName}'...`
1760
873
  });
1761
874
  const binding = loadNativeBinding();
1762
875
  let emitError;
1763
- const resultJson = await binding.importSandboxImage(
1764
- {
1765
- apiUrl: context.apiUrl,
1766
- bearerToken,
1767
- imageReference: reference,
1768
- registeredName: effectiveName,
1769
- diskMb: options.diskMb,
1770
- builderDiskMb: options.builderDiskMb,
1771
- cpus: options.cpus,
1772
- memoryMb: options.memoryMb,
1773
- isPublic: options.isPublic ?? false,
1774
- organizationId: usePat ? context.organizationId : void 0,
1775
- projectId: usePat ? context.projectId : void 0,
1776
- namespace: context.namespace,
1777
- useScopeHeaders: usePat,
1778
- userAgent: void 0,
1779
- dockerCompat: options.dockerCompat ?? false,
1780
- dockerConfigJson: options.dockerConfigJson
1781
- },
1782
- (event) => {
1783
- try {
1784
- emit(eventToEmitDict(event));
1785
- } catch (error) {
1786
- emitError ??= error;
1787
- }
876
+ const nativeOptions = {
877
+ apiUrl: context.apiUrl,
878
+ bearerToken,
879
+ imageReference: reference,
880
+ registeredName: effectiveName,
881
+ diskMb: options.diskMb,
882
+ builderDiskMb: options.builderDiskMb,
883
+ cpus: options.cpus,
884
+ memoryMb: options.memoryMb,
885
+ isPublic: options.isPublic ?? false,
886
+ organizationId: usePat ? context.organizationId : void 0,
887
+ projectId: usePat ? context.projectId : void 0,
888
+ namespace: context.namespace,
889
+ useScopeHeaders: usePat,
890
+ userAgent: void 0,
891
+ dockerCompat: options.dockerCompat ?? false,
892
+ dockerConfigJson: options.dockerConfigJson,
893
+ cas: options.cas ?? false
894
+ };
895
+ const forward = (event) => {
896
+ try {
897
+ emit(eventToEmitDict(event));
898
+ } catch (error) {
899
+ emitError ??= error;
1788
900
  }
1789
- );
901
+ };
902
+ const resultJson = options.cas ? await __runWithInterrupt(
903
+ options.signal,
904
+ (interruptId) => binding.importSandboxImage(nativeOptions, forward, interruptId)
905
+ ) : await binding.importSandboxImage(nativeOptions, forward);
1790
906
  if (emitError != null) {
1791
907
  throw emitError;
1792
908
  }
@@ -1802,10 +918,7 @@ async function importSandboxImage(imageReference, options = {}, deps = {}) {
1802
918
  emit({ type: "done" });
1803
919
  return result;
1804
920
  }
1805
- async function deleteSandboxImage(imageName) {
1806
- if (typeof imageName !== "string" || imageName.length === 0) {
1807
- throw new TypeError("imageName must be a non-empty string");
1808
- }
921
+ function catalogOptionsFromEnv() {
1809
922
  const context = buildContextFromEnv();
1810
923
  const bearerToken = context.apiKey;
1811
924
  if (!bearerToken) {
@@ -1816,63 +929,73 @@ async function deleteSandboxImage(imageName) {
1816
929
  }
1817
930
  throw new Error("Missing TENSORLAKE_API_KEY credentials.");
1818
931
  }
1819
- const client = new CloudClient({
1820
- apiUrl: context.apiUrl,
1821
- apiKey: bearerToken,
1822
- namespace: context.namespace
1823
- });
1824
- try {
1825
- await client.deleteSandboxImage(imageName);
1826
- } finally {
1827
- client.close();
1828
- }
932
+ return { apiUrl: context.apiUrl, bearerToken, useScopeHeaders: false };
1829
933
  }
1830
- async function findSandboxImageByName(imageName) {
1831
- if (typeof imageName !== "string" || imageName.length === 0) {
1832
- throw new TypeError("imageName must be a non-empty string");
1833
- }
934
+ function catalogOptionsFromCredentials(credentials) {
1834
935
  const context = buildContextFromEnv();
1835
- const bearerToken = context.apiKey;
936
+ const bearerToken = credentials.apiKey ?? context.apiKey;
1836
937
  if (!bearerToken) {
1837
- if (context.personalAccessToken) {
1838
- throw new Error(
1839
- "Sandbox image SDKs require TENSORLAKE_API_KEY. Personal access tokens are CLI-only."
1840
- );
1841
- }
1842
938
  throw new Error("Missing TENSORLAKE_API_KEY credentials.");
1843
939
  }
1844
- const client = new CloudClient({
1845
- apiUrl: context.apiUrl,
1846
- apiKey: bearerToken,
1847
- namespace: context.namespace
1848
- });
1849
- try {
1850
- return await client.findSandboxImageByName(imageName);
1851
- } finally {
1852
- client.close();
940
+ const { organizationId, projectId } = credentials;
941
+ if (organizationId === void 0 !== (projectId === void 0)) {
942
+ throw new TypeError("organizationId and projectId must be given together");
1853
943
  }
944
+ return {
945
+ apiUrl: credentials.apiUrl ?? context.apiUrl,
946
+ bearerToken,
947
+ organizationId,
948
+ projectId,
949
+ useScopeHeaders: organizationId !== void 0
950
+ };
1854
951
  }
1855
- async function listSandboxImages() {
1856
- const context = buildContextFromEnv();
1857
- const bearerToken = context.apiKey;
1858
- if (!bearerToken) {
1859
- if (context.personalAccessToken) {
1860
- throw new Error(
1861
- "Sandbox image SDKs require TENSORLAKE_API_KEY. Personal access tokens are CLI-only."
1862
- );
1863
- }
1864
- throw new Error("Missing TENSORLAKE_API_KEY credentials.");
952
+ function parseTemplate(json) {
953
+ return JSON.parse(json);
954
+ }
955
+ async function deleteSandboxImage(imageName) {
956
+ if (typeof imageName !== "string" || imageName.length === 0) {
957
+ throw new TypeError("imageName must be a non-empty string");
1865
958
  }
1866
- const client = new CloudClient({
1867
- apiUrl: context.apiUrl,
1868
- apiKey: bearerToken,
1869
- namespace: context.namespace
1870
- });
1871
- try {
1872
- return await client.listSandboxImages();
1873
- } finally {
1874
- client.close();
959
+ await loadNativeBinding().deleteSandboxImage(catalogOptionsFromEnv(), imageName);
960
+ }
961
+ async function deleteSandboxImageWithCredentials(credentials, imageName) {
962
+ if (typeof imageName !== "string" || imageName.length === 0) {
963
+ throw new TypeError("imageName must be a non-empty string");
964
+ }
965
+ await loadNativeBinding().deleteSandboxImage(
966
+ catalogOptionsFromCredentials(credentials),
967
+ imageName
968
+ );
969
+ }
970
+ async function findSandboxImageByName(imageName) {
971
+ if (typeof imageName !== "string" || imageName.length === 0) {
972
+ throw new TypeError("imageName must be a non-empty string");
973
+ }
974
+ const json = await loadNativeBinding().findSandboxImage(
975
+ catalogOptionsFromEnv(),
976
+ imageName
977
+ );
978
+ return json == null ? null : parseTemplate(json);
979
+ }
980
+ async function findSandboxImageByNameWithCredentials(credentials, imageName) {
981
+ if (typeof imageName !== "string" || imageName.length === 0) {
982
+ throw new TypeError("imageName must be a non-empty string");
1875
983
  }
984
+ const json = await loadNativeBinding().findSandboxImage(
985
+ catalogOptionsFromCredentials(credentials),
986
+ imageName
987
+ );
988
+ return json == null ? null : parseTemplate(json);
989
+ }
990
+ async function listSandboxImages() {
991
+ const json = await loadNativeBinding().listSandboxImages(catalogOptionsFromEnv());
992
+ return JSON.parse(json);
993
+ }
994
+ async function listSandboxImagesWithCredentials(credentials) {
995
+ const json = await loadNativeBinding().listSandboxImages(
996
+ catalogOptionsFromCredentials(credentials)
997
+ );
998
+ return JSON.parse(json);
1876
999
  }
1877
1000
  async function runCreateSandboxImageCli(argv = process.argv.slice(2)) {
1878
1001
  const parsed = (0, import_node_util.parseArgs)({
@@ -1982,30 +1105,44 @@ async function runImportSandboxImageCli(argv = process.argv.slice(2)) {
1982
1105
  { emit: ndjsonStdoutEmit, _allowPat: true }
1983
1106
  );
1984
1107
  }
1985
- var import_node_path2, import_node_os, import_node_fs, import_node_util, cachedNativeBinding, cachedNativeBindingError, DEFAULT_IMAGE_NAME2;
1108
+ var import_node_path3, import_node_os2, import_node_fs2, import_node_util, cachedNativeBinding, cachedNativeBindingError, DEFAULT_IMAGE_NAME2, __imageBuildInternals;
1986
1109
  var init_sandbox_image = __esm({
1987
1110
  "src/sandbox-image.ts"() {
1988
1111
  init_cjs_shims();
1989
- import_node_path2 = __toESM(require("path"), 1);
1990
- import_node_os = __toESM(require("os"), 1);
1991
- import_node_fs = require("fs");
1112
+ import_node_path3 = __toESM(require("path"), 1);
1113
+ import_node_os2 = __toESM(require("os"), 1);
1114
+ import_node_fs2 = require("fs");
1992
1115
  import_node_util = require("util");
1993
- init_cloud_client();
1994
1116
  init_image();
1995
1117
  init_native_binding();
1118
+ init_image_builds();
1996
1119
  DEFAULT_IMAGE_NAME2 = "default";
1120
+ __imageBuildInternals = {
1121
+ loadNativeBinding: () => loadNativeBinding(),
1122
+ buildContextFromEnv: () => buildContextFromEnv(),
1123
+ stderrEmit: (event) => stderrEmit(event),
1124
+ noopEmit: (event) => noopEmit(event),
1125
+ eventToEmitDict: (event) => eventToEmitDict(event),
1126
+ imageRequiresContext: (image) => imageRequiresContext(image),
1127
+ defaultRegisteredName: (dockerfilePath) => defaultRegisteredName(dockerfilePath),
1128
+ defaultRegisteredNameFromImage: (reference) => defaultRegisteredNameFromImage(reference)
1129
+ };
1997
1130
  }
1998
1131
  });
1999
1132
  init_sandbox_image();
2000
1133
  // Annotate the CommonJS export names for ESM import in node:
2001
1134
  0 && (module.exports = {
1135
+ __imageBuildInternals,
2002
1136
  __setNativeBindingForTest,
2003
1137
  buildContextFromEnv,
2004
1138
  createSandboxImage,
2005
1139
  deleteSandboxImage,
1140
+ deleteSandboxImageWithCredentials,
2006
1141
  findSandboxImageByName,
1142
+ findSandboxImageByNameWithCredentials,
2007
1143
  importSandboxImage,
2008
1144
  listSandboxImages,
1145
+ listSandboxImagesWithCredentials,
2009
1146
  runCreateSandboxImageCli,
2010
1147
  runImportSandboxImageCli
2011
1148
  });