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