@tensorlakeai/tensorlake 0.5.151 → 0.5.153
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/README.md +8 -0
- package/dist/applications/index.cjs +3510 -3384
- 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 +3286 -3160
- package/dist/applications/index.js.map +1 -1
- package/dist/function-agent/main.cjs +1 -1
- package/dist/function-agent/main.cjs.map +1 -1
- package/dist/function-agent/main.js +1 -1
- package/dist/function-agent/main.js.map +1 -1
- package/dist/function-executor/main.cjs +2 -2
- package/dist/function-executor/main.cjs.map +1 -1
- package/dist/function-executor/main.js +2 -2
- package/dist/function-executor/main.js.map +1 -1
- package/dist/index.cjs +1424 -1079
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +313 -27
- package/dist/index.d.ts +313 -27
- package/dist/index.js +1401 -1069
- 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 +339 -1295
- 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 +338 -1294
- package/dist/sandbox-image.js.map +1 -1
- package/package.json +8 -7
- package/runtime/function-executor/manifest.json +7 -7
- package/runtime/function-executor/package/dist/function-executor/main.js +2 -2
- package/runtime/function-executor/package/dist/function-executor/main.js.map +1 -1
- 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 +7 -7
- package/runtime/typescript-function-runner/package/dist/function-agent/main.js +1 -1
- package/runtime/typescript-function-runner/package/dist/function-agent/main.js.map +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/index.js
CHANGED
|
@@ -46,7 +46,7 @@ var init_defaults = __esm({
|
|
|
46
46
|
"src/defaults.ts"() {
|
|
47
47
|
"use strict";
|
|
48
48
|
init_esm_shims();
|
|
49
|
-
SDK_VERSION = "0.5.
|
|
49
|
+
SDK_VERSION = "0.5.153";
|
|
50
50
|
API_URL = process.env.TENSORLAKE_API_URL ?? "https://api.tensorlake.ai";
|
|
51
51
|
API_KEY = process.env.TENSORLAKE_API_KEY ?? void 0;
|
|
52
52
|
NAMESPACE = process.env.INDEXIFY_NAMESPACE ?? "default";
|
|
@@ -313,6 +313,11 @@ function createWorkerBinding(runtime) {
|
|
|
313
313
|
return runtime.handle("NativeRepositoryClient", args);
|
|
314
314
|
}
|
|
315
315
|
},
|
|
316
|
+
NativeTcpTunnel: class {
|
|
317
|
+
constructor() {
|
|
318
|
+
return runtime.handle("NativeTcpTunnel", []);
|
|
319
|
+
}
|
|
320
|
+
},
|
|
316
321
|
validateManagedName: (name) => runtime.call(void 0, "validateManagedName", [name])
|
|
317
322
|
};
|
|
318
323
|
}
|
|
@@ -490,7 +495,7 @@ var init_native_worker_client = __esm({
|
|
|
490
495
|
}
|
|
491
496
|
};
|
|
492
497
|
runtimeKey = /* @__PURE__ */ Symbol.for(
|
|
493
|
-
`tensorlake.native.worker.${false ? "source" : "0.5.
|
|
498
|
+
`tensorlake.native.worker.${false ? "source" : "0.5.153"}.v1`
|
|
494
499
|
);
|
|
495
500
|
runtimes = globalThis;
|
|
496
501
|
}
|
|
@@ -590,6 +595,8 @@ var init_models = __esm({
|
|
|
590
595
|
SnapshotStatus2["LOCAL_READY"] = "local_ready";
|
|
591
596
|
SnapshotStatus2["COMPLETED"] = "completed";
|
|
592
597
|
SnapshotStatus2["FAILED"] = "failed";
|
|
598
|
+
SnapshotStatus2["DELETING"] = "deleting";
|
|
599
|
+
SnapshotStatus2["REPLICATING"] = "replicating";
|
|
593
600
|
return SnapshotStatus2;
|
|
594
601
|
})(SnapshotStatus || {});
|
|
595
602
|
ProcessStatus = /* @__PURE__ */ ((ProcessStatus2) => {
|
|
@@ -862,7 +869,6 @@ var init_pending_sandbox = __esm({
|
|
|
862
869
|
});
|
|
863
870
|
|
|
864
871
|
// src/tunnel.ts
|
|
865
|
-
import * as net from "net";
|
|
866
872
|
import WebSocket from "ws";
|
|
867
873
|
async function openTunnelWebSocket(options) {
|
|
868
874
|
const wsUrl = buildTunnelWsUrl(options.baseUrl, options.remotePort);
|
|
@@ -940,116 +946,6 @@ function normalizeWebSocketData(message) {
|
|
|
940
946
|
}
|
|
941
947
|
return Buffer.from(message);
|
|
942
948
|
}
|
|
943
|
-
async function relaySocket(localSocket, websocket) {
|
|
944
|
-
return new Promise((resolve2) => {
|
|
945
|
-
let settled = false;
|
|
946
|
-
const keepAliveInterval = setInterval(() => {
|
|
947
|
-
if (websocket.readyState === WebSocket.OPEN) {
|
|
948
|
-
websocket.ping();
|
|
949
|
-
}
|
|
950
|
-
}, WEBSOCKET_KEEPALIVE_INTERVAL_MS);
|
|
951
|
-
keepAliveInterval.unref?.();
|
|
952
|
-
const finish = () => {
|
|
953
|
-
if (settled) return;
|
|
954
|
-
settled = true;
|
|
955
|
-
clearInterval(keepAliveInterval);
|
|
956
|
-
cleanup();
|
|
957
|
-
resolve2();
|
|
958
|
-
};
|
|
959
|
-
const cleanup = () => {
|
|
960
|
-
localSocket.removeListener("data", onLocalData);
|
|
961
|
-
localSocket.removeListener("end", onLocalEnd);
|
|
962
|
-
localSocket.removeListener("close", onLocalClose);
|
|
963
|
-
localSocket.removeListener("error", onLocalError);
|
|
964
|
-
websocket.removeListener("message", onWsMessage);
|
|
965
|
-
websocket.removeListener("close", onWsClose);
|
|
966
|
-
websocket.removeListener("error", onWsError);
|
|
967
|
-
websocket.removeListener("ping", onWsPing);
|
|
968
|
-
};
|
|
969
|
-
const onLocalData = (chunk) => {
|
|
970
|
-
if (websocket.readyState !== WebSocket.OPEN) {
|
|
971
|
-
localSocket.destroy();
|
|
972
|
-
return;
|
|
973
|
-
}
|
|
974
|
-
websocket.send(chunk, { binary: true }, (error) => {
|
|
975
|
-
if (error) {
|
|
976
|
-
localSocket.destroy(error);
|
|
977
|
-
}
|
|
978
|
-
});
|
|
979
|
-
};
|
|
980
|
-
const onLocalEnd = () => {
|
|
981
|
-
if (websocket.readyState === WebSocket.OPEN) {
|
|
982
|
-
websocket.close();
|
|
983
|
-
}
|
|
984
|
-
};
|
|
985
|
-
const onLocalClose = () => {
|
|
986
|
-
if (websocket.readyState === WebSocket.OPEN || websocket.readyState === WebSocket.CONNECTING) {
|
|
987
|
-
websocket.close();
|
|
988
|
-
}
|
|
989
|
-
finish();
|
|
990
|
-
};
|
|
991
|
-
const onLocalError = () => {
|
|
992
|
-
websocket.close();
|
|
993
|
-
finish();
|
|
994
|
-
};
|
|
995
|
-
const onWsMessage = (message, isBinary) => {
|
|
996
|
-
if (!isBinary) {
|
|
997
|
-
localSocket.destroy(
|
|
998
|
-
new SandboxError("received unexpected text frame from tunnel")
|
|
999
|
-
);
|
|
1000
|
-
websocket.close();
|
|
1001
|
-
return;
|
|
1002
|
-
}
|
|
1003
|
-
const payload = normalizeWebSocketData(message);
|
|
1004
|
-
if (!localSocket.destroyed) {
|
|
1005
|
-
localSocket.write(payload);
|
|
1006
|
-
}
|
|
1007
|
-
};
|
|
1008
|
-
const onWsClose = () => {
|
|
1009
|
-
if (!localSocket.destroyed) {
|
|
1010
|
-
localSocket.end();
|
|
1011
|
-
}
|
|
1012
|
-
finish();
|
|
1013
|
-
};
|
|
1014
|
-
const onWsError = (error) => {
|
|
1015
|
-
localSocket.destroy(error);
|
|
1016
|
-
finish();
|
|
1017
|
-
};
|
|
1018
|
-
const onWsPing = (data) => {
|
|
1019
|
-
if (websocket.readyState === WebSocket.OPEN) {
|
|
1020
|
-
websocket.pong(data, false, () => {
|
|
1021
|
-
});
|
|
1022
|
-
}
|
|
1023
|
-
};
|
|
1024
|
-
localSocket.on("data", onLocalData);
|
|
1025
|
-
localSocket.on("end", onLocalEnd);
|
|
1026
|
-
localSocket.on("close", onLocalClose);
|
|
1027
|
-
localSocket.on("error", onLocalError);
|
|
1028
|
-
websocket.on("message", onWsMessage);
|
|
1029
|
-
websocket.on("close", onWsClose);
|
|
1030
|
-
websocket.on("error", onWsError);
|
|
1031
|
-
websocket.on("ping", onWsPing);
|
|
1032
|
-
});
|
|
1033
|
-
}
|
|
1034
|
-
async function listenServer(server, localPort, localHost) {
|
|
1035
|
-
await new Promise((resolve2, reject) => {
|
|
1036
|
-
const onError = (error) => {
|
|
1037
|
-
server.removeListener("listening", onListening);
|
|
1038
|
-
reject(
|
|
1039
|
-
new SandboxError(
|
|
1040
|
-
`failed to bind local tunnel listener on ${localHost}:${localPort}: ${error.message}`
|
|
1041
|
-
)
|
|
1042
|
-
);
|
|
1043
|
-
};
|
|
1044
|
-
const onListening = () => {
|
|
1045
|
-
server.removeListener("error", onError);
|
|
1046
|
-
resolve2();
|
|
1047
|
-
};
|
|
1048
|
-
server.once("error", onError);
|
|
1049
|
-
server.once("listening", onListening);
|
|
1050
|
-
server.listen(localPort, localHost);
|
|
1051
|
-
});
|
|
1052
|
-
}
|
|
1053
949
|
function validatePort(port, label, allowZero = false) {
|
|
1054
950
|
if (!Number.isInteger(port)) {
|
|
1055
951
|
throw new SandboxError(`${label} must be an integer, got ${port}`);
|
|
@@ -1088,6 +984,8 @@ var init_tunnel = __esm({
|
|
|
1088
984
|
"use strict";
|
|
1089
985
|
init_esm_shims();
|
|
1090
986
|
init_errors();
|
|
987
|
+
init_native_sandbox();
|
|
988
|
+
init_native_worker_client();
|
|
1091
989
|
DEFAULT_TUNNEL_CONNECT_TIMEOUT_MS = 1e4;
|
|
1092
990
|
WEBSOCKET_KEEPALIVE_INTERVAL_MS = 15e3;
|
|
1093
991
|
TunnelByteStream = class _TunnelByteStream {
|
|
@@ -1217,24 +1115,17 @@ var init_tunnel = __esm({
|
|
|
1217
1115
|
}
|
|
1218
1116
|
};
|
|
1219
1117
|
TcpTunnel = class _TcpTunnel {
|
|
1220
|
-
remotePort
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
closePromise = null;
|
|
1229
|
-
constructor(options) {
|
|
1230
|
-
this.baseUrl = options.baseUrl;
|
|
1231
|
-
this.wsHeaders = options.wsHeaders;
|
|
1232
|
-
this.remotePort = options.remotePort;
|
|
1233
|
-
this.localHost = options.localHost;
|
|
1234
|
-
this.localPort = options.localPort;
|
|
1235
|
-
this.server = options.server;
|
|
1236
|
-
this.connectTimeoutMs = options.connectTimeoutMs;
|
|
1118
|
+
constructor(native, remotePort, localHost, localPort) {
|
|
1119
|
+
this.native = native;
|
|
1120
|
+
this.remotePort = remotePort;
|
|
1121
|
+
this.localHost = localHost;
|
|
1122
|
+
this.localPort = localPort;
|
|
1123
|
+
this.lifetime = native.waitClosed();
|
|
1124
|
+
void this.lifetime.catch(() => {
|
|
1125
|
+
});
|
|
1237
1126
|
}
|
|
1127
|
+
closePromise = null;
|
|
1128
|
+
lifetime;
|
|
1238
1129
|
static async listen(options) {
|
|
1239
1130
|
const remotePort = validatePort(options.remotePort, "remote port");
|
|
1240
1131
|
const localHost = options.localHost ?? "127.0.0.1";
|
|
@@ -1243,69 +1134,37 @@ var init_tunnel = __esm({
|
|
|
1243
1134
|
"local port",
|
|
1244
1135
|
true
|
|
1245
1136
|
);
|
|
1246
|
-
const
|
|
1247
|
-
const
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
void tunnel.handleConnection(localSocket);
|
|
1265
|
-
});
|
|
1266
|
-
return tunnel;
|
|
1137
|
+
const timeout = secondsToMillis(options.connectTimeout ?? 10) / 1e3;
|
|
1138
|
+
const native = new (loadNativeSandboxBinding()).NativeTcpTunnel();
|
|
1139
|
+
try {
|
|
1140
|
+
const port = await callNative(
|
|
1141
|
+
() => native.listen(
|
|
1142
|
+
options.baseUrl,
|
|
1143
|
+
options.wsHeaders,
|
|
1144
|
+
remotePort,
|
|
1145
|
+
localHost,
|
|
1146
|
+
localPort,
|
|
1147
|
+
timeout
|
|
1148
|
+
)
|
|
1149
|
+
);
|
|
1150
|
+
return new _TcpTunnel(native, remotePort, localHost, port);
|
|
1151
|
+
} catch (error) {
|
|
1152
|
+
releaseNativeHandle(native);
|
|
1153
|
+
throw error;
|
|
1154
|
+
}
|
|
1267
1155
|
}
|
|
1268
1156
|
address() {
|
|
1269
1157
|
return { host: this.localHost, port: this.localPort };
|
|
1270
1158
|
}
|
|
1271
1159
|
async close() {
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
this.server.close((error) => {
|
|
1281
|
-
if (error) {
|
|
1282
|
-
reject(new SandboxError(`failed to close tunnel listener: ${error.message}`));
|
|
1283
|
-
return;
|
|
1284
|
-
}
|
|
1285
|
-
resolve2();
|
|
1286
|
-
});
|
|
1287
|
-
});
|
|
1288
|
-
return this.closePromise;
|
|
1289
|
-
}
|
|
1290
|
-
async handleConnection(localSocket) {
|
|
1291
|
-
localSocket.setNoDelay(true);
|
|
1292
|
-
const relay = { localSocket, websocket: null };
|
|
1293
|
-
this.activeRelays.add(relay);
|
|
1294
|
-
try {
|
|
1295
|
-
relay.websocket = await openTunnelWebSocket({
|
|
1296
|
-
baseUrl: this.baseUrl,
|
|
1297
|
-
wsHeaders: this.wsHeaders,
|
|
1298
|
-
remotePort: this.remotePort,
|
|
1299
|
-
connectTimeoutMs: this.connectTimeoutMs
|
|
1300
|
-
});
|
|
1301
|
-
await relaySocket(localSocket, relay.websocket);
|
|
1302
|
-
} catch (error) {
|
|
1303
|
-
localSocket.destroy(
|
|
1304
|
-
error instanceof Error ? error : new Error(String(error))
|
|
1305
|
-
);
|
|
1306
|
-
} finally {
|
|
1307
|
-
this.activeRelays.delete(relay);
|
|
1308
|
-
}
|
|
1160
|
+
return this.closePromise ??= (async () => {
|
|
1161
|
+
try {
|
|
1162
|
+
await callNative(() => this.native.close());
|
|
1163
|
+
await this.lifetime;
|
|
1164
|
+
} finally {
|
|
1165
|
+
releaseNativeHandle(this.native);
|
|
1166
|
+
}
|
|
1167
|
+
})();
|
|
1309
1168
|
}
|
|
1310
1169
|
};
|
|
1311
1170
|
}
|
|
@@ -4026,9 +3885,8 @@ var init_sandbox = __esm({
|
|
|
4026
3885
|
*
|
|
4027
3886
|
* Resource targets use create's cpus, memoryMb, and diskMb names. Resize
|
|
4028
3887
|
* waits by default; wait=false returns admission. Timeout does not cancel it.
|
|
4029
|
-
*
|
|
4030
|
-
*
|
|
4031
|
-
* Non-CAS sandboxes do not support live resize.
|
|
3888
|
+
* Which runtimes and dimensions support a live resize is decided by the
|
|
3889
|
+
* server, whose policy error is thrown unchanged.
|
|
4032
3890
|
* Wait, timeout, and pollInterval are ignored on non-resource updates.
|
|
4033
3891
|
* A no-op returns current resources with absent or earlier resize metadata.
|
|
4034
3892
|
*
|
|
@@ -4446,29 +4304,29 @@ var init_sandbox = __esm({
|
|
|
4446
4304
|
}
|
|
4447
4305
|
// --- File operations ---
|
|
4448
4306
|
/** Read a file from the sandbox and return its raw bytes. */
|
|
4449
|
-
async readFile(
|
|
4307
|
+
async readFile(path5) {
|
|
4450
4308
|
const proxy = await this.proxy.client();
|
|
4451
|
-
const { traceId, data } = await callNative(() => proxy.readFile(
|
|
4309
|
+
const { traceId, data } = await callNative(() => proxy.readFile(path5), {
|
|
4452
4310
|
sandboxId: this.sandboxId
|
|
4453
4311
|
});
|
|
4454
4312
|
return Object.assign(Uint8Array.from(data), { traceId });
|
|
4455
4313
|
}
|
|
4456
4314
|
/** Write raw bytes to a file in the sandbox, creating it if it does not exist. */
|
|
4457
|
-
async writeFile(
|
|
4315
|
+
async writeFile(path5, content) {
|
|
4458
4316
|
const proxy = await this.proxy.client();
|
|
4459
|
-
await callNative(() => proxy.writeFile(
|
|
4317
|
+
await callNative(() => proxy.writeFile(path5, Buffer.from(content)), {
|
|
4460
4318
|
sandboxId: this.sandboxId
|
|
4461
4319
|
});
|
|
4462
4320
|
}
|
|
4463
4321
|
/** Delete a file from the sandbox. */
|
|
4464
|
-
async deleteFile(
|
|
4322
|
+
async deleteFile(path5) {
|
|
4465
4323
|
const proxy = await this.proxy.client();
|
|
4466
|
-
await callNative(() => proxy.deleteFile(
|
|
4324
|
+
await callNative(() => proxy.deleteFile(path5), { sandboxId: this.sandboxId });
|
|
4467
4325
|
}
|
|
4468
4326
|
/** List the contents of a directory in the sandbox. */
|
|
4469
|
-
async listDirectory(
|
|
4327
|
+
async listDirectory(path5) {
|
|
4470
4328
|
const proxy = await this.proxy.client();
|
|
4471
|
-
const { traceId, json } = await callNative(() => proxy.listDirectory(
|
|
4329
|
+
const { traceId, json } = await callNative(() => proxy.listDirectory(path5), {
|
|
4472
4330
|
sandboxId: this.sandboxId
|
|
4473
4331
|
});
|
|
4474
4332
|
return Object.assign(fromSnakeKeys(JSON.parse(json)), {
|
|
@@ -5134,9 +4992,9 @@ var init_client = __esm({
|
|
|
5134
4992
|
});
|
|
5135
4993
|
}
|
|
5136
4994
|
/**
|
|
5137
|
-
* Update properties or resize a running sandbox.
|
|
5138
|
-
*
|
|
5139
|
-
*
|
|
4995
|
+
* Update properties or resize a running sandbox. Which runtimes and
|
|
4996
|
+
* dimensions support a live resize is decided by the server, whose policy
|
|
4997
|
+
* error is thrown unchanged.
|
|
5140
4998
|
* Resource names match create. Resize waits by default; wait=false returns
|
|
5141
4999
|
* admission. Timeout leaves the resize running and reports its generation.
|
|
5142
5000
|
* Wait, timeout, and pollInterval are ignored on non-resource updates.
|
|
@@ -5455,6 +5313,11 @@ var init_client = __esm({
|
|
|
5455
5313
|
`Snapshot ${result.snapshotId} failed: ${info.error}`
|
|
5456
5314
|
);
|
|
5457
5315
|
}
|
|
5316
|
+
if (info.status === "deleting" /* DELETING */) {
|
|
5317
|
+
throw new SandboxError(
|
|
5318
|
+
`Snapshot ${result.snapshotId} is being deleted`
|
|
5319
|
+
);
|
|
5320
|
+
}
|
|
5458
5321
|
await sleep2(pollInterval * 1e3);
|
|
5459
5322
|
}
|
|
5460
5323
|
throw new SandboxError(
|
|
@@ -5712,705 +5575,126 @@ var init_client = __esm({
|
|
|
5712
5575
|
}
|
|
5713
5576
|
});
|
|
5714
5577
|
|
|
5715
|
-
// src/
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
headers["Content-Type"] = "application/json";
|
|
5723
|
-
}
|
|
5724
|
-
}
|
|
5725
|
-
const request = {
|
|
5726
|
-
method,
|
|
5727
|
-
path: path4,
|
|
5728
|
-
headersJson: JSON.stringify(headers),
|
|
5729
|
-
statusOnlyCodes: [...options?.statusOnlyCodes ?? []]
|
|
5578
|
+
// src/image.ts
|
|
5579
|
+
import { randomUUID } from "crypto";
|
|
5580
|
+
function cloneOperation(op) {
|
|
5581
|
+
return {
|
|
5582
|
+
type: op.type,
|
|
5583
|
+
args: [...op.args],
|
|
5584
|
+
options: { ...op.options }
|
|
5730
5585
|
};
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
} else if (body !== void 0) {
|
|
5737
|
-
if (body instanceof Blob) request.body = Buffer.from(await body.arrayBuffer());
|
|
5738
|
-
else if (typeof body === "string") request.body = Buffer.from(body);
|
|
5739
|
-
else if (body instanceof ArrayBuffer) request.body = Buffer.from(new Uint8Array(body));
|
|
5740
|
-
else request.body = Buffer.from(body);
|
|
5586
|
+
}
|
|
5587
|
+
function renderOptions(options) {
|
|
5588
|
+
const entries = Object.entries(options);
|
|
5589
|
+
if (entries.length === 0) {
|
|
5590
|
+
return "";
|
|
5741
5591
|
}
|
|
5742
|
-
return
|
|
5592
|
+
return ` ${entries.map(([key, value]) => `--${key}=${value}`).join(" ")}`;
|
|
5593
|
+
}
|
|
5594
|
+
function renderBuildOp(op) {
|
|
5595
|
+
const options = renderOptions(op.options);
|
|
5596
|
+
if (op.type === ImageBuildOperationType.ENV) {
|
|
5597
|
+
return `ENV${options} ${op.args[0]}=${JSON.stringify(op.args[1])}`;
|
|
5598
|
+
}
|
|
5599
|
+
return `${op.type}${options} ${op.args.join(" ")}`;
|
|
5600
|
+
}
|
|
5601
|
+
function dockerfileContent(image) {
|
|
5602
|
+
const lines = image.baseImage == null ? [] : [`FROM ${image.baseImage}`];
|
|
5603
|
+
lines.push(...image.buildOperations.map((op) => renderBuildOp(op)));
|
|
5604
|
+
return lines.join("\n");
|
|
5743
5605
|
}
|
|
5744
|
-
var
|
|
5745
|
-
var
|
|
5746
|
-
"src/
|
|
5606
|
+
var DEFAULT_IMAGE_NAME, ImageBuildOperationType, Image;
|
|
5607
|
+
var init_image = __esm({
|
|
5608
|
+
"src/image.ts"() {
|
|
5747
5609
|
"use strict";
|
|
5748
5610
|
init_esm_shims();
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5611
|
+
DEFAULT_IMAGE_NAME = "default";
|
|
5612
|
+
ImageBuildOperationType = {
|
|
5613
|
+
ADD: "ADD",
|
|
5614
|
+
COPY: "COPY",
|
|
5615
|
+
ENV: "ENV",
|
|
5616
|
+
RUN: "RUN",
|
|
5617
|
+
WORKDIR: "WORKDIR"
|
|
5618
|
+
};
|
|
5619
|
+
Image = class {
|
|
5620
|
+
_id;
|
|
5621
|
+
_name;
|
|
5622
|
+
_tag;
|
|
5623
|
+
_baseImage;
|
|
5624
|
+
_buildOperations;
|
|
5625
|
+
constructor(nameOrOptions = {}, tag = "latest", baseImage = null) {
|
|
5626
|
+
this._id = randomUUID();
|
|
5627
|
+
this._buildOperations = [];
|
|
5628
|
+
if (typeof nameOrOptions === "string") {
|
|
5629
|
+
this._name = nameOrOptions;
|
|
5630
|
+
this._tag = tag;
|
|
5631
|
+
this._baseImage = baseImage;
|
|
5632
|
+
return;
|
|
5759
5633
|
}
|
|
5634
|
+
this._name = nameOrOptions.name ?? DEFAULT_IMAGE_NAME;
|
|
5635
|
+
this._tag = nameOrOptions.tag ?? "latest";
|
|
5636
|
+
this._baseImage = nameOrOptions.baseImage ?? null;
|
|
5760
5637
|
}
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
client() {
|
|
5764
|
-
if (this.closed) throw new Error("Tensorlake native client is closed");
|
|
5765
|
-
if (this.native) return this.native;
|
|
5766
|
-
const ctor = loadNativeSandboxBinding().NativeCloudClient;
|
|
5767
|
-
if (!ctor) throw new Error("Native binding does not export NativeCloudClient; rebuild with 'npm run build:native'");
|
|
5768
|
-
return this.native = new ctor(JSON.stringify(this.options));
|
|
5638
|
+
get name() {
|
|
5639
|
+
return this._name;
|
|
5769
5640
|
}
|
|
5770
|
-
|
|
5771
|
-
this.
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5641
|
+
get tag() {
|
|
5642
|
+
return this._tag;
|
|
5643
|
+
}
|
|
5644
|
+
get baseImage() {
|
|
5645
|
+
return this._baseImage;
|
|
5646
|
+
}
|
|
5647
|
+
get buildOperations() {
|
|
5648
|
+
return this._buildOperations.map(cloneOperation);
|
|
5649
|
+
}
|
|
5650
|
+
add(src, dest, options = void 0) {
|
|
5651
|
+
return this._addOperation({
|
|
5652
|
+
type: ImageBuildOperationType.ADD,
|
|
5653
|
+
args: [src, dest],
|
|
5654
|
+
options: options == null ? {} : { ...options }
|
|
5655
|
+
});
|
|
5656
|
+
}
|
|
5657
|
+
copy(src, dest, options = void 0) {
|
|
5658
|
+
return this._addOperation({
|
|
5659
|
+
type: ImageBuildOperationType.COPY,
|
|
5660
|
+
args: [src, dest],
|
|
5661
|
+
options: options == null ? {} : { ...options }
|
|
5662
|
+
});
|
|
5663
|
+
}
|
|
5664
|
+
env(key, value) {
|
|
5665
|
+
return this._addOperation({
|
|
5666
|
+
type: ImageBuildOperationType.ENV,
|
|
5667
|
+
args: [key, value],
|
|
5668
|
+
options: {}
|
|
5669
|
+
});
|
|
5670
|
+
}
|
|
5671
|
+
run(commands, options = void 0) {
|
|
5672
|
+
return this._addOperation({
|
|
5673
|
+
type: ImageBuildOperationType.RUN,
|
|
5674
|
+
args: Array.isArray(commands) ? [...commands] : [commands],
|
|
5675
|
+
options: options == null ? {} : { ...options }
|
|
5676
|
+
});
|
|
5677
|
+
}
|
|
5678
|
+
workdir(directory) {
|
|
5679
|
+
return this._addOperation({
|
|
5680
|
+
type: ImageBuildOperationType.WORKDIR,
|
|
5681
|
+
args: [directory],
|
|
5682
|
+
options: {}
|
|
5683
|
+
});
|
|
5783
5684
|
}
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5685
|
+
/**
|
|
5686
|
+
* Build this image as a sandbox template and register it.
|
|
5687
|
+
*
|
|
5688
|
+
* Materializes the image in a build sandbox, snapshots the filesystem,
|
|
5689
|
+
* and registers the snapshot as a named sandbox template.
|
|
5690
|
+
*/
|
|
5691
|
+
async build(options = {}) {
|
|
5692
|
+
const { createSandboxImage: createSandboxImage2 } = await Promise.resolve().then(() => (init_sandbox_image(), sandbox_image_exports));
|
|
5693
|
+
return createSandboxImage2(this, options);
|
|
5789
5694
|
}
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
yield* nativeEventStream((emit) => this.client().stream(request, emit), void 0, signal);
|
|
5794
|
-
}
|
|
5795
|
-
};
|
|
5796
|
-
}
|
|
5797
|
-
});
|
|
5798
|
-
|
|
5799
|
-
// src/cloud-client.ts
|
|
5800
|
-
import { nanoid } from "nanoid";
|
|
5801
|
-
function secretFromMetadata(metadata) {
|
|
5802
|
-
return {
|
|
5803
|
-
id: metadata.id,
|
|
5804
|
-
name: metadata.name,
|
|
5805
|
-
createdAt: new Date(metadata.created_at_ms)
|
|
5806
|
-
};
|
|
5807
|
-
}
|
|
5808
|
-
function applicationAllowsUnauthenticatedRequests(manifest) {
|
|
5809
|
-
return Array.isArray(manifest.allow) && manifest.allow.includes(UNAUTHENTICATED_REQUESTS);
|
|
5810
|
-
}
|
|
5811
|
-
function publicEndpointIdFromManifest(manifest) {
|
|
5812
|
-
for (const key of ["public_endpoint_id", "publicEndpointId"]) {
|
|
5813
|
-
const value = manifest[key];
|
|
5814
|
-
if (typeof value === "string" && value.length > 0) {
|
|
5815
|
-
return value;
|
|
5816
|
-
}
|
|
5817
|
-
}
|
|
5818
|
-
return void 0;
|
|
5819
|
-
}
|
|
5820
|
-
function generatePublicEndpointId() {
|
|
5821
|
-
return `endpoint_${nanoid()}`;
|
|
5822
|
-
}
|
|
5823
|
-
function createApplicationBuildForm(request, imageContexts) {
|
|
5824
|
-
const contextsByPartName = /* @__PURE__ */ new Map();
|
|
5825
|
-
for (const context of imageContexts) {
|
|
5826
|
-
if (contextsByPartName.has(context.contextTarPartName)) {
|
|
5827
|
-
throw new Error(
|
|
5828
|
-
`duplicate image context part name '${context.contextTarPartName}'`
|
|
5829
|
-
);
|
|
5830
|
-
}
|
|
5831
|
-
contextsByPartName.set(context.contextTarPartName, context);
|
|
5832
|
-
}
|
|
5833
|
-
const form = new FormData();
|
|
5834
|
-
form.append(
|
|
5835
|
-
"app_version",
|
|
5836
|
-
new Blob([JSON.stringify(request)], { type: "application/json" }),
|
|
5837
|
-
"app_version"
|
|
5838
|
-
);
|
|
5839
|
-
for (const image of request.images) {
|
|
5840
|
-
const context = contextsByPartName.get(image.contextTarPartName);
|
|
5841
|
-
if (!context) {
|
|
5842
|
-
throw new Error(
|
|
5843
|
-
`missing image context for part '${image.contextTarPartName}'`
|
|
5844
|
-
);
|
|
5845
|
-
}
|
|
5846
|
-
form.append(
|
|
5847
|
-
image.contextTarPartName,
|
|
5848
|
-
new Blob([toBlobPart(context.contextTarGz)]),
|
|
5849
|
-
`${image.contextTarPartName}.tar.gz`
|
|
5850
|
-
);
|
|
5851
|
-
}
|
|
5852
|
-
for (const context of imageContexts) {
|
|
5853
|
-
if (!request.images.some((image) => image.contextTarPartName === context.contextTarPartName)) {
|
|
5854
|
-
throw new Error(
|
|
5855
|
-
`unexpected image context for part '${context.contextTarPartName}'`
|
|
5856
|
-
);
|
|
5857
|
-
}
|
|
5858
|
-
}
|
|
5859
|
-
return form;
|
|
5860
|
-
}
|
|
5861
|
-
function trimTrailingSlashes2(value) {
|
|
5862
|
-
return value.endsWith("/") ? value.slice(0, -1) : value;
|
|
5863
|
-
}
|
|
5864
|
-
function nextRequestPath(next) {
|
|
5865
|
-
const schemeIndex = next.indexOf("://");
|
|
5866
|
-
if (schemeIndex !== -1) {
|
|
5867
|
-
const afterScheme = next.slice(schemeIndex + 3);
|
|
5868
|
-
const slashIndex = afterScheme.indexOf("/");
|
|
5869
|
-
return slashIndex === -1 ? "/" : afterScheme.slice(slashIndex);
|
|
5870
|
-
}
|
|
5871
|
-
return next.startsWith("/") ? next : `/${next}`;
|
|
5872
|
-
}
|
|
5873
|
-
function toBlobPart(data) {
|
|
5874
|
-
if (typeof data === "string" || data instanceof Blob) {
|
|
5875
|
-
return data;
|
|
5876
|
-
}
|
|
5877
|
-
if (data instanceof Uint8Array) {
|
|
5878
|
-
return Uint8Array.from(data).buffer;
|
|
5879
|
-
}
|
|
5880
|
-
return data;
|
|
5881
|
-
}
|
|
5882
|
-
function toRequestBody(data) {
|
|
5883
|
-
return toBlobPart(data);
|
|
5884
|
-
}
|
|
5885
|
-
async function parseJsonResponse(response) {
|
|
5886
|
-
const text = await response.text();
|
|
5887
|
-
if (!text) {
|
|
5888
|
-
return void 0;
|
|
5889
|
-
}
|
|
5890
|
-
return JSON.parse(text);
|
|
5891
|
-
}
|
|
5892
|
-
var CloudClient, UNAUTHENTICATED_REQUESTS;
|
|
5893
|
-
var init_cloud_client = __esm({
|
|
5894
|
-
"src/cloud-client.ts"() {
|
|
5895
|
-
"use strict";
|
|
5896
|
-
init_esm_shims();
|
|
5897
|
-
init_defaults();
|
|
5898
|
-
init_native_cloud();
|
|
5899
|
-
init_models();
|
|
5900
|
-
CloudClient = class _CloudClient {
|
|
5901
|
-
transport;
|
|
5902
|
-
organizationId;
|
|
5903
|
-
projectId;
|
|
5904
|
-
namespace;
|
|
5905
|
-
constructor(options) {
|
|
5906
|
-
this.organizationId = options?.organizationId;
|
|
5907
|
-
this.projectId = options?.projectId;
|
|
5908
|
-
this.namespace = options?.namespace ?? NAMESPACE;
|
|
5909
|
-
this.transport = new NativeCloudTransport({
|
|
5910
|
-
baseUrl: options?.apiUrl ?? API_URL,
|
|
5911
|
-
apiKey: options?.apiKey ?? API_KEY,
|
|
5912
|
-
organizationId: this.organizationId,
|
|
5913
|
-
projectId: this.projectId,
|
|
5914
|
-
maxRetries: options?.maxRetries ?? MAX_RETRIES,
|
|
5915
|
-
retryBackoffMs: options?.retryBackoffMs ?? RETRY_BACKOFF_MS,
|
|
5916
|
-
timeoutMs: DEFAULT_HTTP_TIMEOUT_MS,
|
|
5917
|
-
userAgent: `tensorlake-typescript-sdk/${SDK_VERSION}`
|
|
5918
|
-
});
|
|
5919
|
-
}
|
|
5920
|
-
static forCloud(options) {
|
|
5921
|
-
return new _CloudClient(options);
|
|
5922
|
-
}
|
|
5923
|
-
close() {
|
|
5924
|
-
this.transport.close();
|
|
5925
|
-
}
|
|
5926
|
-
async upsertApplication(manifest, codeZip, upgradeRunningRequests = false) {
|
|
5927
|
-
const applicationManifest = { ...manifest };
|
|
5928
|
-
let publicEndpointId = publicEndpointIdFromManifest(applicationManifest);
|
|
5929
|
-
if (applicationAllowsUnauthenticatedRequests(applicationManifest) && publicEndpointId === void 0) {
|
|
5930
|
-
const applicationName = applicationManifest.name;
|
|
5931
|
-
if (typeof applicationName === "string" && applicationName.length > 0) {
|
|
5932
|
-
publicEndpointId = await this.existingApplicationPublicEndpointId(applicationName);
|
|
5933
|
-
}
|
|
5934
|
-
publicEndpointId ??= generatePublicEndpointId();
|
|
5935
|
-
}
|
|
5936
|
-
if (publicEndpointId !== void 0) {
|
|
5937
|
-
applicationManifest.public_endpoint_id = publicEndpointId;
|
|
5938
|
-
delete applicationManifest.publicEndpointId;
|
|
5939
|
-
}
|
|
5940
|
-
const form = new FormData();
|
|
5941
|
-
form.append(
|
|
5942
|
-
"code",
|
|
5943
|
-
new Blob([toBlobPart(codeZip)], { type: "application/zip" }),
|
|
5944
|
-
"code.zip"
|
|
5945
|
-
);
|
|
5946
|
-
form.append("code_content_type", "application/zip");
|
|
5947
|
-
form.append("application", JSON.stringify(applicationManifest));
|
|
5948
|
-
form.append(
|
|
5949
|
-
"upgrade_requests_to_latest_code",
|
|
5950
|
-
String(upgradeRunningRequests)
|
|
5951
|
-
);
|
|
5952
|
-
await this.transport.requestResponse("POST", this.namespacePath("applications"), {
|
|
5953
|
-
body: form
|
|
5954
|
-
});
|
|
5955
|
-
}
|
|
5956
|
-
async deleteApplication(applicationName) {
|
|
5957
|
-
await this.transport.requestResponse(
|
|
5958
|
-
"DELETE",
|
|
5959
|
-
this.namespacePath(`applications/${encodeURIComponent(applicationName)}`)
|
|
5960
|
-
);
|
|
5961
|
-
}
|
|
5962
|
-
async deleteSandboxImage(imageName) {
|
|
5963
|
-
await this.transport.requestResponse(
|
|
5964
|
-
"DELETE",
|
|
5965
|
-
this.namespacePath(`sandbox-images/${encodeURIComponent(imageName)}`)
|
|
5966
|
-
);
|
|
5967
|
-
}
|
|
5968
|
-
/**
|
|
5969
|
-
* Look up a registered sandbox image (template) by its registered name.
|
|
5970
|
-
*
|
|
5971
|
-
* Returns the template, or `null` when no image with that name exists.
|
|
5972
|
-
* API-key clients may omit organization/project IDs and use the
|
|
5973
|
-
* token-scoped Platform API route directly. Explicit scope remains
|
|
5974
|
-
* available for PAT callers.
|
|
5975
|
-
*/
|
|
5976
|
-
async findSandboxImageByName(imageName, options) {
|
|
5977
|
-
const base = this.platformProjectPath(
|
|
5978
|
-
"sandbox-templates",
|
|
5979
|
-
options?.organizationId,
|
|
5980
|
-
options?.projectId
|
|
5981
|
-
);
|
|
5982
|
-
const response = await this.transport.requestResponse(
|
|
5983
|
-
"GET",
|
|
5984
|
-
`${base}/by-name/${encodeURIComponent(imageName)}`,
|
|
5985
|
-
{ statusOnlyCodes: /* @__PURE__ */ new Set([404]) }
|
|
5986
|
-
);
|
|
5987
|
-
if (response.status === 404) {
|
|
5988
|
-
return null;
|
|
5989
|
-
}
|
|
5990
|
-
const raw = await parseJsonResponse(response);
|
|
5991
|
-
return fromSnakeKeys(raw);
|
|
5992
|
-
}
|
|
5993
|
-
/**
|
|
5994
|
-
* List all registered sandbox images (templates), following pagination to
|
|
5995
|
-
* the end. API-key clients may omit organization/project IDs and use the
|
|
5996
|
-
* token-scoped Platform API route directly.
|
|
5997
|
-
*/
|
|
5998
|
-
async listSandboxImages(options) {
|
|
5999
|
-
const base = this.platformProjectPath(
|
|
6000
|
-
"sandbox-templates",
|
|
6001
|
-
options?.organizationId,
|
|
6002
|
-
options?.projectId
|
|
6003
|
-
);
|
|
6004
|
-
let path4 = `${base}?pageSize=100`;
|
|
6005
|
-
const templates = [];
|
|
6006
|
-
while (path4 !== null) {
|
|
6007
|
-
const page = await this.transport.requestJson(
|
|
6008
|
-
"GET",
|
|
6009
|
-
path4
|
|
6010
|
-
);
|
|
6011
|
-
for (const item of page.items ?? []) {
|
|
6012
|
-
templates.push(fromSnakeKeys(item));
|
|
6013
|
-
}
|
|
6014
|
-
const next = page.pagination?.next;
|
|
6015
|
-
path4 = next ? nextRequestPath(next) : null;
|
|
6016
|
-
}
|
|
6017
|
-
return templates;
|
|
6018
|
-
}
|
|
6019
|
-
async applications() {
|
|
6020
|
-
const raw = await this.transport.requestJson(
|
|
6021
|
-
"GET",
|
|
6022
|
-
this.namespacePath("applications")
|
|
6023
|
-
);
|
|
6024
|
-
return (raw.applications ?? []).map(
|
|
6025
|
-
(application) => fromSnakeKeys(application)
|
|
6026
|
-
);
|
|
6027
|
-
}
|
|
6028
|
-
async applicationManifest(applicationName) {
|
|
6029
|
-
const raw = await this.transport.requestJson(
|
|
6030
|
-
"GET",
|
|
6031
|
-
this.namespacePath(`applications/${encodeURIComponent(applicationName)}`)
|
|
6032
|
-
);
|
|
6033
|
-
return fromSnakeKeys(raw);
|
|
6034
|
-
}
|
|
6035
|
-
async runRequest(applicationName, inputs = []) {
|
|
6036
|
-
const path4 = this.namespacePath(
|
|
6037
|
-
`applications/${encodeURIComponent(applicationName)}`
|
|
6038
|
-
);
|
|
6039
|
-
const response = inputs.length === 0 ? await this.transport.requestResponse("POST", path4, {
|
|
6040
|
-
body: new Uint8Array(),
|
|
6041
|
-
headers: { Accept: "application/json" }
|
|
6042
|
-
}) : inputs.length === 1 && inputs[0].name === "0" ? await this.transport.requestResponse("POST", path4, {
|
|
6043
|
-
body: toRequestBody(inputs[0].data),
|
|
6044
|
-
headers: {
|
|
6045
|
-
Accept: "application/json",
|
|
6046
|
-
"Content-Type": inputs[0].contentType
|
|
6047
|
-
}
|
|
6048
|
-
}) : await this.runMultipartRequest(path4, inputs);
|
|
6049
|
-
const body = await parseJsonResponse(response);
|
|
6050
|
-
const requestId = body?.request_id;
|
|
6051
|
-
if (!requestId) {
|
|
6052
|
-
throw new Error("missing request_id in run request response body");
|
|
6053
|
-
}
|
|
6054
|
-
return requestId;
|
|
6055
|
-
}
|
|
6056
|
-
async waitOnRequestCompletion(applicationName, requestId) {
|
|
6057
|
-
const stream = this.transport.stream(
|
|
6058
|
-
"GET",
|
|
6059
|
-
this.namespacePath(
|
|
6060
|
-
`applications/${encodeURIComponent(applicationName)}/requests/${encodeURIComponent(requestId)}/progress`
|
|
6061
|
-
)
|
|
6062
|
-
);
|
|
6063
|
-
for await (const event of stream) {
|
|
6064
|
-
if (Object.prototype.hasOwnProperty.call(event, "RequestFinished")) {
|
|
6065
|
-
return;
|
|
6066
|
-
}
|
|
6067
|
-
}
|
|
6068
|
-
throw new Error("progress stream ended before request completion");
|
|
6069
|
-
}
|
|
6070
|
-
async requestMetadata(applicationName, requestId) {
|
|
6071
|
-
const raw = await this.transport.requestJson(
|
|
6072
|
-
"GET",
|
|
6073
|
-
this.namespacePath(
|
|
6074
|
-
`applications/${encodeURIComponent(applicationName)}/requests/${encodeURIComponent(requestId)}`
|
|
6075
|
-
)
|
|
6076
|
-
);
|
|
6077
|
-
return fromSnakeKeys(raw);
|
|
6078
|
-
}
|
|
6079
|
-
async requestOutput(applicationName, requestId) {
|
|
6080
|
-
const response = await this.transport.requestResponse(
|
|
6081
|
-
"GET",
|
|
6082
|
-
this.namespacePath(
|
|
6083
|
-
`applications/${encodeURIComponent(applicationName)}/requests/${encodeURIComponent(requestId)}/output`
|
|
6084
|
-
)
|
|
6085
|
-
);
|
|
6086
|
-
const serializedValue = new Uint8Array(await response.arrayBuffer());
|
|
6087
|
-
const contentType = response.headers.get("content-type") ?? "";
|
|
6088
|
-
return {
|
|
6089
|
-
serializedValue,
|
|
6090
|
-
contentType
|
|
6091
|
-
};
|
|
6092
|
-
}
|
|
6093
|
-
async listSecrets(options) {
|
|
6094
|
-
const base = this.secretCollectionPath(
|
|
6095
|
-
options?.organizationId,
|
|
6096
|
-
options?.projectId
|
|
6097
|
-
);
|
|
6098
|
-
const raw = await this.transport.requestJson("GET", base);
|
|
6099
|
-
const pageSize = Math.max(0, options?.pageSize ?? 100);
|
|
6100
|
-
return Object.assign(
|
|
6101
|
-
{
|
|
6102
|
-
items: raw.slice(0, pageSize).map(secretFromMetadata),
|
|
6103
|
-
pagination: { total: raw.length }
|
|
6104
|
-
},
|
|
6105
|
-
{ traceId: raw.traceId }
|
|
6106
|
-
);
|
|
6107
|
-
}
|
|
6108
|
-
async getSecret(secretId, options) {
|
|
6109
|
-
const base = this.secretCollectionPath(
|
|
6110
|
-
options?.organizationId,
|
|
6111
|
-
options?.projectId
|
|
6112
|
-
);
|
|
6113
|
-
const raw = await this.transport.requestJson(
|
|
6114
|
-
"GET",
|
|
6115
|
-
`${base}/${encodeURIComponent(secretId)}`
|
|
6116
|
-
);
|
|
6117
|
-
return Object.assign(secretFromMetadata(raw), { traceId: raw.traceId });
|
|
6118
|
-
}
|
|
6119
|
-
async upsertSecrets(secrets, options) {
|
|
6120
|
-
const base = this.secretCollectionPath(
|
|
6121
|
-
options?.organizationId,
|
|
6122
|
-
options?.projectId
|
|
6123
|
-
);
|
|
6124
|
-
if (Array.isArray(secrets)) {
|
|
6125
|
-
const results = [];
|
|
6126
|
-
for (const secret of secrets) {
|
|
6127
|
-
results.push(await this.upsertSecret(base, secret));
|
|
6128
|
-
}
|
|
6129
|
-
return results;
|
|
6130
|
-
}
|
|
6131
|
-
return this.upsertSecret(base, secrets);
|
|
6132
|
-
}
|
|
6133
|
-
async deleteSecret(secretId, options) {
|
|
6134
|
-
const base = this.secretCollectionPath(
|
|
6135
|
-
options?.organizationId,
|
|
6136
|
-
options?.projectId
|
|
6137
|
-
);
|
|
6138
|
-
await this.transport.requestResponse(
|
|
6139
|
-
"DELETE",
|
|
6140
|
-
`${base}/${encodeURIComponent(secretId)}`
|
|
6141
|
-
);
|
|
6142
|
-
}
|
|
6143
|
-
async upsertSecret(base, secret) {
|
|
6144
|
-
let response = await this.transport.requestResponse("POST", base, {
|
|
6145
|
-
json: secret,
|
|
6146
|
-
headers: { "Idempotency-Key": nanoid() },
|
|
6147
|
-
statusOnlyCodes: /* @__PURE__ */ new Set([409])
|
|
6148
|
-
});
|
|
6149
|
-
if (response.status === 409) {
|
|
6150
|
-
const prefix = base.slice(0, -"/secrets".length);
|
|
6151
|
-
const existing = await this.transport.requestJson(
|
|
6152
|
-
"GET",
|
|
6153
|
-
`${prefix}/secret-names/${encodeURIComponent(secret.name)}`
|
|
6154
|
-
);
|
|
6155
|
-
response = await this.transport.requestResponse(
|
|
6156
|
-
"POST",
|
|
6157
|
-
`${base}/${encodeURIComponent(existing.id)}/versions`,
|
|
6158
|
-
{
|
|
6159
|
-
json: { value: secret.value },
|
|
6160
|
-
headers: { "Idempotency-Key": nanoid() }
|
|
6161
|
-
}
|
|
6162
|
-
);
|
|
6163
|
-
}
|
|
6164
|
-
const metadata = await parseJsonResponse(response);
|
|
6165
|
-
return Object.assign(secretFromMetadata(metadata), {
|
|
6166
|
-
traceId: response.traceId
|
|
6167
|
-
});
|
|
6168
|
-
}
|
|
6169
|
-
async startImageBuild(buildServicePath, request) {
|
|
6170
|
-
const form = new FormData();
|
|
6171
|
-
form.append("graph_name", request.applicationName);
|
|
6172
|
-
form.append("graph_version", request.applicationVersion);
|
|
6173
|
-
form.append("graph_function_name", request.functionName);
|
|
6174
|
-
form.append("image_name", request.imageName);
|
|
6175
|
-
form.append("image_id", request.imageId);
|
|
6176
|
-
form.append(
|
|
6177
|
-
"context",
|
|
6178
|
-
new Blob([toBlobPart(request.buildContext)]),
|
|
6179
|
-
"context.tar.gz"
|
|
6180
|
-
);
|
|
6181
|
-
const response = await this.transport.requestResponse(
|
|
6182
|
-
"PUT",
|
|
6183
|
-
`${trimTrailingSlashes2(buildServicePath)}/builds`,
|
|
6184
|
-
{ body: form }
|
|
6185
|
-
);
|
|
6186
|
-
const raw = await parseJsonResponse(response);
|
|
6187
|
-
return fromSnakeKeys(raw);
|
|
6188
|
-
}
|
|
6189
|
-
async createApplicationBuild(buildServicePath, request, imageContexts) {
|
|
6190
|
-
const form = createApplicationBuildForm(request, imageContexts);
|
|
6191
|
-
const response = await this.transport.requestResponse(
|
|
6192
|
-
"POST",
|
|
6193
|
-
trimTrailingSlashes2(buildServicePath),
|
|
6194
|
-
{ body: form }
|
|
6195
|
-
);
|
|
6196
|
-
const raw = await parseJsonResponse(response);
|
|
6197
|
-
return fromSnakeKeys(raw);
|
|
6198
|
-
}
|
|
6199
|
-
async applicationBuildInfo(buildServicePath, applicationBuildId) {
|
|
6200
|
-
const raw = await this.transport.requestJson(
|
|
6201
|
-
"GET",
|
|
6202
|
-
`${trimTrailingSlashes2(buildServicePath)}/${encodeURIComponent(applicationBuildId)}`
|
|
6203
|
-
);
|
|
6204
|
-
return fromSnakeKeys(raw);
|
|
6205
|
-
}
|
|
6206
|
-
async cancelApplicationBuild(buildServicePath, applicationBuildId) {
|
|
6207
|
-
const raw = await this.transport.requestJson(
|
|
6208
|
-
"POST",
|
|
6209
|
-
`${trimTrailingSlashes2(buildServicePath)}/${encodeURIComponent(applicationBuildId)}/cancel`
|
|
6210
|
-
);
|
|
6211
|
-
return fromSnakeKeys(raw);
|
|
6212
|
-
}
|
|
6213
|
-
async buildInfo(buildServicePath, buildId) {
|
|
6214
|
-
const raw = await this.transport.requestJson(
|
|
6215
|
-
"GET",
|
|
6216
|
-
`${trimTrailingSlashes2(buildServicePath)}/builds/${encodeURIComponent(buildId)}`
|
|
6217
|
-
);
|
|
6218
|
-
return fromSnakeKeys(raw);
|
|
6219
|
-
}
|
|
6220
|
-
async cancelBuild(buildServicePath, buildId) {
|
|
6221
|
-
await this.transport.requestResponse(
|
|
6222
|
-
"POST",
|
|
6223
|
-
`${trimTrailingSlashes2(buildServicePath)}/builds/${encodeURIComponent(buildId)}/cancel`
|
|
6224
|
-
);
|
|
6225
|
-
}
|
|
6226
|
-
async *streamBuildLogs(buildServicePath, buildId, signal) {
|
|
6227
|
-
const stream = this.transport.stream(
|
|
6228
|
-
"GET",
|
|
6229
|
-
`${trimTrailingSlashes2(buildServicePath)}/builds/${encodeURIComponent(buildId)}/logs`,
|
|
6230
|
-
signal
|
|
6231
|
-
);
|
|
6232
|
-
for await (const event of stream) {
|
|
6233
|
-
yield fromSnakeKeys(event);
|
|
6234
|
-
}
|
|
6235
|
-
}
|
|
6236
|
-
async runMultipartRequest(path4, inputs) {
|
|
6237
|
-
const form = new FormData();
|
|
6238
|
-
for (const input of inputs) {
|
|
6239
|
-
form.append(
|
|
6240
|
-
input.name,
|
|
6241
|
-
new Blob([toBlobPart(input.data)], { type: input.contentType }),
|
|
6242
|
-
input.name
|
|
6243
|
-
);
|
|
6244
|
-
}
|
|
6245
|
-
return this.transport.requestResponse("POST", path4, {
|
|
6246
|
-
body: form,
|
|
6247
|
-
headers: { Accept: "application/json" }
|
|
6248
|
-
});
|
|
6249
|
-
}
|
|
6250
|
-
namespacePath(subpath) {
|
|
6251
|
-
return `/v1/namespaces/${encodeURIComponent(this.namespace)}/${subpath.replace(/^\/+/, "")}`;
|
|
6252
|
-
}
|
|
6253
|
-
async existingApplicationPublicEndpointId(applicationName) {
|
|
6254
|
-
const response = await this.transport.requestResponse(
|
|
6255
|
-
"GET",
|
|
6256
|
-
this.namespacePath(`applications/${encodeURIComponent(applicationName)}`),
|
|
6257
|
-
{ statusOnlyCodes: /* @__PURE__ */ new Set([404]) }
|
|
6258
|
-
);
|
|
6259
|
-
if (response.status === 404) {
|
|
6260
|
-
return void 0;
|
|
6261
|
-
}
|
|
6262
|
-
const application = await parseJsonResponse(response);
|
|
6263
|
-
return publicEndpointIdFromManifest(application);
|
|
6264
|
-
}
|
|
6265
|
-
platformProjectPath(resource, organizationId, projectId) {
|
|
6266
|
-
const resolvedOrganizationId = organizationId ?? this.organizationId;
|
|
6267
|
-
const resolvedProjectId = projectId ?? this.projectId;
|
|
6268
|
-
if (!resolvedOrganizationId && !resolvedProjectId) {
|
|
6269
|
-
return `/platform/v1/${resource}`;
|
|
6270
|
-
}
|
|
6271
|
-
if (!resolvedOrganizationId || !resolvedProjectId) {
|
|
6272
|
-
throw new Error(
|
|
6273
|
-
"organizationId and projectId must be provided together"
|
|
6274
|
-
);
|
|
6275
|
-
}
|
|
6276
|
-
return `/platform/v1/organizations/${encodeURIComponent(resolvedOrganizationId)}/projects/${encodeURIComponent(resolvedProjectId)}/${resource}`;
|
|
6277
|
-
}
|
|
6278
|
-
secretCollectionPath(organizationId, projectId) {
|
|
6279
|
-
const resolvedOrganizationId = organizationId ?? this.organizationId;
|
|
6280
|
-
const resolvedProjectId = projectId ?? this.projectId;
|
|
6281
|
-
if (!resolvedOrganizationId && !resolvedProjectId) {
|
|
6282
|
-
return this.namespacePath("secrets");
|
|
6283
|
-
}
|
|
6284
|
-
if (!resolvedOrganizationId || !resolvedProjectId) {
|
|
6285
|
-
throw new Error("organizationId and projectId must be provided together");
|
|
6286
|
-
}
|
|
6287
|
-
return this.namespacePath("secrets");
|
|
6288
|
-
}
|
|
6289
|
-
};
|
|
6290
|
-
UNAUTHENTICATED_REQUESTS = "unauthenticated_requests";
|
|
6291
|
-
}
|
|
6292
|
-
});
|
|
6293
|
-
|
|
6294
|
-
// src/image.ts
|
|
6295
|
-
import { randomUUID } from "crypto";
|
|
6296
|
-
function cloneOperation(op) {
|
|
6297
|
-
return {
|
|
6298
|
-
type: op.type,
|
|
6299
|
-
args: [...op.args],
|
|
6300
|
-
options: { ...op.options }
|
|
6301
|
-
};
|
|
6302
|
-
}
|
|
6303
|
-
function renderOptions(options) {
|
|
6304
|
-
const entries = Object.entries(options);
|
|
6305
|
-
if (entries.length === 0) {
|
|
6306
|
-
return "";
|
|
6307
|
-
}
|
|
6308
|
-
return ` ${entries.map(([key, value]) => `--${key}=${value}`).join(" ")}`;
|
|
6309
|
-
}
|
|
6310
|
-
function renderBuildOp(op) {
|
|
6311
|
-
const options = renderOptions(op.options);
|
|
6312
|
-
if (op.type === ImageBuildOperationType.ENV) {
|
|
6313
|
-
return `ENV${options} ${op.args[0]}=${JSON.stringify(op.args[1])}`;
|
|
6314
|
-
}
|
|
6315
|
-
return `${op.type}${options} ${op.args.join(" ")}`;
|
|
6316
|
-
}
|
|
6317
|
-
function dockerfileContent(image) {
|
|
6318
|
-
const lines = image.baseImage == null ? [] : [`FROM ${image.baseImage}`];
|
|
6319
|
-
lines.push(...image.buildOperations.map((op) => renderBuildOp(op)));
|
|
6320
|
-
return lines.join("\n");
|
|
6321
|
-
}
|
|
6322
|
-
var DEFAULT_IMAGE_NAME, ImageBuildOperationType, Image;
|
|
6323
|
-
var init_image = __esm({
|
|
6324
|
-
"src/image.ts"() {
|
|
6325
|
-
"use strict";
|
|
6326
|
-
init_esm_shims();
|
|
6327
|
-
DEFAULT_IMAGE_NAME = "default";
|
|
6328
|
-
ImageBuildOperationType = {
|
|
6329
|
-
ADD: "ADD",
|
|
6330
|
-
COPY: "COPY",
|
|
6331
|
-
ENV: "ENV",
|
|
6332
|
-
RUN: "RUN",
|
|
6333
|
-
WORKDIR: "WORKDIR"
|
|
6334
|
-
};
|
|
6335
|
-
Image = class {
|
|
6336
|
-
_id;
|
|
6337
|
-
_name;
|
|
6338
|
-
_tag;
|
|
6339
|
-
_baseImage;
|
|
6340
|
-
_buildOperations;
|
|
6341
|
-
constructor(nameOrOptions = {}, tag = "latest", baseImage = null) {
|
|
6342
|
-
this._id = randomUUID();
|
|
6343
|
-
this._buildOperations = [];
|
|
6344
|
-
if (typeof nameOrOptions === "string") {
|
|
6345
|
-
this._name = nameOrOptions;
|
|
6346
|
-
this._tag = tag;
|
|
6347
|
-
this._baseImage = baseImage;
|
|
6348
|
-
return;
|
|
6349
|
-
}
|
|
6350
|
-
this._name = nameOrOptions.name ?? DEFAULT_IMAGE_NAME;
|
|
6351
|
-
this._tag = nameOrOptions.tag ?? "latest";
|
|
6352
|
-
this._baseImage = nameOrOptions.baseImage ?? null;
|
|
6353
|
-
}
|
|
6354
|
-
get name() {
|
|
6355
|
-
return this._name;
|
|
6356
|
-
}
|
|
6357
|
-
get tag() {
|
|
6358
|
-
return this._tag;
|
|
6359
|
-
}
|
|
6360
|
-
get baseImage() {
|
|
6361
|
-
return this._baseImage;
|
|
6362
|
-
}
|
|
6363
|
-
get buildOperations() {
|
|
6364
|
-
return this._buildOperations.map(cloneOperation);
|
|
6365
|
-
}
|
|
6366
|
-
add(src, dest, options = void 0) {
|
|
6367
|
-
return this._addOperation({
|
|
6368
|
-
type: ImageBuildOperationType.ADD,
|
|
6369
|
-
args: [src, dest],
|
|
6370
|
-
options: options == null ? {} : { ...options }
|
|
6371
|
-
});
|
|
6372
|
-
}
|
|
6373
|
-
copy(src, dest, options = void 0) {
|
|
6374
|
-
return this._addOperation({
|
|
6375
|
-
type: ImageBuildOperationType.COPY,
|
|
6376
|
-
args: [src, dest],
|
|
6377
|
-
options: options == null ? {} : { ...options }
|
|
6378
|
-
});
|
|
6379
|
-
}
|
|
6380
|
-
env(key, value) {
|
|
6381
|
-
return this._addOperation({
|
|
6382
|
-
type: ImageBuildOperationType.ENV,
|
|
6383
|
-
args: [key, value],
|
|
6384
|
-
options: {}
|
|
6385
|
-
});
|
|
6386
|
-
}
|
|
6387
|
-
run(commands, options = void 0) {
|
|
6388
|
-
return this._addOperation({
|
|
6389
|
-
type: ImageBuildOperationType.RUN,
|
|
6390
|
-
args: Array.isArray(commands) ? [...commands] : [commands],
|
|
6391
|
-
options: options == null ? {} : { ...options }
|
|
6392
|
-
});
|
|
6393
|
-
}
|
|
6394
|
-
workdir(directory) {
|
|
6395
|
-
return this._addOperation({
|
|
6396
|
-
type: ImageBuildOperationType.WORKDIR,
|
|
6397
|
-
args: [directory],
|
|
6398
|
-
options: {}
|
|
6399
|
-
});
|
|
6400
|
-
}
|
|
6401
|
-
/**
|
|
6402
|
-
* Build this image as a sandbox template and register it.
|
|
6403
|
-
*
|
|
6404
|
-
* Materializes the image in a build sandbox, snapshots the filesystem,
|
|
6405
|
-
* and registers the snapshot as a named sandbox template.
|
|
6406
|
-
*/
|
|
6407
|
-
async build(options = {}) {
|
|
6408
|
-
const { createSandboxImage: createSandboxImage2 } = await Promise.resolve().then(() => (init_sandbox_image(), sandbox_image_exports));
|
|
6409
|
-
return createSandboxImage2(this, options);
|
|
6410
|
-
}
|
|
6411
|
-
_addOperation(op) {
|
|
6412
|
-
this._buildOperations.push(op);
|
|
6413
|
-
return this;
|
|
5695
|
+
_addOperation(op) {
|
|
5696
|
+
this._buildOperations.push(op);
|
|
5697
|
+
return this;
|
|
6414
5698
|
}
|
|
6415
5699
|
};
|
|
6416
5700
|
}
|
|
@@ -6562,22 +5846,477 @@ var init_native_binding = __esm({
|
|
|
6562
5846
|
}
|
|
6563
5847
|
});
|
|
6564
5848
|
|
|
5849
|
+
// src/image-builds.ts
|
|
5850
|
+
import path3 from "path";
|
|
5851
|
+
import os from "os";
|
|
5852
|
+
import { existsSync as existsSync2, mkdtempSync, rmSync } from "fs";
|
|
5853
|
+
function camelize(key) {
|
|
5854
|
+
return key.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
|
|
5855
|
+
}
|
|
5856
|
+
function toImageBuildError(error) {
|
|
5857
|
+
if (!(error instanceof Error)) return error;
|
|
5858
|
+
let payload;
|
|
5859
|
+
try {
|
|
5860
|
+
payload = JSON.parse(error.message);
|
|
5861
|
+
} catch {
|
|
5862
|
+
return error;
|
|
5863
|
+
}
|
|
5864
|
+
if (!payload || payload.category !== "image_build") return error;
|
|
5865
|
+
const details = {};
|
|
5866
|
+
for (const [key, value] of Object.entries(payload)) {
|
|
5867
|
+
if (key === "category") continue;
|
|
5868
|
+
details[camelize(key)] = value;
|
|
5869
|
+
}
|
|
5870
|
+
const typed = details;
|
|
5871
|
+
switch (typed.code) {
|
|
5872
|
+
case "not_found":
|
|
5873
|
+
return new ImageBuildNotFoundError(typed);
|
|
5874
|
+
case "image_build_in_progress":
|
|
5875
|
+
return new ImageBuildInProgressError(typed);
|
|
5876
|
+
case "failed":
|
|
5877
|
+
return new ImageBuildFailedError(typed);
|
|
5878
|
+
case "cancelled":
|
|
5879
|
+
return new ImageBuildCancelledError(typed);
|
|
5880
|
+
case "timeout":
|
|
5881
|
+
return new ImageBuildTimeoutError(typed);
|
|
5882
|
+
case "interrupted":
|
|
5883
|
+
return new ImageBuildInterruptedError(typed);
|
|
5884
|
+
default:
|
|
5885
|
+
return new ImageBuildError(typed);
|
|
5886
|
+
}
|
|
5887
|
+
}
|
|
5888
|
+
function camelizeRecord(value) {
|
|
5889
|
+
const out = {};
|
|
5890
|
+
for (const [key, inner] of Object.entries(value)) out[camelize(key)] = inner;
|
|
5891
|
+
return out;
|
|
5892
|
+
}
|
|
5893
|
+
function parseBuildInfo(raw) {
|
|
5894
|
+
const camel = camelizeRecord(raw);
|
|
5895
|
+
const result = raw.result && typeof raw.result === "object" ? camelizeRecord(raw.result) : null;
|
|
5896
|
+
return {
|
|
5897
|
+
buildId: String(raw.build_id ?? ""),
|
|
5898
|
+
clientRequestId: camel.clientRequestId ?? null,
|
|
5899
|
+
kind: String(raw.kind ?? ""),
|
|
5900
|
+
name: raw.name ?? null,
|
|
5901
|
+
status: String(raw.status ?? ""),
|
|
5902
|
+
phase: raw.phase ?? null,
|
|
5903
|
+
attemptNo: Number(raw.attempt_no ?? 0),
|
|
5904
|
+
builderSandboxId: camel.builderSandboxId ?? null,
|
|
5905
|
+
error: raw.error ?? null,
|
|
5906
|
+
result,
|
|
5907
|
+
operationDeadlineMs: camel.operationDeadlineMs ?? null,
|
|
5908
|
+
createdAtMs: camel.createdAtMs ?? null,
|
|
5909
|
+
updatedAtMs: camel.updatedAtMs ?? null,
|
|
5910
|
+
raw
|
|
5911
|
+
};
|
|
5912
|
+
}
|
|
5913
|
+
function parseResult(json) {
|
|
5914
|
+
return camelizeRecord(JSON.parse(json));
|
|
5915
|
+
}
|
|
5916
|
+
function credentialsFromEnv() {
|
|
5917
|
+
const context = __imageBuildInternals.buildContextFromEnv();
|
|
5918
|
+
if (!context.apiKey) {
|
|
5919
|
+
if (context.personalAccessToken) {
|
|
5920
|
+
throw new ImageBuildError({
|
|
5921
|
+
code: "auth",
|
|
5922
|
+
message: "Sandbox image SDKs require TENSORLAKE_API_KEY. Personal access tokens are CLI-only."
|
|
5923
|
+
});
|
|
5924
|
+
}
|
|
5925
|
+
throw new ImageBuildError({ code: "auth", message: "Missing TENSORLAKE_API_KEY credentials." });
|
|
5926
|
+
}
|
|
5927
|
+
return { apiUrl: context.apiUrl, bearerToken: context.apiKey, namespace: context.namespace };
|
|
5928
|
+
}
|
|
5929
|
+
function clientOptions(credentials) {
|
|
5930
|
+
return {
|
|
5931
|
+
apiUrl: credentials.apiUrl,
|
|
5932
|
+
bearerToken: credentials.bearerToken,
|
|
5933
|
+
namespace: credentials.namespace,
|
|
5934
|
+
useScopeHeaders: false
|
|
5935
|
+
};
|
|
5936
|
+
}
|
|
5937
|
+
function rejectLegacyReference(buildId) {
|
|
5938
|
+
if (typeof buildId !== "string" || buildId.trim().length === 0) {
|
|
5939
|
+
throw new ImageBuildError({ code: "usage", message: "buildId must be a non-empty string" });
|
|
5940
|
+
}
|
|
5941
|
+
if (buildId.startsWith("sandbox_template_")) {
|
|
5942
|
+
throw new ImageBuildError({
|
|
5943
|
+
code: "usage",
|
|
5944
|
+
message: `'${buildId}' is a legacy sandbox template id; legacy images have no build operation to get, wait for or cancel`,
|
|
5945
|
+
buildId
|
|
5946
|
+
});
|
|
5947
|
+
}
|
|
5948
|
+
if (buildId.startsWith("image_")) {
|
|
5949
|
+
throw new ImageBuildError({
|
|
5950
|
+
code: "usage",
|
|
5951
|
+
message: `'${buildId}' is an image id, not a build id; look the image up with findSandboxImageByName or use the build id admission returned`,
|
|
5952
|
+
buildId
|
|
5953
|
+
});
|
|
5954
|
+
}
|
|
5955
|
+
}
|
|
5956
|
+
async function __runWithInterrupt(signal, run) {
|
|
5957
|
+
const binding = __imageBuildInternals.loadNativeBinding();
|
|
5958
|
+
if (signal === void 0) {
|
|
5959
|
+
try {
|
|
5960
|
+
return await run(void 0);
|
|
5961
|
+
} catch (error) {
|
|
5962
|
+
throw toImageBuildError(error);
|
|
5963
|
+
}
|
|
5964
|
+
}
|
|
5965
|
+
const interruptId = binding.createImageBuildInterrupt();
|
|
5966
|
+
const onAbort = () => binding.triggerImageBuildInterrupt(interruptId);
|
|
5967
|
+
if (signal.aborted) onAbort();
|
|
5968
|
+
else signal.addEventListener("abort", onAbort, { once: true });
|
|
5969
|
+
try {
|
|
5970
|
+
return await run(interruptId);
|
|
5971
|
+
} catch (error) {
|
|
5972
|
+
throw toImageBuildError(error);
|
|
5973
|
+
} finally {
|
|
5974
|
+
signal.removeEventListener("abort", onAbort);
|
|
5975
|
+
binding.releaseImageBuildInterrupt(interruptId);
|
|
5976
|
+
}
|
|
5977
|
+
}
|
|
5978
|
+
function makeEmitter(options) {
|
|
5979
|
+
const emit = options.emit ?? (options.verbose ? __imageBuildInternals.stderrEmit : __imageBuildInternals.noopEmit);
|
|
5980
|
+
let emitError;
|
|
5981
|
+
const forward = (event) => {
|
|
5982
|
+
try {
|
|
5983
|
+
emit(__imageBuildInternals.eventToEmitDict(event));
|
|
5984
|
+
} catch (error) {
|
|
5985
|
+
emitError ??= error;
|
|
5986
|
+
}
|
|
5987
|
+
};
|
|
5988
|
+
return {
|
|
5989
|
+
forward,
|
|
5990
|
+
emit,
|
|
5991
|
+
rethrow() {
|
|
5992
|
+
if (emitError != null) throw emitError;
|
|
5993
|
+
}
|
|
5994
|
+
};
|
|
5995
|
+
}
|
|
5996
|
+
function decodeStarted(json, credentials) {
|
|
5997
|
+
const payload = JSON.parse(json);
|
|
5998
|
+
return new ImageBuildHandle(parseBuildInfo(payload.build ?? {}), credentials, payload.client_request_id);
|
|
5999
|
+
}
|
|
6000
|
+
async function startImageBuild(source, options = {}, deps = {}) {
|
|
6001
|
+
const emitter = makeEmitter({ emit: deps.emit ?? options.emit, verbose: options.verbose });
|
|
6002
|
+
let dockerfilePath;
|
|
6003
|
+
let dockerfileText;
|
|
6004
|
+
let contextDir;
|
|
6005
|
+
let name;
|
|
6006
|
+
let tempContextDir;
|
|
6007
|
+
if (source instanceof Image) {
|
|
6008
|
+
if (!source.baseImage) throw new Error("Image must have a baseImage to build");
|
|
6009
|
+
if (options.contextDir != null) {
|
|
6010
|
+
contextDir = path3.resolve(options.contextDir);
|
|
6011
|
+
} else if (__imageBuildInternals.imageRequiresContext(source)) {
|
|
6012
|
+
throw new Error(
|
|
6013
|
+
"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>`."
|
|
6014
|
+
);
|
|
6015
|
+
} else {
|
|
6016
|
+
tempContextDir = mkdtempSync(path3.join(os.tmpdir(), "tl-build-context-"));
|
|
6017
|
+
contextDir = tempContextDir;
|
|
6018
|
+
}
|
|
6019
|
+
dockerfilePath = path3.join(contextDir, "Dockerfile");
|
|
6020
|
+
let text = dockerfileContent(source);
|
|
6021
|
+
if (!text.endsWith("\n")) text += "\n";
|
|
6022
|
+
dockerfileText = text;
|
|
6023
|
+
name = options.registeredName ?? source.name;
|
|
6024
|
+
} else if (typeof source === "string") {
|
|
6025
|
+
const resolved = path3.resolve(source);
|
|
6026
|
+
if (!existsSync2(resolved)) throw new Error(`Dockerfile not found: ${source}`);
|
|
6027
|
+
dockerfilePath = resolved;
|
|
6028
|
+
name = options.registeredName ?? __imageBuildInternals.defaultRegisteredName(resolved);
|
|
6029
|
+
} else {
|
|
6030
|
+
throw new TypeError(`source must be an Image or a Dockerfile path, got ${typeof source}`);
|
|
6031
|
+
}
|
|
6032
|
+
try {
|
|
6033
|
+
const credentials = credentialsFromEnv();
|
|
6034
|
+
const binding = __imageBuildInternals.loadNativeBinding();
|
|
6035
|
+
emitter.emit({ type: "status", message: `Building image '${name}'...` });
|
|
6036
|
+
const json = await __runWithInterrupt(
|
|
6037
|
+
options.signal,
|
|
6038
|
+
(interruptId) => binding.startImageBuild(
|
|
6039
|
+
{
|
|
6040
|
+
apiUrl: credentials.apiUrl,
|
|
6041
|
+
bearerToken: credentials.bearerToken,
|
|
6042
|
+
dockerfilePath,
|
|
6043
|
+
registeredName: name,
|
|
6044
|
+
diskMb: options.diskMb,
|
|
6045
|
+
cpus: options.cpus,
|
|
6046
|
+
memoryMb: options.memoryMb,
|
|
6047
|
+
isPublic: options.isPublic ?? false,
|
|
6048
|
+
namespace: credentials.namespace,
|
|
6049
|
+
useScopeHeaders: false,
|
|
6050
|
+
dockerConfigJson: options.dockerConfigJson,
|
|
6051
|
+
dockerfileText,
|
|
6052
|
+
contextDir,
|
|
6053
|
+
cas: true,
|
|
6054
|
+
buildArgs: options.buildArgs
|
|
6055
|
+
},
|
|
6056
|
+
emitter.forward,
|
|
6057
|
+
interruptId
|
|
6058
|
+
)
|
|
6059
|
+
);
|
|
6060
|
+
emitter.rethrow();
|
|
6061
|
+
return decodeStarted(json, credentials);
|
|
6062
|
+
} finally {
|
|
6063
|
+
if (tempContextDir != null) rmSync(tempContextDir, { recursive: true, force: true });
|
|
6064
|
+
}
|
|
6065
|
+
}
|
|
6066
|
+
async function startImageImport(imageReference, options = {}, deps = {}) {
|
|
6067
|
+
if (typeof imageReference !== "string" || imageReference.trim().length === 0) {
|
|
6068
|
+
throw new Error("image reference to import must not be empty");
|
|
6069
|
+
}
|
|
6070
|
+
const reference = imageReference.trim();
|
|
6071
|
+
const name = options.registeredName ?? __imageBuildInternals.defaultRegisteredNameFromImage(reference);
|
|
6072
|
+
const emitter = makeEmitter({ emit: deps.emit ?? options.emit, verbose: options.verbose });
|
|
6073
|
+
const credentials = credentialsFromEnv();
|
|
6074
|
+
const binding = __imageBuildInternals.loadNativeBinding();
|
|
6075
|
+
emitter.emit({ type: "status", message: `Importing image '${reference}' as '${name}'...` });
|
|
6076
|
+
const json = await __runWithInterrupt(
|
|
6077
|
+
options.signal,
|
|
6078
|
+
(interruptId) => binding.startImageImport(
|
|
6079
|
+
{
|
|
6080
|
+
apiUrl: credentials.apiUrl,
|
|
6081
|
+
bearerToken: credentials.bearerToken,
|
|
6082
|
+
imageReference: reference,
|
|
6083
|
+
registeredName: name,
|
|
6084
|
+
diskMb: options.diskMb,
|
|
6085
|
+
cpus: options.cpus,
|
|
6086
|
+
memoryMb: options.memoryMb,
|
|
6087
|
+
isPublic: options.isPublic ?? false,
|
|
6088
|
+
namespace: credentials.namespace,
|
|
6089
|
+
useScopeHeaders: false,
|
|
6090
|
+
dockerConfigJson: options.dockerConfigJson,
|
|
6091
|
+
cas: true
|
|
6092
|
+
},
|
|
6093
|
+
emitter.forward,
|
|
6094
|
+
interruptId
|
|
6095
|
+
)
|
|
6096
|
+
);
|
|
6097
|
+
emitter.rethrow();
|
|
6098
|
+
return decodeStarted(json, credentials);
|
|
6099
|
+
}
|
|
6100
|
+
async function getImageBuild(buildId) {
|
|
6101
|
+
rejectLegacyReference(buildId);
|
|
6102
|
+
const credentials = credentialsFromEnv();
|
|
6103
|
+
const binding = __imageBuildInternals.loadNativeBinding();
|
|
6104
|
+
let json;
|
|
6105
|
+
try {
|
|
6106
|
+
json = await binding.getImageBuild(clientOptions(credentials), buildId);
|
|
6107
|
+
} catch (error) {
|
|
6108
|
+
throw toImageBuildError(error);
|
|
6109
|
+
}
|
|
6110
|
+
return new ImageBuildHandle(parseBuildInfo(JSON.parse(json)), credentials);
|
|
6111
|
+
}
|
|
6112
|
+
async function waitImageBuild(buildId, options = {}) {
|
|
6113
|
+
rejectLegacyReference(buildId);
|
|
6114
|
+
const credentials = credentialsFromEnv();
|
|
6115
|
+
const binding = __imageBuildInternals.loadNativeBinding();
|
|
6116
|
+
const emitter = makeEmitter(options);
|
|
6117
|
+
const json = await __runWithInterrupt(
|
|
6118
|
+
options.signal,
|
|
6119
|
+
(interruptId) => binding.waitImageBuild(
|
|
6120
|
+
clientOptions(credentials),
|
|
6121
|
+
buildId,
|
|
6122
|
+
{ timeoutMs: options.timeoutMs, followLogs: options.followLogs ?? false },
|
|
6123
|
+
emitter.forward,
|
|
6124
|
+
interruptId
|
|
6125
|
+
)
|
|
6126
|
+
);
|
|
6127
|
+
emitter.rethrow();
|
|
6128
|
+
return parseResult(json);
|
|
6129
|
+
}
|
|
6130
|
+
async function cancelImageBuildWith(credentials, selector) {
|
|
6131
|
+
const binding = __imageBuildInternals.loadNativeBinding();
|
|
6132
|
+
let json;
|
|
6133
|
+
try {
|
|
6134
|
+
json = await binding.cancelImageBuild(clientOptions(credentials), {
|
|
6135
|
+
buildId: selector.buildId,
|
|
6136
|
+
clientRequestId: selector.clientRequestId
|
|
6137
|
+
});
|
|
6138
|
+
} catch (error) {
|
|
6139
|
+
throw toImageBuildError(error);
|
|
6140
|
+
}
|
|
6141
|
+
const payload = JSON.parse(json);
|
|
6142
|
+
const outcome = String(payload.outcome ?? "");
|
|
6143
|
+
return {
|
|
6144
|
+
outcome,
|
|
6145
|
+
build: payload.build ? parseBuildInfo(payload.build) : null,
|
|
6146
|
+
confirmed: ["cancelled", "already_cancelled", "already_failed"].includes(outcome)
|
|
6147
|
+
};
|
|
6148
|
+
}
|
|
6149
|
+
async function cancelImageBuild(selector) {
|
|
6150
|
+
const hasBuild = selector.buildId != null;
|
|
6151
|
+
const hasRequest = selector.clientRequestId != null;
|
|
6152
|
+
if (hasBuild === hasRequest) {
|
|
6153
|
+
throw new ImageBuildError({
|
|
6154
|
+
code: "usage",
|
|
6155
|
+
message: "pass exactly one of buildId or clientRequestId"
|
|
6156
|
+
});
|
|
6157
|
+
}
|
|
6158
|
+
if (selector.buildId != null) rejectLegacyReference(selector.buildId);
|
|
6159
|
+
return cancelImageBuildWith(credentialsFromEnv(), selector);
|
|
6160
|
+
}
|
|
6161
|
+
var ImageBuildError, ImageBuildNotFoundError, ImageBuildInProgressError, ImageBuildFailedError, ImageBuildCancelledError, ImageBuildTimeoutError, ImageBuildInterruptedError, ImageBuildHandle;
|
|
6162
|
+
var init_image_builds = __esm({
|
|
6163
|
+
"src/image-builds.ts"() {
|
|
6164
|
+
"use strict";
|
|
6165
|
+
init_esm_shims();
|
|
6166
|
+
init_image();
|
|
6167
|
+
init_sandbox_image();
|
|
6168
|
+
ImageBuildError = class extends Error {
|
|
6169
|
+
code;
|
|
6170
|
+
buildId;
|
|
6171
|
+
clientRequestId;
|
|
6172
|
+
details;
|
|
6173
|
+
constructor(details) {
|
|
6174
|
+
super(details.message);
|
|
6175
|
+
this.name = "ImageBuildError";
|
|
6176
|
+
this.code = details.code;
|
|
6177
|
+
this.details = details;
|
|
6178
|
+
if (details.buildId) this.buildId = details.buildId;
|
|
6179
|
+
if (details.clientRequestId) this.clientRequestId = details.clientRequestId;
|
|
6180
|
+
}
|
|
6181
|
+
};
|
|
6182
|
+
ImageBuildNotFoundError = class extends ImageBuildError {
|
|
6183
|
+
constructor(details) {
|
|
6184
|
+
super(details);
|
|
6185
|
+
this.name = "ImageBuildNotFoundError";
|
|
6186
|
+
}
|
|
6187
|
+
};
|
|
6188
|
+
ImageBuildInProgressError = class extends ImageBuildError {
|
|
6189
|
+
imageName;
|
|
6190
|
+
activeBuildId;
|
|
6191
|
+
activeKind;
|
|
6192
|
+
activeStatus;
|
|
6193
|
+
constructor(details) {
|
|
6194
|
+
super(details);
|
|
6195
|
+
this.name = "ImageBuildInProgressError";
|
|
6196
|
+
if (details.imageName) this.imageName = details.imageName;
|
|
6197
|
+
if (details.activeBuildId) this.activeBuildId = details.activeBuildId;
|
|
6198
|
+
if (details.activeKind) this.activeKind = details.activeKind;
|
|
6199
|
+
if (details.activeStatus) this.activeStatus = details.activeStatus;
|
|
6200
|
+
}
|
|
6201
|
+
};
|
|
6202
|
+
ImageBuildFailedError = class extends ImageBuildError {
|
|
6203
|
+
error;
|
|
6204
|
+
info;
|
|
6205
|
+
constructor(details) {
|
|
6206
|
+
super(details);
|
|
6207
|
+
this.name = "ImageBuildFailedError";
|
|
6208
|
+
this.error = details.error ?? "no error recorded";
|
|
6209
|
+
if (details.info) this.info = parseBuildInfo(details.info);
|
|
6210
|
+
}
|
|
6211
|
+
};
|
|
6212
|
+
ImageBuildCancelledError = class extends ImageBuildError {
|
|
6213
|
+
info;
|
|
6214
|
+
constructor(details) {
|
|
6215
|
+
super(details);
|
|
6216
|
+
this.name = "ImageBuildCancelledError";
|
|
6217
|
+
if (details.info) this.info = parseBuildInfo(details.info);
|
|
6218
|
+
}
|
|
6219
|
+
};
|
|
6220
|
+
ImageBuildTimeoutError = class extends ImageBuildError {
|
|
6221
|
+
constructor(details) {
|
|
6222
|
+
super(details);
|
|
6223
|
+
this.name = "ImageBuildTimeoutError";
|
|
6224
|
+
}
|
|
6225
|
+
};
|
|
6226
|
+
ImageBuildInterruptedError = class extends ImageBuildError {
|
|
6227
|
+
outcome;
|
|
6228
|
+
confirmed;
|
|
6229
|
+
result;
|
|
6230
|
+
constructor(details) {
|
|
6231
|
+
super(details);
|
|
6232
|
+
this.name = "ImageBuildInterruptedError";
|
|
6233
|
+
this.outcome = details.outcome ?? "unconfirmed";
|
|
6234
|
+
this.confirmed = details.confirmed === true;
|
|
6235
|
+
if (details.result) this.result = details.result;
|
|
6236
|
+
}
|
|
6237
|
+
};
|
|
6238
|
+
ImageBuildHandle = class {
|
|
6239
|
+
buildId;
|
|
6240
|
+
/**
|
|
6241
|
+
* The admission's request id, when this handle started the build. Never
|
|
6242
|
+
* needed to cancel; a recovery aid for a lost admission answer.
|
|
6243
|
+
*/
|
|
6244
|
+
clientRequestId;
|
|
6245
|
+
#info;
|
|
6246
|
+
#credentials;
|
|
6247
|
+
/** @internal */
|
|
6248
|
+
constructor(info, credentials, clientRequestId) {
|
|
6249
|
+
this.buildId = info.buildId;
|
|
6250
|
+
this.clientRequestId = clientRequestId ?? info.clientRequestId ?? null;
|
|
6251
|
+
this.#info = info;
|
|
6252
|
+
this.#credentials = credentials;
|
|
6253
|
+
}
|
|
6254
|
+
/** The last observed state. */
|
|
6255
|
+
get info() {
|
|
6256
|
+
return this.#info;
|
|
6257
|
+
}
|
|
6258
|
+
/** Re-read the current state. */
|
|
6259
|
+
async refresh() {
|
|
6260
|
+
const binding = __imageBuildInternals.loadNativeBinding();
|
|
6261
|
+
let json;
|
|
6262
|
+
try {
|
|
6263
|
+
json = await binding.getImageBuild(clientOptions(this.#credentials), this.buildId);
|
|
6264
|
+
} catch (error) {
|
|
6265
|
+
throw toImageBuildError(error);
|
|
6266
|
+
}
|
|
6267
|
+
this.#info = parseBuildInfo(JSON.parse(json));
|
|
6268
|
+
return this.#info;
|
|
6269
|
+
}
|
|
6270
|
+
/**
|
|
6271
|
+
* Wait for publication and return this build's immutable result. See
|
|
6272
|
+
* {@link ImageBuildWaitOptions} for the timeout/abort distinction.
|
|
6273
|
+
*/
|
|
6274
|
+
async wait(options = {}) {
|
|
6275
|
+
const binding = __imageBuildInternals.loadNativeBinding();
|
|
6276
|
+
const emitter = makeEmitter(options);
|
|
6277
|
+
const json = await __runWithInterrupt(
|
|
6278
|
+
options.signal,
|
|
6279
|
+
(interruptId) => binding.waitImageBuild(
|
|
6280
|
+
clientOptions(this.#credentials),
|
|
6281
|
+
this.buildId,
|
|
6282
|
+
{ timeoutMs: options.timeoutMs, followLogs: options.followLogs ?? false },
|
|
6283
|
+
emitter.forward,
|
|
6284
|
+
interruptId
|
|
6285
|
+
)
|
|
6286
|
+
);
|
|
6287
|
+
emitter.rethrow();
|
|
6288
|
+
const result = parseResult(json);
|
|
6289
|
+
this.#info = { ...this.#info, status: "succeeded", result };
|
|
6290
|
+
return result;
|
|
6291
|
+
}
|
|
6292
|
+
/** Cancel this build by its id (the sufficient selector). */
|
|
6293
|
+
async cancel() {
|
|
6294
|
+
return cancelImageBuildWith(this.#credentials, { buildId: this.buildId });
|
|
6295
|
+
}
|
|
6296
|
+
};
|
|
6297
|
+
}
|
|
6298
|
+
});
|
|
6299
|
+
|
|
6565
6300
|
// src/sandbox-image.ts
|
|
6566
6301
|
var sandbox_image_exports = {};
|
|
6567
6302
|
__export(sandbox_image_exports, {
|
|
6303
|
+
__imageBuildInternals: () => __imageBuildInternals,
|
|
6568
6304
|
__setNativeBindingForTest: () => __setNativeBindingForTest,
|
|
6569
6305
|
buildContextFromEnv: () => buildContextFromEnv,
|
|
6570
6306
|
createSandboxImage: () => createSandboxImage,
|
|
6571
6307
|
deleteSandboxImage: () => deleteSandboxImage,
|
|
6308
|
+
deleteSandboxImageWithCredentials: () => deleteSandboxImageWithCredentials,
|
|
6572
6309
|
findSandboxImageByName: () => findSandboxImageByName,
|
|
6310
|
+
findSandboxImageByNameWithCredentials: () => findSandboxImageByNameWithCredentials,
|
|
6573
6311
|
importSandboxImage: () => importSandboxImage,
|
|
6574
6312
|
listSandboxImages: () => listSandboxImages,
|
|
6313
|
+
listSandboxImagesWithCredentials: () => listSandboxImagesWithCredentials,
|
|
6575
6314
|
runCreateSandboxImageCli: () => runCreateSandboxImageCli,
|
|
6576
6315
|
runImportSandboxImageCli: () => runImportSandboxImageCli
|
|
6577
6316
|
});
|
|
6578
|
-
import
|
|
6579
|
-
import
|
|
6580
|
-
import { existsSync as
|
|
6317
|
+
import path4 from "path";
|
|
6318
|
+
import os2 from "os";
|
|
6319
|
+
import { existsSync as existsSync3, mkdtempSync as mkdtempSync2, rmSync as rmSync2 } from "fs";
|
|
6581
6320
|
import { parseArgs } from "util";
|
|
6582
6321
|
function loadNativeBinding() {
|
|
6583
6322
|
if (cachedNativeBinding) return cachedNativeBinding;
|
|
@@ -6611,9 +6350,9 @@ function buildContextFromEnv() {
|
|
|
6611
6350
|
};
|
|
6612
6351
|
}
|
|
6613
6352
|
function defaultRegisteredName(dockerfilePath) {
|
|
6614
|
-
const parsed =
|
|
6353
|
+
const parsed = path4.parse(dockerfilePath);
|
|
6615
6354
|
if (parsed.name.toLowerCase() === "dockerfile") {
|
|
6616
|
-
const parentName =
|
|
6355
|
+
const parentName = path4.basename(path4.dirname(dockerfilePath)).trim();
|
|
6617
6356
|
return parentName || "sandbox-image";
|
|
6618
6357
|
}
|
|
6619
6358
|
return parsed.name || "sandbox-image";
|
|
@@ -6649,6 +6388,15 @@ function eventToEmitDict(event) {
|
|
|
6649
6388
|
message: event.message
|
|
6650
6389
|
};
|
|
6651
6390
|
if (event.stream != null) out.stream = event.stream;
|
|
6391
|
+
if (event.buildId != null) out.build_id = event.buildId;
|
|
6392
|
+
if (event.clientRequestId !== void 0 && event.eventType !== "status") {
|
|
6393
|
+
out.client_request_id = event.clientRequestId;
|
|
6394
|
+
}
|
|
6395
|
+
if (event.status != null) out.status = event.status;
|
|
6396
|
+
if (event.phase !== void 0 && event.eventType.startsWith("build_")) out.phase = event.phase;
|
|
6397
|
+
if (event.attempt != null) out.attempt = event.attempt;
|
|
6398
|
+
if (event.outcome != null) out.outcome = event.outcome;
|
|
6399
|
+
if (event.confirmed != null) out.confirmed = event.confirmed;
|
|
6652
6400
|
return out;
|
|
6653
6401
|
}
|
|
6654
6402
|
function runOpMountsContext(op) {
|
|
@@ -6703,24 +6451,24 @@ async function createSandboxImage(source, options = {}, deps = {}) {
|
|
|
6703
6451
|
}
|
|
6704
6452
|
let resolvedContext;
|
|
6705
6453
|
if (options.contextDir != null) {
|
|
6706
|
-
resolvedContext =
|
|
6454
|
+
resolvedContext = path4.resolve(options.contextDir);
|
|
6707
6455
|
} else if (imageRequiresContext(source)) {
|
|
6708
6456
|
throw new Error(
|
|
6709
6457
|
"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>`."
|
|
6710
6458
|
);
|
|
6711
6459
|
} else {
|
|
6712
|
-
tempContextDir =
|
|
6460
|
+
tempContextDir = mkdtempSync2(path4.join(os2.tmpdir(), "tl-build-context-"));
|
|
6713
6461
|
resolvedContext = tempContextDir;
|
|
6714
6462
|
}
|
|
6715
|
-
dockerfilePath =
|
|
6463
|
+
dockerfilePath = path4.join(resolvedContext, "Dockerfile");
|
|
6716
6464
|
let text = dockerfileContent(source);
|
|
6717
6465
|
if (!text.endsWith("\n")) text += "\n";
|
|
6718
6466
|
dockerfileText = text;
|
|
6719
6467
|
nativeContextDir = resolvedContext;
|
|
6720
6468
|
effectiveName = options.registeredName ?? source.name;
|
|
6721
6469
|
} else if (typeof source === "string") {
|
|
6722
|
-
const resolvedPath =
|
|
6723
|
-
if (!
|
|
6470
|
+
const resolvedPath = path4.resolve(source);
|
|
6471
|
+
if (!existsSync3(resolvedPath)) {
|
|
6724
6472
|
throw new Error(`Dockerfile not found: ${source}`);
|
|
6725
6473
|
}
|
|
6726
6474
|
dockerfilePath = resolvedPath;
|
|
@@ -6750,38 +6498,47 @@ async function createSandboxImage(source, options = {}, deps = {}) {
|
|
|
6750
6498
|
deps._allowPat ? "Missing TENSORLAKE_API_KEY or TENSORLAKE_PAT credentials." : "Missing TENSORLAKE_API_KEY credentials."
|
|
6751
6499
|
);
|
|
6752
6500
|
}
|
|
6501
|
+
if (options.signal !== void 0 && !options.cas) {
|
|
6502
|
+
throw new Error(
|
|
6503
|
+
"signal is only supported for CAS image builds (cas: true); a legacy build has no Image Service build operation to cancel"
|
|
6504
|
+
);
|
|
6505
|
+
}
|
|
6753
6506
|
emit({ type: "status", message: `Building image '${effectiveName}'...` });
|
|
6754
6507
|
const binding = loadNativeBinding();
|
|
6755
6508
|
let emitError;
|
|
6756
|
-
const
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6509
|
+
const nativeOptions = {
|
|
6510
|
+
apiUrl: context.apiUrl,
|
|
6511
|
+
bearerToken,
|
|
6512
|
+
dockerfilePath,
|
|
6513
|
+
registeredName: effectiveName,
|
|
6514
|
+
diskMb: options.diskMb,
|
|
6515
|
+
builderDiskMb: options.builderDiskMb,
|
|
6516
|
+
cpus: options.cpus,
|
|
6517
|
+
memoryMb: options.memoryMb,
|
|
6518
|
+
isPublic: options.isPublic ?? false,
|
|
6519
|
+
organizationId: usePat ? context.organizationId : void 0,
|
|
6520
|
+
projectId: usePat ? context.projectId : void 0,
|
|
6521
|
+
namespace: context.namespace,
|
|
6522
|
+
useScopeHeaders: usePat,
|
|
6523
|
+
userAgent: void 0,
|
|
6524
|
+
dockerCompat: options.dockerCompat ?? false,
|
|
6525
|
+
dockerConfigJson: options.dockerConfigJson,
|
|
6526
|
+
dockerfileText,
|
|
6527
|
+
contextDir: nativeContextDir,
|
|
6528
|
+
cas: options.cas ?? false,
|
|
6529
|
+
buildArgs: options.buildArgs
|
|
6530
|
+
};
|
|
6531
|
+
const forward = (event) => {
|
|
6532
|
+
try {
|
|
6533
|
+
emit(eventToEmitDict(event));
|
|
6534
|
+
} catch (error) {
|
|
6535
|
+
emitError ??= error;
|
|
6783
6536
|
}
|
|
6784
|
-
|
|
6537
|
+
};
|
|
6538
|
+
const resultJson = options.cas ? await __runWithInterrupt(
|
|
6539
|
+
options.signal,
|
|
6540
|
+
(interruptId) => binding.buildSandboxImage(nativeOptions, forward, interruptId)
|
|
6541
|
+
) : await binding.buildSandboxImage(nativeOptions, forward);
|
|
6785
6542
|
if (emitError != null) {
|
|
6786
6543
|
throw emitError;
|
|
6787
6544
|
}
|
|
@@ -6798,7 +6555,7 @@ async function createSandboxImage(source, options = {}, deps = {}) {
|
|
|
6798
6555
|
return result;
|
|
6799
6556
|
} finally {
|
|
6800
6557
|
if (tempContextDir != null) {
|
|
6801
|
-
|
|
6558
|
+
rmSync2(tempContextDir, { recursive: true, force: true });
|
|
6802
6559
|
}
|
|
6803
6560
|
}
|
|
6804
6561
|
}
|
|
@@ -6827,39 +6584,47 @@ async function importSandboxImage(imageReference, options = {}, deps = {}) {
|
|
|
6827
6584
|
deps._allowPat ? "Missing TENSORLAKE_API_KEY or TENSORLAKE_PAT credentials." : "Missing TENSORLAKE_API_KEY credentials."
|
|
6828
6585
|
);
|
|
6829
6586
|
}
|
|
6587
|
+
if (options.signal !== void 0 && !options.cas) {
|
|
6588
|
+
throw new Error(
|
|
6589
|
+
"signal is only supported for CAS image imports (cas: true); a legacy import has no Image Service build operation to cancel"
|
|
6590
|
+
);
|
|
6591
|
+
}
|
|
6830
6592
|
emit({
|
|
6831
6593
|
type: "status",
|
|
6832
6594
|
message: `Importing image '${reference}' as '${effectiveName}'...`
|
|
6833
6595
|
});
|
|
6834
6596
|
const binding = loadNativeBinding();
|
|
6835
6597
|
let emitError;
|
|
6836
|
-
const
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
|
|
6853
|
-
|
|
6854
|
-
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
}
|
|
6598
|
+
const nativeOptions = {
|
|
6599
|
+
apiUrl: context.apiUrl,
|
|
6600
|
+
bearerToken,
|
|
6601
|
+
imageReference: reference,
|
|
6602
|
+
registeredName: effectiveName,
|
|
6603
|
+
diskMb: options.diskMb,
|
|
6604
|
+
builderDiskMb: options.builderDiskMb,
|
|
6605
|
+
cpus: options.cpus,
|
|
6606
|
+
memoryMb: options.memoryMb,
|
|
6607
|
+
isPublic: options.isPublic ?? false,
|
|
6608
|
+
organizationId: usePat ? context.organizationId : void 0,
|
|
6609
|
+
projectId: usePat ? context.projectId : void 0,
|
|
6610
|
+
namespace: context.namespace,
|
|
6611
|
+
useScopeHeaders: usePat,
|
|
6612
|
+
userAgent: void 0,
|
|
6613
|
+
dockerCompat: options.dockerCompat ?? false,
|
|
6614
|
+
dockerConfigJson: options.dockerConfigJson,
|
|
6615
|
+
cas: options.cas ?? false
|
|
6616
|
+
};
|
|
6617
|
+
const forward = (event) => {
|
|
6618
|
+
try {
|
|
6619
|
+
emit(eventToEmitDict(event));
|
|
6620
|
+
} catch (error) {
|
|
6621
|
+
emitError ??= error;
|
|
6861
6622
|
}
|
|
6862
|
-
|
|
6623
|
+
};
|
|
6624
|
+
const resultJson = options.cas ? await __runWithInterrupt(
|
|
6625
|
+
options.signal,
|
|
6626
|
+
(interruptId) => binding.importSandboxImage(nativeOptions, forward, interruptId)
|
|
6627
|
+
) : await binding.importSandboxImage(nativeOptions, forward);
|
|
6863
6628
|
if (emitError != null) {
|
|
6864
6629
|
throw emitError;
|
|
6865
6630
|
}
|
|
@@ -6875,10 +6640,7 @@ async function importSandboxImage(imageReference, options = {}, deps = {}) {
|
|
|
6875
6640
|
emit({ type: "done" });
|
|
6876
6641
|
return result;
|
|
6877
6642
|
}
|
|
6878
|
-
|
|
6879
|
-
if (typeof imageName !== "string" || imageName.length === 0) {
|
|
6880
|
-
throw new TypeError("imageName must be a non-empty string");
|
|
6881
|
-
}
|
|
6643
|
+
function catalogOptionsFromEnv() {
|
|
6882
6644
|
const context = buildContextFromEnv();
|
|
6883
6645
|
const bearerToken = context.apiKey;
|
|
6884
6646
|
if (!bearerToken) {
|
|
@@ -6889,63 +6651,73 @@ async function deleteSandboxImage(imageName) {
|
|
|
6889
6651
|
}
|
|
6890
6652
|
throw new Error("Missing TENSORLAKE_API_KEY credentials.");
|
|
6891
6653
|
}
|
|
6892
|
-
|
|
6893
|
-
apiUrl: context.apiUrl,
|
|
6894
|
-
apiKey: bearerToken,
|
|
6895
|
-
namespace: context.namespace
|
|
6896
|
-
});
|
|
6897
|
-
try {
|
|
6898
|
-
await client.deleteSandboxImage(imageName);
|
|
6899
|
-
} finally {
|
|
6900
|
-
client.close();
|
|
6901
|
-
}
|
|
6654
|
+
return { apiUrl: context.apiUrl, bearerToken, useScopeHeaders: false };
|
|
6902
6655
|
}
|
|
6903
|
-
|
|
6904
|
-
if (typeof imageName !== "string" || imageName.length === 0) {
|
|
6905
|
-
throw new TypeError("imageName must be a non-empty string");
|
|
6906
|
-
}
|
|
6656
|
+
function catalogOptionsFromCredentials(credentials) {
|
|
6907
6657
|
const context = buildContextFromEnv();
|
|
6908
|
-
const bearerToken = context.apiKey;
|
|
6658
|
+
const bearerToken = credentials.apiKey ?? context.apiKey;
|
|
6909
6659
|
if (!bearerToken) {
|
|
6910
|
-
if (context.personalAccessToken) {
|
|
6911
|
-
throw new Error(
|
|
6912
|
-
"Sandbox image SDKs require TENSORLAKE_API_KEY. Personal access tokens are CLI-only."
|
|
6913
|
-
);
|
|
6914
|
-
}
|
|
6915
6660
|
throw new Error("Missing TENSORLAKE_API_KEY credentials.");
|
|
6916
6661
|
}
|
|
6917
|
-
const
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
namespace: context.namespace
|
|
6921
|
-
});
|
|
6922
|
-
try {
|
|
6923
|
-
return await client.findSandboxImageByName(imageName);
|
|
6924
|
-
} finally {
|
|
6925
|
-
client.close();
|
|
6662
|
+
const { organizationId, projectId } = credentials;
|
|
6663
|
+
if (organizationId === void 0 !== (projectId === void 0)) {
|
|
6664
|
+
throw new TypeError("organizationId and projectId must be given together");
|
|
6926
6665
|
}
|
|
6666
|
+
return {
|
|
6667
|
+
apiUrl: credentials.apiUrl ?? context.apiUrl,
|
|
6668
|
+
bearerToken,
|
|
6669
|
+
organizationId,
|
|
6670
|
+
projectId,
|
|
6671
|
+
useScopeHeaders: organizationId !== void 0
|
|
6672
|
+
};
|
|
6927
6673
|
}
|
|
6928
|
-
|
|
6929
|
-
|
|
6930
|
-
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
"Sandbox image SDKs require TENSORLAKE_API_KEY. Personal access tokens are CLI-only."
|
|
6935
|
-
);
|
|
6936
|
-
}
|
|
6937
|
-
throw new Error("Missing TENSORLAKE_API_KEY credentials.");
|
|
6674
|
+
function parseTemplate(json) {
|
|
6675
|
+
return JSON.parse(json);
|
|
6676
|
+
}
|
|
6677
|
+
async function deleteSandboxImage(imageName) {
|
|
6678
|
+
if (typeof imageName !== "string" || imageName.length === 0) {
|
|
6679
|
+
throw new TypeError("imageName must be a non-empty string");
|
|
6938
6680
|
}
|
|
6939
|
-
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
|
|
6945
|
-
|
|
6946
|
-
|
|
6947
|
-
|
|
6681
|
+
await loadNativeBinding().deleteSandboxImage(catalogOptionsFromEnv(), imageName);
|
|
6682
|
+
}
|
|
6683
|
+
async function deleteSandboxImageWithCredentials(credentials, imageName) {
|
|
6684
|
+
if (typeof imageName !== "string" || imageName.length === 0) {
|
|
6685
|
+
throw new TypeError("imageName must be a non-empty string");
|
|
6686
|
+
}
|
|
6687
|
+
await loadNativeBinding().deleteSandboxImage(
|
|
6688
|
+
catalogOptionsFromCredentials(credentials),
|
|
6689
|
+
imageName
|
|
6690
|
+
);
|
|
6691
|
+
}
|
|
6692
|
+
async function findSandboxImageByName(imageName) {
|
|
6693
|
+
if (typeof imageName !== "string" || imageName.length === 0) {
|
|
6694
|
+
throw new TypeError("imageName must be a non-empty string");
|
|
6695
|
+
}
|
|
6696
|
+
const json = await loadNativeBinding().findSandboxImage(
|
|
6697
|
+
catalogOptionsFromEnv(),
|
|
6698
|
+
imageName
|
|
6699
|
+
);
|
|
6700
|
+
return json == null ? null : parseTemplate(json);
|
|
6701
|
+
}
|
|
6702
|
+
async function findSandboxImageByNameWithCredentials(credentials, imageName) {
|
|
6703
|
+
if (typeof imageName !== "string" || imageName.length === 0) {
|
|
6704
|
+
throw new TypeError("imageName must be a non-empty string");
|
|
6948
6705
|
}
|
|
6706
|
+
const json = await loadNativeBinding().findSandboxImage(
|
|
6707
|
+
catalogOptionsFromCredentials(credentials),
|
|
6708
|
+
imageName
|
|
6709
|
+
);
|
|
6710
|
+
return json == null ? null : parseTemplate(json);
|
|
6711
|
+
}
|
|
6712
|
+
async function listSandboxImages() {
|
|
6713
|
+
const json = await loadNativeBinding().listSandboxImages(catalogOptionsFromEnv());
|
|
6714
|
+
return JSON.parse(json);
|
|
6715
|
+
}
|
|
6716
|
+
async function listSandboxImagesWithCredentials(credentials) {
|
|
6717
|
+
const json = await loadNativeBinding().listSandboxImages(
|
|
6718
|
+
catalogOptionsFromCredentials(credentials)
|
|
6719
|
+
);
|
|
6720
|
+
return JSON.parse(json);
|
|
6949
6721
|
}
|
|
6950
6722
|
async function runCreateSandboxImageCli(argv = process.argv.slice(2)) {
|
|
6951
6723
|
const parsed = parseArgs({
|
|
@@ -7055,15 +6827,25 @@ async function runImportSandboxImageCli(argv = process.argv.slice(2)) {
|
|
|
7055
6827
|
{ emit: ndjsonStdoutEmit, _allowPat: true }
|
|
7056
6828
|
);
|
|
7057
6829
|
}
|
|
7058
|
-
var cachedNativeBinding, cachedNativeBindingError, DEFAULT_IMAGE_NAME2;
|
|
6830
|
+
var cachedNativeBinding, cachedNativeBindingError, DEFAULT_IMAGE_NAME2, __imageBuildInternals;
|
|
7059
6831
|
var init_sandbox_image = __esm({
|
|
7060
6832
|
"src/sandbox-image.ts"() {
|
|
7061
6833
|
"use strict";
|
|
7062
6834
|
init_esm_shims();
|
|
7063
|
-
init_cloud_client();
|
|
7064
6835
|
init_image();
|
|
7065
6836
|
init_native_binding();
|
|
6837
|
+
init_image_builds();
|
|
7066
6838
|
DEFAULT_IMAGE_NAME2 = "default";
|
|
6839
|
+
__imageBuildInternals = {
|
|
6840
|
+
loadNativeBinding: () => loadNativeBinding(),
|
|
6841
|
+
buildContextFromEnv: () => buildContextFromEnv(),
|
|
6842
|
+
stderrEmit: (event) => stderrEmit(event),
|
|
6843
|
+
noopEmit: (event) => noopEmit(event),
|
|
6844
|
+
eventToEmitDict: (event) => eventToEmitDict(event),
|
|
6845
|
+
imageRequiresContext: (image) => imageRequiresContext(image),
|
|
6846
|
+
defaultRegisteredName: (dockerfilePath) => defaultRegisteredName(dockerfilePath),
|
|
6847
|
+
defaultRegisteredNameFromImage: (reference) => defaultRegisteredNameFromImage(reference)
|
|
6848
|
+
};
|
|
7067
6849
|
}
|
|
7068
6850
|
});
|
|
7069
6851
|
|
|
@@ -7075,11 +6857,546 @@ init_pending_sandbox();
|
|
|
7075
6857
|
init_sandbox();
|
|
7076
6858
|
init_desktop();
|
|
7077
6859
|
init_tunnel();
|
|
7078
|
-
|
|
6860
|
+
|
|
6861
|
+
// src/cloud-client.ts
|
|
6862
|
+
init_esm_shims();
|
|
6863
|
+
init_defaults();
|
|
6864
|
+
import { nanoid } from "nanoid";
|
|
6865
|
+
|
|
6866
|
+
// src/native-cloud.ts
|
|
6867
|
+
init_esm_shims();
|
|
6868
|
+
init_native_sandbox();
|
|
6869
|
+
init_native_worker_client();
|
|
6870
|
+
var NativeCloudTransport = class {
|
|
6871
|
+
constructor(options) {
|
|
6872
|
+
this.options = options;
|
|
6873
|
+
if (!Number.isSafeInteger(options.maxRetries) || options.maxRetries < 0 || options.maxRetries > 4294967295) {
|
|
6874
|
+
throw new RangeError("maxRetries must be a non-negative 32-bit integer");
|
|
6875
|
+
}
|
|
6876
|
+
if (!Number.isFinite(options.retryBackoffMs) || options.retryBackoffMs < 0) {
|
|
6877
|
+
throw new RangeError("retryBackoffMs must be a non-negative finite number");
|
|
6878
|
+
}
|
|
6879
|
+
}
|
|
6880
|
+
native;
|
|
6881
|
+
closed = false;
|
|
6882
|
+
client() {
|
|
6883
|
+
if (this.closed) throw new Error("Tensorlake native client is closed");
|
|
6884
|
+
if (this.native) return this.native;
|
|
6885
|
+
const ctor = loadNativeSandboxBinding().NativeCloudClient;
|
|
6886
|
+
if (!ctor) throw new Error("Native binding does not export NativeCloudClient; rebuild with 'npm run build:native'");
|
|
6887
|
+
return this.native = new ctor(JSON.stringify(this.options));
|
|
6888
|
+
}
|
|
6889
|
+
close() {
|
|
6890
|
+
this.closed = true;
|
|
6891
|
+
releaseNativeHandle(this.native ?? null);
|
|
6892
|
+
this.native = void 0;
|
|
6893
|
+
}
|
|
6894
|
+
async requestResponse(method, path5, options) {
|
|
6895
|
+
const request = await serializeRequest(method, path5, options);
|
|
6896
|
+
const raw = await callNative(() => this.client().request(request));
|
|
6897
|
+
const response = new Response(
|
|
6898
|
+
[204, 205, 304].includes(raw.status) ? null : Uint8Array.from(raw.data).buffer,
|
|
6899
|
+
{ status: raw.status, headers: JSON.parse(raw.headersJson) }
|
|
6900
|
+
);
|
|
6901
|
+
return Object.assign(response, { traceId: raw.traceId });
|
|
6902
|
+
}
|
|
6903
|
+
async requestJson(method, path5) {
|
|
6904
|
+
const response = await this.requestResponse(method, path5);
|
|
6905
|
+
const text = await response.text();
|
|
6906
|
+
const value = text ? JSON.parse(text) : null;
|
|
6907
|
+
return Object.assign(value ?? {}, { traceId: response.traceId });
|
|
6908
|
+
}
|
|
6909
|
+
async *stream(method, path5, signal) {
|
|
6910
|
+
if (signal?.aborted) return;
|
|
6911
|
+
const request = await serializeRequest(method, path5, { headers: { Accept: "text/event-stream" } });
|
|
6912
|
+
yield* nativeEventStream((emit) => this.client().stream(request, emit), void 0, signal);
|
|
6913
|
+
}
|
|
6914
|
+
};
|
|
6915
|
+
async function serializeRequest(method, path5, options) {
|
|
6916
|
+
const headers = { ...options?.headers };
|
|
6917
|
+
let body = options?.body;
|
|
6918
|
+
if (options?.json !== void 0) {
|
|
6919
|
+
body = JSON.stringify(options.json);
|
|
6920
|
+
if (!Object.keys(headers).some((key) => key.toLowerCase() === "content-type")) {
|
|
6921
|
+
headers["Content-Type"] = "application/json";
|
|
6922
|
+
}
|
|
6923
|
+
}
|
|
6924
|
+
const request = {
|
|
6925
|
+
method,
|
|
6926
|
+
path: path5,
|
|
6927
|
+
headersJson: JSON.stringify(headers),
|
|
6928
|
+
statusOnlyCodes: [...options?.statusOnlyCodes ?? []]
|
|
6929
|
+
};
|
|
6930
|
+
if (body instanceof FormData) {
|
|
6931
|
+
request.parts = [];
|
|
6932
|
+
for (const [name, value] of body.entries()) {
|
|
6933
|
+
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" });
|
|
6934
|
+
}
|
|
6935
|
+
} else if (body !== void 0) {
|
|
6936
|
+
if (body instanceof Blob) request.body = Buffer.from(await body.arrayBuffer());
|
|
6937
|
+
else if (typeof body === "string") request.body = Buffer.from(body);
|
|
6938
|
+
else if (body instanceof ArrayBuffer) request.body = Buffer.from(new Uint8Array(body));
|
|
6939
|
+
else request.body = Buffer.from(body);
|
|
6940
|
+
}
|
|
6941
|
+
return request;
|
|
6942
|
+
}
|
|
6943
|
+
|
|
6944
|
+
// src/cloud-client.ts
|
|
6945
|
+
init_models();
|
|
6946
|
+
init_sandbox_image();
|
|
6947
|
+
var CloudClient = class _CloudClient {
|
|
6948
|
+
transport;
|
|
6949
|
+
apiUrl;
|
|
6950
|
+
apiKey;
|
|
6951
|
+
organizationId;
|
|
6952
|
+
projectId;
|
|
6953
|
+
namespace;
|
|
6954
|
+
constructor(options) {
|
|
6955
|
+
this.apiUrl = options?.apiUrl ?? API_URL;
|
|
6956
|
+
this.apiKey = options?.apiKey ?? API_KEY;
|
|
6957
|
+
this.organizationId = options?.organizationId;
|
|
6958
|
+
this.projectId = options?.projectId;
|
|
6959
|
+
this.namespace = options?.namespace ?? NAMESPACE;
|
|
6960
|
+
this.transport = new NativeCloudTransport({
|
|
6961
|
+
baseUrl: options?.apiUrl ?? API_URL,
|
|
6962
|
+
apiKey: options?.apiKey ?? API_KEY,
|
|
6963
|
+
organizationId: this.organizationId,
|
|
6964
|
+
projectId: this.projectId,
|
|
6965
|
+
maxRetries: options?.maxRetries ?? MAX_RETRIES,
|
|
6966
|
+
retryBackoffMs: options?.retryBackoffMs ?? RETRY_BACKOFF_MS,
|
|
6967
|
+
timeoutMs: DEFAULT_HTTP_TIMEOUT_MS,
|
|
6968
|
+
userAgent: `tensorlake-typescript-sdk/${SDK_VERSION}`
|
|
6969
|
+
});
|
|
6970
|
+
}
|
|
6971
|
+
static forCloud(options) {
|
|
6972
|
+
return new _CloudClient(options);
|
|
6973
|
+
}
|
|
6974
|
+
close() {
|
|
6975
|
+
this.transport.close();
|
|
6976
|
+
}
|
|
6977
|
+
async upsertApplication(manifest, codeZip, upgradeRunningRequests = false) {
|
|
6978
|
+
const applicationManifest = { ...manifest };
|
|
6979
|
+
let publicEndpointId = publicEndpointIdFromManifest(applicationManifest);
|
|
6980
|
+
if (applicationAllowsUnauthenticatedRequests(applicationManifest) && publicEndpointId === void 0) {
|
|
6981
|
+
const applicationName = applicationManifest.name;
|
|
6982
|
+
if (typeof applicationName === "string" && applicationName.length > 0) {
|
|
6983
|
+
publicEndpointId = await this.existingApplicationPublicEndpointId(applicationName);
|
|
6984
|
+
}
|
|
6985
|
+
publicEndpointId ??= generatePublicEndpointId();
|
|
6986
|
+
}
|
|
6987
|
+
if (publicEndpointId !== void 0) {
|
|
6988
|
+
applicationManifest.public_endpoint_id = publicEndpointId;
|
|
6989
|
+
delete applicationManifest.publicEndpointId;
|
|
6990
|
+
}
|
|
6991
|
+
const form = new FormData();
|
|
6992
|
+
form.append(
|
|
6993
|
+
"code",
|
|
6994
|
+
new Blob([toBlobPart(codeZip)], { type: "application/zip" }),
|
|
6995
|
+
"code.zip"
|
|
6996
|
+
);
|
|
6997
|
+
form.append("code_content_type", "application/zip");
|
|
6998
|
+
form.append("application", JSON.stringify(applicationManifest));
|
|
6999
|
+
form.append(
|
|
7000
|
+
"upgrade_requests_to_latest_code",
|
|
7001
|
+
String(upgradeRunningRequests)
|
|
7002
|
+
);
|
|
7003
|
+
await this.transport.requestResponse("POST", this.namespacePath("applications"), {
|
|
7004
|
+
body: form
|
|
7005
|
+
});
|
|
7006
|
+
}
|
|
7007
|
+
async deleteApplication(applicationName) {
|
|
7008
|
+
await this.transport.requestResponse(
|
|
7009
|
+
"DELETE",
|
|
7010
|
+
this.namespacePath(`applications/${encodeURIComponent(applicationName)}`)
|
|
7011
|
+
);
|
|
7012
|
+
}
|
|
7013
|
+
/**
|
|
7014
|
+
* Delete a registered sandbox image by name or id through the merged
|
|
7015
|
+
* catalog, with this client's credentials: an `image_` id or a name the
|
|
7016
|
+
* Image Service knows deletes a CAS image, a `sandbox_template_` id or a
|
|
7017
|
+
* name registered only in the platform registry deletes a legacy image.
|
|
7018
|
+
* Rejects when neither catalog knows the reference. The same semantics
|
|
7019
|
+
* and accepted differences as the module-level `deleteSandboxImage`.
|
|
7020
|
+
*/
|
|
7021
|
+
async deleteSandboxImage(imageName) {
|
|
7022
|
+
await deleteSandboxImageWithCredentials(this.catalogCredentials(), imageName);
|
|
7023
|
+
}
|
|
7024
|
+
/**
|
|
7025
|
+
* Look up a registered sandbox image by name or id through the merged
|
|
7026
|
+
* catalog, with this client's credentials. Returns the image in the
|
|
7027
|
+
* sandbox-template shape, or `null` when neither the Image Service nor the
|
|
7028
|
+
* platform registry knows the reference. An explicit organization/project
|
|
7029
|
+
* scope (the client's, or the call's override) addresses that project's
|
|
7030
|
+
* routes directly, as before; without one the key's own scope applies.
|
|
7031
|
+
*/
|
|
7032
|
+
async findSandboxImageByName(imageName, options) {
|
|
7033
|
+
return findSandboxImageByNameWithCredentials(
|
|
7034
|
+
this.catalogCredentials(options),
|
|
7035
|
+
imageName
|
|
7036
|
+
);
|
|
7037
|
+
}
|
|
7038
|
+
/**
|
|
7039
|
+
* List every registered sandbox image of the project (CAS and legacy, in
|
|
7040
|
+
* the sandbox-template shape, newest first) through the merged catalog,
|
|
7041
|
+
* with this client's credentials. An explicit organization/project scope
|
|
7042
|
+
* (the client's, or the call's override) addresses that project's routes
|
|
7043
|
+
* directly, as before; without one the key's own scope applies.
|
|
7044
|
+
*/
|
|
7045
|
+
async listSandboxImages(options) {
|
|
7046
|
+
return listSandboxImagesWithCredentials(this.catalogCredentials(options));
|
|
7047
|
+
}
|
|
7048
|
+
catalogCredentials(options) {
|
|
7049
|
+
return {
|
|
7050
|
+
apiUrl: this.apiUrl,
|
|
7051
|
+
apiKey: this.apiKey,
|
|
7052
|
+
organizationId: options?.organizationId ?? this.organizationId,
|
|
7053
|
+
projectId: options?.projectId ?? this.projectId
|
|
7054
|
+
};
|
|
7055
|
+
}
|
|
7056
|
+
async applications() {
|
|
7057
|
+
const raw = await this.transport.requestJson(
|
|
7058
|
+
"GET",
|
|
7059
|
+
this.namespacePath("applications")
|
|
7060
|
+
);
|
|
7061
|
+
return (raw.applications ?? []).map(
|
|
7062
|
+
(application) => fromSnakeKeys(application)
|
|
7063
|
+
);
|
|
7064
|
+
}
|
|
7065
|
+
async applicationManifest(applicationName) {
|
|
7066
|
+
const raw = await this.transport.requestJson(
|
|
7067
|
+
"GET",
|
|
7068
|
+
this.namespacePath(`applications/${encodeURIComponent(applicationName)}`)
|
|
7069
|
+
);
|
|
7070
|
+
return fromSnakeKeys(raw);
|
|
7071
|
+
}
|
|
7072
|
+
async runRequest(applicationName, inputs = []) {
|
|
7073
|
+
const path5 = this.namespacePath(
|
|
7074
|
+
`applications/${encodeURIComponent(applicationName)}`
|
|
7075
|
+
);
|
|
7076
|
+
const response = inputs.length === 0 ? await this.transport.requestResponse("POST", path5, {
|
|
7077
|
+
body: new Uint8Array(),
|
|
7078
|
+
headers: { Accept: "application/json" }
|
|
7079
|
+
}) : inputs.length === 1 && inputs[0].name === "0" ? await this.transport.requestResponse("POST", path5, {
|
|
7080
|
+
body: toRequestBody(inputs[0].data),
|
|
7081
|
+
headers: {
|
|
7082
|
+
Accept: "application/json",
|
|
7083
|
+
"Content-Type": inputs[0].contentType
|
|
7084
|
+
}
|
|
7085
|
+
}) : await this.runMultipartRequest(path5, inputs);
|
|
7086
|
+
const body = await parseJsonResponse(response);
|
|
7087
|
+
const requestId = body?.request_id;
|
|
7088
|
+
if (!requestId) {
|
|
7089
|
+
throw new Error("missing request_id in run request response body");
|
|
7090
|
+
}
|
|
7091
|
+
return requestId;
|
|
7092
|
+
}
|
|
7093
|
+
async waitOnRequestCompletion(applicationName, requestId) {
|
|
7094
|
+
const stream = this.transport.stream(
|
|
7095
|
+
"GET",
|
|
7096
|
+
this.namespacePath(
|
|
7097
|
+
`applications/${encodeURIComponent(applicationName)}/requests/${encodeURIComponent(requestId)}/progress`
|
|
7098
|
+
)
|
|
7099
|
+
);
|
|
7100
|
+
for await (const event of stream) {
|
|
7101
|
+
if (Object.prototype.hasOwnProperty.call(event, "RequestFinished")) {
|
|
7102
|
+
return;
|
|
7103
|
+
}
|
|
7104
|
+
}
|
|
7105
|
+
throw new Error("progress stream ended before request completion");
|
|
7106
|
+
}
|
|
7107
|
+
async requestMetadata(applicationName, requestId) {
|
|
7108
|
+
const raw = await this.transport.requestJson(
|
|
7109
|
+
"GET",
|
|
7110
|
+
this.namespacePath(
|
|
7111
|
+
`applications/${encodeURIComponent(applicationName)}/requests/${encodeURIComponent(requestId)}`
|
|
7112
|
+
)
|
|
7113
|
+
);
|
|
7114
|
+
return fromSnakeKeys(raw);
|
|
7115
|
+
}
|
|
7116
|
+
async requestOutput(applicationName, requestId) {
|
|
7117
|
+
const response = await this.transport.requestResponse(
|
|
7118
|
+
"GET",
|
|
7119
|
+
this.namespacePath(
|
|
7120
|
+
`applications/${encodeURIComponent(applicationName)}/requests/${encodeURIComponent(requestId)}/output`
|
|
7121
|
+
)
|
|
7122
|
+
);
|
|
7123
|
+
const serializedValue = new Uint8Array(await response.arrayBuffer());
|
|
7124
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
7125
|
+
return {
|
|
7126
|
+
serializedValue,
|
|
7127
|
+
contentType
|
|
7128
|
+
};
|
|
7129
|
+
}
|
|
7130
|
+
async listSecrets(options) {
|
|
7131
|
+
const base = this.secretCollectionPath(
|
|
7132
|
+
options?.organizationId,
|
|
7133
|
+
options?.projectId
|
|
7134
|
+
);
|
|
7135
|
+
const raw = await this.transport.requestJson("GET", base);
|
|
7136
|
+
const pageSize = Math.max(0, options?.pageSize ?? 100);
|
|
7137
|
+
return Object.assign(
|
|
7138
|
+
{
|
|
7139
|
+
items: raw.slice(0, pageSize).map(secretFromMetadata),
|
|
7140
|
+
pagination: { total: raw.length }
|
|
7141
|
+
},
|
|
7142
|
+
{ traceId: raw.traceId }
|
|
7143
|
+
);
|
|
7144
|
+
}
|
|
7145
|
+
async getSecret(secretId, options) {
|
|
7146
|
+
const base = this.secretCollectionPath(
|
|
7147
|
+
options?.organizationId,
|
|
7148
|
+
options?.projectId
|
|
7149
|
+
);
|
|
7150
|
+
const raw = await this.transport.requestJson(
|
|
7151
|
+
"GET",
|
|
7152
|
+
`${base}/${encodeURIComponent(secretId)}`
|
|
7153
|
+
);
|
|
7154
|
+
return Object.assign(secretFromMetadata(raw), { traceId: raw.traceId });
|
|
7155
|
+
}
|
|
7156
|
+
async upsertSecrets(secrets, options) {
|
|
7157
|
+
const base = this.secretCollectionPath(
|
|
7158
|
+
options?.organizationId,
|
|
7159
|
+
options?.projectId
|
|
7160
|
+
);
|
|
7161
|
+
if (Array.isArray(secrets)) {
|
|
7162
|
+
const results = [];
|
|
7163
|
+
for (const secret of secrets) {
|
|
7164
|
+
results.push(await this.upsertSecret(base, secret));
|
|
7165
|
+
}
|
|
7166
|
+
return results;
|
|
7167
|
+
}
|
|
7168
|
+
return this.upsertSecret(base, secrets);
|
|
7169
|
+
}
|
|
7170
|
+
async deleteSecret(secretId, options) {
|
|
7171
|
+
const base = this.secretCollectionPath(
|
|
7172
|
+
options?.organizationId,
|
|
7173
|
+
options?.projectId
|
|
7174
|
+
);
|
|
7175
|
+
await this.transport.requestResponse(
|
|
7176
|
+
"DELETE",
|
|
7177
|
+
`${base}/${encodeURIComponent(secretId)}`
|
|
7178
|
+
);
|
|
7179
|
+
}
|
|
7180
|
+
async upsertSecret(base, secret) {
|
|
7181
|
+
let response = await this.transport.requestResponse("POST", base, {
|
|
7182
|
+
json: secret,
|
|
7183
|
+
headers: { "Idempotency-Key": nanoid() },
|
|
7184
|
+
statusOnlyCodes: /* @__PURE__ */ new Set([409])
|
|
7185
|
+
});
|
|
7186
|
+
if (response.status === 409) {
|
|
7187
|
+
const prefix = base.slice(0, -"/secrets".length);
|
|
7188
|
+
const existing = await this.transport.requestJson(
|
|
7189
|
+
"GET",
|
|
7190
|
+
`${prefix}/secret-names/${encodeURIComponent(secret.name)}`
|
|
7191
|
+
);
|
|
7192
|
+
response = await this.transport.requestResponse(
|
|
7193
|
+
"POST",
|
|
7194
|
+
`${base}/${encodeURIComponent(existing.id)}/versions`,
|
|
7195
|
+
{
|
|
7196
|
+
json: { value: secret.value },
|
|
7197
|
+
headers: { "Idempotency-Key": nanoid() }
|
|
7198
|
+
}
|
|
7199
|
+
);
|
|
7200
|
+
}
|
|
7201
|
+
const metadata = await parseJsonResponse(response);
|
|
7202
|
+
return Object.assign(secretFromMetadata(metadata), {
|
|
7203
|
+
traceId: response.traceId
|
|
7204
|
+
});
|
|
7205
|
+
}
|
|
7206
|
+
async startImageBuild(buildServicePath, request) {
|
|
7207
|
+
const form = new FormData();
|
|
7208
|
+
form.append("graph_name", request.applicationName);
|
|
7209
|
+
form.append("graph_version", request.applicationVersion);
|
|
7210
|
+
form.append("graph_function_name", request.functionName);
|
|
7211
|
+
form.append("image_name", request.imageName);
|
|
7212
|
+
form.append("image_id", request.imageId);
|
|
7213
|
+
form.append(
|
|
7214
|
+
"context",
|
|
7215
|
+
new Blob([toBlobPart(request.buildContext)]),
|
|
7216
|
+
"context.tar.gz"
|
|
7217
|
+
);
|
|
7218
|
+
const response = await this.transport.requestResponse(
|
|
7219
|
+
"PUT",
|
|
7220
|
+
`${trimTrailingSlashes2(buildServicePath)}/builds`,
|
|
7221
|
+
{ body: form }
|
|
7222
|
+
);
|
|
7223
|
+
const raw = await parseJsonResponse(response);
|
|
7224
|
+
return fromSnakeKeys(raw);
|
|
7225
|
+
}
|
|
7226
|
+
async createApplicationBuild(buildServicePath, request, imageContexts) {
|
|
7227
|
+
const form = createApplicationBuildForm(request, imageContexts);
|
|
7228
|
+
const response = await this.transport.requestResponse(
|
|
7229
|
+
"POST",
|
|
7230
|
+
trimTrailingSlashes2(buildServicePath),
|
|
7231
|
+
{ body: form }
|
|
7232
|
+
);
|
|
7233
|
+
const raw = await parseJsonResponse(response);
|
|
7234
|
+
return fromSnakeKeys(raw);
|
|
7235
|
+
}
|
|
7236
|
+
async applicationBuildInfo(buildServicePath, applicationBuildId) {
|
|
7237
|
+
const raw = await this.transport.requestJson(
|
|
7238
|
+
"GET",
|
|
7239
|
+
`${trimTrailingSlashes2(buildServicePath)}/${encodeURIComponent(applicationBuildId)}`
|
|
7240
|
+
);
|
|
7241
|
+
return fromSnakeKeys(raw);
|
|
7242
|
+
}
|
|
7243
|
+
async cancelApplicationBuild(buildServicePath, applicationBuildId) {
|
|
7244
|
+
const raw = await this.transport.requestJson(
|
|
7245
|
+
"POST",
|
|
7246
|
+
`${trimTrailingSlashes2(buildServicePath)}/${encodeURIComponent(applicationBuildId)}/cancel`
|
|
7247
|
+
);
|
|
7248
|
+
return fromSnakeKeys(raw);
|
|
7249
|
+
}
|
|
7250
|
+
async buildInfo(buildServicePath, buildId) {
|
|
7251
|
+
const raw = await this.transport.requestJson(
|
|
7252
|
+
"GET",
|
|
7253
|
+
`${trimTrailingSlashes2(buildServicePath)}/builds/${encodeURIComponent(buildId)}`
|
|
7254
|
+
);
|
|
7255
|
+
return fromSnakeKeys(raw);
|
|
7256
|
+
}
|
|
7257
|
+
async cancelBuild(buildServicePath, buildId) {
|
|
7258
|
+
await this.transport.requestResponse(
|
|
7259
|
+
"POST",
|
|
7260
|
+
`${trimTrailingSlashes2(buildServicePath)}/builds/${encodeURIComponent(buildId)}/cancel`
|
|
7261
|
+
);
|
|
7262
|
+
}
|
|
7263
|
+
async *streamBuildLogs(buildServicePath, buildId, signal) {
|
|
7264
|
+
const stream = this.transport.stream(
|
|
7265
|
+
"GET",
|
|
7266
|
+
`${trimTrailingSlashes2(buildServicePath)}/builds/${encodeURIComponent(buildId)}/logs`,
|
|
7267
|
+
signal
|
|
7268
|
+
);
|
|
7269
|
+
for await (const event of stream) {
|
|
7270
|
+
yield fromSnakeKeys(event);
|
|
7271
|
+
}
|
|
7272
|
+
}
|
|
7273
|
+
async runMultipartRequest(path5, inputs) {
|
|
7274
|
+
const form = new FormData();
|
|
7275
|
+
for (const input of inputs) {
|
|
7276
|
+
form.append(
|
|
7277
|
+
input.name,
|
|
7278
|
+
new Blob([toBlobPart(input.data)], { type: input.contentType }),
|
|
7279
|
+
input.name
|
|
7280
|
+
);
|
|
7281
|
+
}
|
|
7282
|
+
return this.transport.requestResponse("POST", path5, {
|
|
7283
|
+
body: form,
|
|
7284
|
+
headers: { Accept: "application/json" }
|
|
7285
|
+
});
|
|
7286
|
+
}
|
|
7287
|
+
namespacePath(subpath) {
|
|
7288
|
+
return `/v1/namespaces/${encodeURIComponent(this.namespace)}/${subpath.replace(/^\/+/, "")}`;
|
|
7289
|
+
}
|
|
7290
|
+
async existingApplicationPublicEndpointId(applicationName) {
|
|
7291
|
+
const response = await this.transport.requestResponse(
|
|
7292
|
+
"GET",
|
|
7293
|
+
this.namespacePath(`applications/${encodeURIComponent(applicationName)}`),
|
|
7294
|
+
{ statusOnlyCodes: /* @__PURE__ */ new Set([404]) }
|
|
7295
|
+
);
|
|
7296
|
+
if (response.status === 404) {
|
|
7297
|
+
return void 0;
|
|
7298
|
+
}
|
|
7299
|
+
const application = await parseJsonResponse(response);
|
|
7300
|
+
return publicEndpointIdFromManifest(application);
|
|
7301
|
+
}
|
|
7302
|
+
secretCollectionPath(organizationId, projectId) {
|
|
7303
|
+
const resolvedOrganizationId = organizationId ?? this.organizationId;
|
|
7304
|
+
const resolvedProjectId = projectId ?? this.projectId;
|
|
7305
|
+
if (!resolvedOrganizationId && !resolvedProjectId) {
|
|
7306
|
+
return this.namespacePath("secrets");
|
|
7307
|
+
}
|
|
7308
|
+
if (!resolvedOrganizationId || !resolvedProjectId) {
|
|
7309
|
+
throw new Error("organizationId and projectId must be provided together");
|
|
7310
|
+
}
|
|
7311
|
+
return this.namespacePath("secrets");
|
|
7312
|
+
}
|
|
7313
|
+
};
|
|
7314
|
+
function secretFromMetadata(metadata) {
|
|
7315
|
+
return {
|
|
7316
|
+
id: metadata.id,
|
|
7317
|
+
name: metadata.name,
|
|
7318
|
+
createdAt: new Date(metadata.created_at_ms)
|
|
7319
|
+
};
|
|
7320
|
+
}
|
|
7321
|
+
var UNAUTHENTICATED_REQUESTS = "unauthenticated_requests";
|
|
7322
|
+
function applicationAllowsUnauthenticatedRequests(manifest) {
|
|
7323
|
+
return Array.isArray(manifest.allow) && manifest.allow.includes(UNAUTHENTICATED_REQUESTS);
|
|
7324
|
+
}
|
|
7325
|
+
function publicEndpointIdFromManifest(manifest) {
|
|
7326
|
+
for (const key of ["public_endpoint_id", "publicEndpointId"]) {
|
|
7327
|
+
const value = manifest[key];
|
|
7328
|
+
if (typeof value === "string" && value.length > 0) {
|
|
7329
|
+
return value;
|
|
7330
|
+
}
|
|
7331
|
+
}
|
|
7332
|
+
return void 0;
|
|
7333
|
+
}
|
|
7334
|
+
function generatePublicEndpointId() {
|
|
7335
|
+
return `endpoint_${nanoid()}`;
|
|
7336
|
+
}
|
|
7337
|
+
function createApplicationBuildForm(request, imageContexts) {
|
|
7338
|
+
const contextsByPartName = /* @__PURE__ */ new Map();
|
|
7339
|
+
for (const context of imageContexts) {
|
|
7340
|
+
if (contextsByPartName.has(context.contextTarPartName)) {
|
|
7341
|
+
throw new Error(
|
|
7342
|
+
`duplicate image context part name '${context.contextTarPartName}'`
|
|
7343
|
+
);
|
|
7344
|
+
}
|
|
7345
|
+
contextsByPartName.set(context.contextTarPartName, context);
|
|
7346
|
+
}
|
|
7347
|
+
const form = new FormData();
|
|
7348
|
+
form.append(
|
|
7349
|
+
"app_version",
|
|
7350
|
+
new Blob([JSON.stringify(request)], { type: "application/json" }),
|
|
7351
|
+
"app_version"
|
|
7352
|
+
);
|
|
7353
|
+
for (const image of request.images) {
|
|
7354
|
+
const context = contextsByPartName.get(image.contextTarPartName);
|
|
7355
|
+
if (!context) {
|
|
7356
|
+
throw new Error(
|
|
7357
|
+
`missing image context for part '${image.contextTarPartName}'`
|
|
7358
|
+
);
|
|
7359
|
+
}
|
|
7360
|
+
form.append(
|
|
7361
|
+
image.contextTarPartName,
|
|
7362
|
+
new Blob([toBlobPart(context.contextTarGz)]),
|
|
7363
|
+
`${image.contextTarPartName}.tar.gz`
|
|
7364
|
+
);
|
|
7365
|
+
}
|
|
7366
|
+
for (const context of imageContexts) {
|
|
7367
|
+
if (!request.images.some((image) => image.contextTarPartName === context.contextTarPartName)) {
|
|
7368
|
+
throw new Error(
|
|
7369
|
+
`unexpected image context for part '${context.contextTarPartName}'`
|
|
7370
|
+
);
|
|
7371
|
+
}
|
|
7372
|
+
}
|
|
7373
|
+
return form;
|
|
7374
|
+
}
|
|
7375
|
+
function trimTrailingSlashes2(value) {
|
|
7376
|
+
return value.endsWith("/") ? value.slice(0, -1) : value;
|
|
7377
|
+
}
|
|
7378
|
+
function toBlobPart(data) {
|
|
7379
|
+
if (typeof data === "string" || data instanceof Blob) {
|
|
7380
|
+
return data;
|
|
7381
|
+
}
|
|
7382
|
+
if (data instanceof Uint8Array) {
|
|
7383
|
+
return Uint8Array.from(data).buffer;
|
|
7384
|
+
}
|
|
7385
|
+
return data;
|
|
7386
|
+
}
|
|
7387
|
+
function toRequestBody(data) {
|
|
7388
|
+
return toBlobPart(data);
|
|
7389
|
+
}
|
|
7390
|
+
async function parseJsonResponse(response) {
|
|
7391
|
+
const text = await response.text();
|
|
7392
|
+
if (!text) {
|
|
7393
|
+
return void 0;
|
|
7394
|
+
}
|
|
7395
|
+
return JSON.parse(text);
|
|
7396
|
+
}
|
|
7079
7397
|
|
|
7080
7398
|
// src/api-client.ts
|
|
7081
7399
|
init_esm_shims();
|
|
7082
|
-
init_cloud_client();
|
|
7083
7400
|
|
|
7084
7401
|
// src/filesystem.ts
|
|
7085
7402
|
init_esm_shims();
|
|
@@ -7097,12 +7414,12 @@ import { promisify } from "util";
|
|
|
7097
7414
|
init_esm_shims();
|
|
7098
7415
|
var GIT_MODE_DIR = 16384;
|
|
7099
7416
|
var GIT_MODE_SYMLINK = 40960;
|
|
7100
|
-
function trimSlashes(
|
|
7417
|
+
function trimSlashes(path5) {
|
|
7101
7418
|
let start = 0;
|
|
7102
|
-
let end =
|
|
7103
|
-
while (start < end &&
|
|
7104
|
-
while (end > start &&
|
|
7105
|
-
return
|
|
7419
|
+
let end = path5.length;
|
|
7420
|
+
while (start < end && path5.charCodeAt(start) === 47) start += 1;
|
|
7421
|
+
while (end > start && path5.charCodeAt(end - 1) === 47) end -= 1;
|
|
7422
|
+
return path5.slice(start, end);
|
|
7106
7423
|
}
|
|
7107
7424
|
function fileEntryFromWire(entry, dirPath) {
|
|
7108
7425
|
const mode = entry.mode ?? 33188;
|
|
@@ -7120,9 +7437,9 @@ function fileEntryFromWire(entry, dirPath) {
|
|
|
7120
7437
|
}
|
|
7121
7438
|
function mountStatusFromRaw(raw, localPath) {
|
|
7122
7439
|
const mounted = "mounted" in raw ? Boolean(raw.mounted) : "active" in raw ? Boolean(raw.active) : true;
|
|
7123
|
-
const
|
|
7440
|
+
const path5 = String(raw.path || raw.mount_path || localPath || "");
|
|
7124
7441
|
const filesystem = raw.filesystem || raw.file_system || raw.repository || null;
|
|
7125
|
-
return { path:
|
|
7442
|
+
return { path: path5, filesystem, mounted, raw };
|
|
7126
7443
|
}
|
|
7127
7444
|
var FilesystemError = class extends Error {
|
|
7128
7445
|
constructor(message) {
|
|
@@ -7141,11 +7458,11 @@ var FilesystemNotFoundError = class extends FilesystemError {
|
|
|
7141
7458
|
var FileNotFoundInFilesystemError = class extends FilesystemError {
|
|
7142
7459
|
filesystem;
|
|
7143
7460
|
path;
|
|
7144
|
-
constructor(filesystem,
|
|
7145
|
-
super(`File not found in filesystem ${filesystem}: ${
|
|
7461
|
+
constructor(filesystem, path5) {
|
|
7462
|
+
super(`File not found in filesystem ${filesystem}: ${path5}`);
|
|
7146
7463
|
this.name = "FileNotFoundInFilesystemError";
|
|
7147
7464
|
this.filesystem = filesystem;
|
|
7148
|
-
this.path =
|
|
7465
|
+
this.path = path5;
|
|
7149
7466
|
}
|
|
7150
7467
|
};
|
|
7151
7468
|
var FilesystemAPIError = class extends FilesystemError {
|
|
@@ -7499,8 +7816,8 @@ var Filesystem = class {
|
|
|
7499
7816
|
}
|
|
7500
7817
|
// -- writes -------------------------------------------------------------------
|
|
7501
7818
|
/** Write one file. Returns the snapshot (version) the write produced. */
|
|
7502
|
-
async writeFile(
|
|
7503
|
-
return await this.writeFiles(/* @__PURE__ */ new Map([[
|
|
7819
|
+
async writeFile(path5, data, message) {
|
|
7820
|
+
return await this.writeFiles(/* @__PURE__ */ new Map([[path5, data]]), message);
|
|
7504
7821
|
}
|
|
7505
7822
|
/** Write several files (and/or delete paths) in one atomic snapshot. */
|
|
7506
7823
|
async writeFiles(files, message, deletes = []) {
|
|
@@ -7508,8 +7825,8 @@ var Filesystem = class {
|
|
|
7508
7825
|
if (entries.length === 0 && deletes.length === 0) {
|
|
7509
7826
|
throw new FilesystemError("nothing to write: no files or deletions given");
|
|
7510
7827
|
}
|
|
7511
|
-
const writes = entries.map(([
|
|
7512
|
-
path:
|
|
7828
|
+
const writes = entries.map(([path5, data]) => ({
|
|
7829
|
+
path: path5,
|
|
7513
7830
|
content: toBuffer(data)
|
|
7514
7831
|
}));
|
|
7515
7832
|
const resolvedMessage = message || `write ${writes.length} file(s) via SDK`;
|
|
@@ -7525,9 +7842,9 @@ var Filesystem = class {
|
|
|
7525
7842
|
* Stream one local file directly to object storage in bounded parts.
|
|
7526
7843
|
* This is the memory-bounded API for multi-GiB files.
|
|
7527
7844
|
*/
|
|
7528
|
-
async writeFileFromPath(
|
|
7845
|
+
async writeFileFromPath(path5, localPath, message) {
|
|
7529
7846
|
return await this.writeFilesFromPaths(
|
|
7530
|
-
/* @__PURE__ */ new Map([[
|
|
7847
|
+
/* @__PURE__ */ new Map([[path5, localPath]]),
|
|
7531
7848
|
message
|
|
7532
7849
|
);
|
|
7533
7850
|
}
|
|
@@ -7540,7 +7857,7 @@ var Filesystem = class {
|
|
|
7540
7857
|
if (entries.length === 0) {
|
|
7541
7858
|
throw new FilesystemError("nothing to write: no local files given");
|
|
7542
7859
|
}
|
|
7543
|
-
const writes = entries.map(([
|
|
7860
|
+
const writes = entries.map(([path5, localPath]) => ({ path: path5, localPath }));
|
|
7544
7861
|
const resolvedMessage = message || `write ${writes.length} local file(s) via SDK`;
|
|
7545
7862
|
const branch = await this.branch();
|
|
7546
7863
|
const traced = await callNative2(
|
|
@@ -7617,11 +7934,11 @@ var Filesystem = class {
|
|
|
7617
7934
|
};
|
|
7618
7935
|
}
|
|
7619
7936
|
/** Delete one file. Returns the durable version the deletion produced. */
|
|
7620
|
-
async deleteFile(
|
|
7937
|
+
async deleteFile(path5, message) {
|
|
7621
7938
|
return await this.writeFiles(
|
|
7622
7939
|
/* @__PURE__ */ new Map(),
|
|
7623
|
-
message || `delete ${
|
|
7624
|
-
[
|
|
7940
|
+
message || `delete ${path5} via SDK`,
|
|
7941
|
+
[path5]
|
|
7625
7942
|
);
|
|
7626
7943
|
}
|
|
7627
7944
|
/**
|
|
@@ -7672,15 +7989,15 @@ var Filesystem = class {
|
|
|
7672
7989
|
* Read a file's bytes at `version` (the current `main` head or a retained
|
|
7673
7990
|
* snapshot id; defaults to the filesystem's current head).
|
|
7674
7991
|
*/
|
|
7675
|
-
async readFile(
|
|
7676
|
-
return (await this.readFileWithMetadata(
|
|
7992
|
+
async readFile(path5, version) {
|
|
7993
|
+
return (await this.readFileWithMetadata(path5, { version })).data;
|
|
7677
7994
|
}
|
|
7678
7995
|
/**
|
|
7679
7996
|
* Read bytes and immutable metadata in one request. A range is executed by
|
|
7680
7997
|
* Artifact Storage, so callers never download the unrequested remainder.
|
|
7681
7998
|
*/
|
|
7682
|
-
async readFileWithMetadata(
|
|
7683
|
-
if (trimSlashes(
|
|
7999
|
+
async readFileWithMetadata(path5, options = {}) {
|
|
8000
|
+
if (trimSlashes(path5) === "") {
|
|
7684
8001
|
throw new FilesystemError("file path must not be empty");
|
|
7685
8002
|
}
|
|
7686
8003
|
const range = options.range;
|
|
@@ -7693,12 +8010,12 @@ var Filesystem = class {
|
|
|
7693
8010
|
const traced = await callNative2(
|
|
7694
8011
|
() => this.native.readFilesystemFile(
|
|
7695
8012
|
this.name,
|
|
7696
|
-
|
|
8013
|
+
path5,
|
|
7697
8014
|
resolvedVersion,
|
|
7698
8015
|
range?.offset,
|
|
7699
8016
|
range?.length
|
|
7700
8017
|
),
|
|
7701
|
-
new FileNotFoundInFilesystemError(this.name,
|
|
8018
|
+
new FileNotFoundInFilesystemError(this.name, path5)
|
|
7702
8019
|
);
|
|
7703
8020
|
const fullSize = traced.fullSize;
|
|
7704
8021
|
if (!traced.contentId || fullSize === void 0 || !Number.isSafeInteger(fullSize) || fullSize < 0 || traced.data.byteLength > fullSize) {
|
|
@@ -7713,9 +8030,9 @@ var Filesystem = class {
|
|
|
7713
8030
|
};
|
|
7714
8031
|
}
|
|
7715
8032
|
/** Read a file as UTF-8 text at `version`. Throws on non-UTF-8 content. */
|
|
7716
|
-
async readText(
|
|
8033
|
+
async readText(path5, version) {
|
|
7717
8034
|
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(
|
|
7718
|
-
await this.readFile(
|
|
8035
|
+
await this.readFile(path5, version)
|
|
7719
8036
|
);
|
|
7720
8037
|
}
|
|
7721
8038
|
/** List one directory (non-recursive) at `version`. */
|
|
@@ -7778,11 +8095,11 @@ var FilesystemMount = class {
|
|
|
7778
8095
|
path;
|
|
7779
8096
|
readonly;
|
|
7780
8097
|
/** @internal — obtain instances via `FilesystemClient.mount()`. */
|
|
7781
|
-
constructor(client, cli, filesystem,
|
|
8098
|
+
constructor(client, cli, filesystem, path5, readonly) {
|
|
7782
8099
|
this.client = client;
|
|
7783
8100
|
this.cli = cli;
|
|
7784
8101
|
this.filesystem = filesystem;
|
|
7785
|
-
this.path =
|
|
8102
|
+
this.path = path5;
|
|
7786
8103
|
this.readonly = readonly;
|
|
7787
8104
|
}
|
|
7788
8105
|
/** Flush pending local changes into a durable snapshot. */
|
|
@@ -7800,6 +8117,7 @@ var FilesystemMount = class {
|
|
|
7800
8117
|
};
|
|
7801
8118
|
|
|
7802
8119
|
// src/api-client.ts
|
|
8120
|
+
init_sandbox_image();
|
|
7803
8121
|
init_errors();
|
|
7804
8122
|
var APIClient = class {
|
|
7805
8123
|
cloudClient;
|
|
@@ -7827,7 +8145,7 @@ var APIClient = class {
|
|
|
7827
8145
|
await this.cloudClient.deleteApplication(applicationName);
|
|
7828
8146
|
}
|
|
7829
8147
|
async deleteSandboxImage(imageName) {
|
|
7830
|
-
await this.
|
|
8148
|
+
await deleteSandboxImageWithCredentials(this.filesystemOptions, imageName);
|
|
7831
8149
|
}
|
|
7832
8150
|
async createFileSystem(name, description, options) {
|
|
7833
8151
|
const filesystem = await new FilesystemClient(this.filesystemOptions).create(
|
|
@@ -7914,14 +8232,14 @@ var GitCli = class extends MountCli {
|
|
|
7914
8232
|
if (options.readOnly && (options.publish || options.workspace !== void 0) || options.publish && options.workspace !== void 0) {
|
|
7915
8233
|
throw new TypeError("readOnly, publish, and workspace are mutually exclusive");
|
|
7916
8234
|
}
|
|
7917
|
-
const
|
|
8235
|
+
const path5 = resolve(localPath);
|
|
7918
8236
|
const args = ["mount"];
|
|
7919
8237
|
if (options.readOnly) args.push("--ro");
|
|
7920
8238
|
if (options.publish) args.push("--publish");
|
|
7921
8239
|
if (options.workspace !== void 0) args.push(`--workspace=${options.workspace}`);
|
|
7922
|
-
args.push("--", target,
|
|
8240
|
+
args.push("--", target, path5);
|
|
7923
8241
|
await this.run(args);
|
|
7924
|
-
return new RepositoryMount(this, target,
|
|
8242
|
+
return new RepositoryMount(this, target, path5, options.readOnly ?? false);
|
|
7925
8243
|
}
|
|
7926
8244
|
async unmount(localPath, options = {}) {
|
|
7927
8245
|
requireNonEmpty(localPath, "localPath");
|
|
@@ -7959,44 +8277,44 @@ var GitCli = class extends MountCli {
|
|
|
7959
8277
|
raw
|
|
7960
8278
|
};
|
|
7961
8279
|
}
|
|
7962
|
-
async snapshot(
|
|
8280
|
+
async snapshot(path5, message) {
|
|
7963
8281
|
const args = ["snapshot"];
|
|
7964
8282
|
if (message !== void 0) args.push(`--message=${message}`);
|
|
7965
|
-
args.push("--",
|
|
8283
|
+
args.push("--", path5);
|
|
7966
8284
|
await this.run(args);
|
|
7967
8285
|
}
|
|
7968
|
-
async sync(
|
|
7969
|
-
const args = ["sync", "--",
|
|
8286
|
+
async sync(path5, target) {
|
|
8287
|
+
const args = ["sync", "--", path5];
|
|
7970
8288
|
if (target !== void 0) {
|
|
7971
8289
|
requireNonEmpty(target, "target");
|
|
7972
8290
|
args.push(target);
|
|
7973
8291
|
}
|
|
7974
8292
|
await this.run(args);
|
|
7975
8293
|
}
|
|
7976
|
-
async rebase(
|
|
8294
|
+
async rebase(path5, target, failOnConflict) {
|
|
7977
8295
|
requireNonEmpty(target, "target");
|
|
7978
8296
|
const args = ["rebase"];
|
|
7979
8297
|
if (failOnConflict) args.push("--fail-on-conflict");
|
|
7980
|
-
args.push("--",
|
|
8298
|
+
args.push("--", path5, target);
|
|
7981
8299
|
await this.run(args);
|
|
7982
8300
|
}
|
|
7983
|
-
async promote(
|
|
8301
|
+
async promote(path5, branch, merge) {
|
|
7984
8302
|
requireNonEmpty(branch, "branch");
|
|
7985
8303
|
const args = ["promote"];
|
|
7986
8304
|
if (merge) args.push("--merge");
|
|
7987
|
-
args.push("--",
|
|
8305
|
+
args.push("--", path5, branch);
|
|
7988
8306
|
await this.run(args);
|
|
7989
8307
|
}
|
|
7990
|
-
async prefetch(
|
|
7991
|
-
await this.run(["prefetch", "--",
|
|
8308
|
+
async prefetch(path5) {
|
|
8309
|
+
await this.run(["prefetch", "--", path5]);
|
|
7992
8310
|
}
|
|
7993
8311
|
};
|
|
7994
8312
|
var RepositoryMount = class {
|
|
7995
8313
|
/** @internal Obtain instances via RepositoryClient.mount(). */
|
|
7996
|
-
constructor(cli, target,
|
|
8314
|
+
constructor(cli, target, path5, readOnly) {
|
|
7997
8315
|
this.cli = cli;
|
|
7998
8316
|
this.target = target;
|
|
7999
|
-
this.path =
|
|
8317
|
+
this.path = path5;
|
|
8000
8318
|
this.readOnly = readOnly;
|
|
8001
8319
|
}
|
|
8002
8320
|
/** Inspect workspace state, pending changes, and daemon diagnostics. */
|
|
@@ -8231,6 +8549,7 @@ function validateTimeoutMs2(timeoutMs) {
|
|
|
8231
8549
|
|
|
8232
8550
|
// src/index.ts
|
|
8233
8551
|
init_sandbox_image();
|
|
8552
|
+
init_image_builds();
|
|
8234
8553
|
|
|
8235
8554
|
// src/file-system.ts
|
|
8236
8555
|
init_esm_shims();
|
|
@@ -9614,38 +9933,38 @@ init_esm_shims();
|
|
|
9614
9933
|
import { createHash } from "crypto";
|
|
9615
9934
|
var textEncoder = new TextEncoder();
|
|
9616
9935
|
var textDecoder = new TextDecoder("utf-8", { fatal: true });
|
|
9617
|
-
function assertJSONValue(value,
|
|
9936
|
+
function assertJSONValue(value, path5, seen) {
|
|
9618
9937
|
if (value === null || typeof value === "string" || typeof value === "boolean") return;
|
|
9619
9938
|
if (typeof value === "number") {
|
|
9620
|
-
if (!Number.isFinite(value)) throw new SerializationError(`${
|
|
9939
|
+
if (!Number.isFinite(value)) throw new SerializationError(`${path5} contains a non-finite number`);
|
|
9621
9940
|
return;
|
|
9622
9941
|
}
|
|
9623
9942
|
if (typeof value !== "object") {
|
|
9624
|
-
throw new SerializationError(`${
|
|
9943
|
+
throw new SerializationError(`${path5} contains unsupported ${typeof value}`);
|
|
9625
9944
|
}
|
|
9626
9945
|
if (isFile(value)) {
|
|
9627
|
-
throw new SerializationError(`${
|
|
9946
|
+
throw new SerializationError(`${path5} contains a nested File; File is only supported as a direct value`);
|
|
9628
9947
|
}
|
|
9629
9948
|
if (isHttpBody(value)) {
|
|
9630
9949
|
throw new SerializationError(
|
|
9631
|
-
`${
|
|
9950
|
+
`${path5} contains a nested HttpBody; HttpBody is only supported as a direct value`
|
|
9632
9951
|
);
|
|
9633
9952
|
}
|
|
9634
|
-
if (seen.has(value)) throw new SerializationError(`${
|
|
9953
|
+
if (seen.has(value)) throw new SerializationError(`${path5} contains a cycle`);
|
|
9635
9954
|
if (Object.getPrototypeOf(value) !== Object.prototype && !Array.isArray(value)) {
|
|
9636
|
-
throw new SerializationError(`${
|
|
9955
|
+
throw new SerializationError(`${path5} contains unsupported ${value.constructor?.name ?? "object"}`);
|
|
9637
9956
|
}
|
|
9638
9957
|
seen.add(value);
|
|
9639
9958
|
if (Array.isArray(value)) {
|
|
9640
9959
|
for (let index = 0; index < value.length; index += 1) {
|
|
9641
9960
|
if (!Object.prototype.hasOwnProperty.call(value, index)) {
|
|
9642
|
-
throw new SerializationError(`${
|
|
9961
|
+
throw new SerializationError(`${path5} contains a sparse array entry at index ${index}`);
|
|
9643
9962
|
}
|
|
9644
|
-
assertJSONValue(value[index], `${
|
|
9963
|
+
assertJSONValue(value[index], `${path5}[${index}]`, seen);
|
|
9645
9964
|
}
|
|
9646
9965
|
} else {
|
|
9647
9966
|
for (const [key, item] of Object.entries(value)) {
|
|
9648
|
-
assertJSONValue(item, `${
|
|
9967
|
+
assertJSONValue(item, `${path5}.${key}`, seen);
|
|
9649
9968
|
}
|
|
9650
9969
|
}
|
|
9651
9970
|
seen.delete(value);
|
|
@@ -10094,7 +10413,15 @@ export {
|
|
|
10094
10413
|
Headers,
|
|
10095
10414
|
HttpBody,
|
|
10096
10415
|
Image,
|
|
10416
|
+
ImageBuildCancelledError,
|
|
10417
|
+
ImageBuildError,
|
|
10418
|
+
ImageBuildFailedError,
|
|
10419
|
+
ImageBuildHandle,
|
|
10420
|
+
ImageBuildInProgressError,
|
|
10421
|
+
ImageBuildInterruptedError,
|
|
10422
|
+
ImageBuildNotFoundError,
|
|
10097
10423
|
ImageBuildOperationType,
|
|
10424
|
+
ImageBuildTimeoutError,
|
|
10098
10425
|
MountError,
|
|
10099
10426
|
OutputMode,
|
|
10100
10427
|
PendingSandbox,
|
|
@@ -10127,12 +10454,14 @@ export {
|
|
|
10127
10454
|
TERMINATION_REASON_CANCELLED,
|
|
10128
10455
|
TERMINATION_REASON_NO_CAPACITY,
|
|
10129
10456
|
TcpTunnel,
|
|
10457
|
+
cancelImageBuild,
|
|
10130
10458
|
createFileSystem,
|
|
10131
10459
|
createSandboxImage,
|
|
10132
10460
|
deleteFileSystem,
|
|
10133
10461
|
deleteSandboxImage,
|
|
10134
10462
|
dockerfileContent,
|
|
10135
10463
|
findSandboxImageByName,
|
|
10464
|
+
getImageBuild,
|
|
10136
10465
|
importSandboxImage,
|
|
10137
10466
|
isSandboxPending,
|
|
10138
10467
|
listFileSystems,
|
|
@@ -10144,6 +10473,9 @@ export {
|
|
|
10144
10473
|
runLocal,
|
|
10145
10474
|
runRemote,
|
|
10146
10475
|
sandboxUrlFromIngressEndpoint,
|
|
10147
|
-
schema
|
|
10476
|
+
schema,
|
|
10477
|
+
startImageBuild,
|
|
10478
|
+
startImageImport,
|
|
10479
|
+
waitImageBuild
|
|
10148
10480
|
};
|
|
10149
10481
|
//# sourceMappingURL=index.js.map
|