trainfabric 0.1.31 → 0.1.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +57 -11
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -8923,7 +8923,17 @@ function collectRuntimeFiles(repoPath) {
|
|
|
8923
8923
|
if (found.length >= maxFiles) {
|
|
8924
8924
|
return;
|
|
8925
8925
|
}
|
|
8926
|
-
|
|
8926
|
+
let entries;
|
|
8927
|
+
try {
|
|
8928
|
+
entries = import_node_fs.default.readdirSync(currentPath, { withFileTypes: true });
|
|
8929
|
+
} catch (error) {
|
|
8930
|
+
if (error.code === "EACCES" || error.code === "EPERM") {
|
|
8931
|
+
const relativePath = import_node_path2.default.relative(repoPath, currentPath) || ".";
|
|
8932
|
+
throw new Error(`Permission denied while scanning repository path: ${relativePath}`);
|
|
8933
|
+
}
|
|
8934
|
+
throw new Error(`Failed to scan repository path: ${currentPath}`);
|
|
8935
|
+
}
|
|
8936
|
+
for (const entry of entries) {
|
|
8927
8937
|
const absolute = import_node_path2.default.join(currentPath, entry.name);
|
|
8928
8938
|
const relative = import_node_path2.default.relative(repoPath, absolute).split(import_node_path2.default.sep).join("/");
|
|
8929
8939
|
if (entry.isDirectory()) {
|
|
@@ -8935,13 +8945,30 @@ function collectRuntimeFiles(repoPath) {
|
|
|
8935
8945
|
if (!entry.isFile() || !shouldIncludeFile(entry.name)) {
|
|
8936
8946
|
continue;
|
|
8937
8947
|
}
|
|
8938
|
-
|
|
8948
|
+
let stat;
|
|
8949
|
+
try {
|
|
8950
|
+
stat = import_node_fs.default.statSync(absolute);
|
|
8951
|
+
} catch (error) {
|
|
8952
|
+
if (error.code === "EACCES" || error.code === "EPERM") {
|
|
8953
|
+
throw new Error(`Permission denied while scanning repository file: ${relative}`);
|
|
8954
|
+
}
|
|
8955
|
+
throw new Error(`Failed to inspect repository file: ${relative}`);
|
|
8956
|
+
}
|
|
8939
8957
|
if (stat.size > maxFileBytes) {
|
|
8940
8958
|
continue;
|
|
8941
8959
|
}
|
|
8960
|
+
let content;
|
|
8961
|
+
try {
|
|
8962
|
+
content = import_node_fs.default.readFileSync(absolute, "utf8");
|
|
8963
|
+
} catch (error) {
|
|
8964
|
+
if (error.code === "EACCES" || error.code === "EPERM") {
|
|
8965
|
+
throw new Error(`Permission denied while reading repository file: ${relative}`);
|
|
8966
|
+
}
|
|
8967
|
+
throw new Error(`Failed to read repository file: ${relative}`);
|
|
8968
|
+
}
|
|
8942
8969
|
found.push({
|
|
8943
8970
|
path: relative,
|
|
8944
|
-
content
|
|
8971
|
+
content
|
|
8945
8972
|
});
|
|
8946
8973
|
}
|
|
8947
8974
|
}
|
|
@@ -8985,7 +9012,22 @@ function validateGitBranch(value) {
|
|
|
8985
9012
|
function validateRepoPath(repoPath) {
|
|
8986
9013
|
const absolute = import_node_path2.default.resolve(repoPath);
|
|
8987
9014
|
const parsed = import_node_path2.default.parse(absolute);
|
|
8988
|
-
|
|
9015
|
+
const unsafeRoots = /* @__PURE__ */ new Set([
|
|
9016
|
+
parsed.root,
|
|
9017
|
+
import_node_os.default.homedir(),
|
|
9018
|
+
import_node_path2.default.resolve(import_node_os.default.tmpdir()),
|
|
9019
|
+
import_node_path2.default.resolve("/tmp"),
|
|
9020
|
+
import_node_path2.default.resolve("/private/tmp"),
|
|
9021
|
+
import_node_path2.default.resolve("/var"),
|
|
9022
|
+
import_node_path2.default.resolve("/Users"),
|
|
9023
|
+
import_node_path2.default.resolve("/System"),
|
|
9024
|
+
import_node_path2.default.resolve("/Library"),
|
|
9025
|
+
import_node_path2.default.resolve("/Applications"),
|
|
9026
|
+
import_node_path2.default.resolve("/etc"),
|
|
9027
|
+
import_node_path2.default.resolve("/bin"),
|
|
9028
|
+
import_node_path2.default.resolve("/usr")
|
|
9029
|
+
]);
|
|
9030
|
+
if (unsafeRoots.has(absolute)) {
|
|
8989
9031
|
throw new Error(`Refusing to package unsafe repository path: ${repoPath}`);
|
|
8990
9032
|
}
|
|
8991
9033
|
let stat;
|
|
@@ -9175,6 +9217,9 @@ function normalizeLearningRate(lr) {
|
|
|
9175
9217
|
function buildComputeSpec(options) {
|
|
9176
9218
|
const gpuCount = normalizePositiveInteger(options.gpus, "GPU count", 1);
|
|
9177
9219
|
const nodeCount = normalizePositiveInteger(options.nodes, "Node count", 1);
|
|
9220
|
+
if (nodeCount > gpuCount) {
|
|
9221
|
+
throw new Error("Node count cannot exceed GPU count. Request at least one GPU per node.");
|
|
9222
|
+
}
|
|
9178
9223
|
const compute = {
|
|
9179
9224
|
gpuCount,
|
|
9180
9225
|
nodeCount,
|
|
@@ -9207,7 +9252,7 @@ function buildComputeSpec(options) {
|
|
|
9207
9252
|
|
|
9208
9253
|
// src/index.ts
|
|
9209
9254
|
var DEFAULT_TRAINFABRIC_API_URL2 = "https://api.trainfabric.com";
|
|
9210
|
-
var CLI_VERSION = "0.1.
|
|
9255
|
+
var CLI_VERSION = "0.1.33";
|
|
9211
9256
|
var CONFIG_DIR = import_node_path3.default.join(import_node_os2.default.homedir(), ".trainfabric");
|
|
9212
9257
|
var CONFIG_PATH = import_node_path3.default.join(CONFIG_DIR, "config.json");
|
|
9213
9258
|
var FALLBACK_SECRET_PATH = import_node_path3.default.join(CONFIG_DIR, "session.enc");
|
|
@@ -9731,14 +9776,15 @@ function normalizeHttpBaseUrl(value) {
|
|
|
9731
9776
|
try {
|
|
9732
9777
|
url = new URL(value);
|
|
9733
9778
|
} catch {
|
|
9734
|
-
throw new Error(`Invalid base URL "${value}". Use an absolute
|
|
9779
|
+
throw new Error(`Invalid base URL "${value}". Use an absolute HTTPS origin such as https://api.trainfabric.com.`);
|
|
9780
|
+
}
|
|
9781
|
+
const isLocalDevHost = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "::1";
|
|
9782
|
+
if (url.protocol !== "https:" && !(isLocalDevHost && url.protocol === "http:")) {
|
|
9783
|
+
throw new Error(`Invalid base URL "${value}". Use HTTPS, or http://localhost for local development.`);
|
|
9735
9784
|
}
|
|
9736
|
-
if (url.
|
|
9737
|
-
throw new Error(`Invalid base URL "${value}". Use
|
|
9785
|
+
if (url.pathname !== "/" || url.search || url.hash) {
|
|
9786
|
+
throw new Error(`Invalid base URL "${value}". Use the API origin without a path, query, or hash.`);
|
|
9738
9787
|
}
|
|
9739
|
-
url.pathname = url.pathname.replace(/\/+$/, "");
|
|
9740
|
-
url.search = "";
|
|
9741
|
-
url.hash = "";
|
|
9742
9788
|
return url.toString().replace(/\/+$/, "");
|
|
9743
9789
|
}
|
|
9744
9790
|
async function login(config) {
|