trainfabric 0.1.13 → 0.1.15
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 +45 -19
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -8922,7 +8922,7 @@ function buildComputeSpec(options) {
|
|
|
8922
8922
|
|
|
8923
8923
|
// src/index.ts
|
|
8924
8924
|
var DEFAULT_TRAINFABRIC_API_URL2 = "https://api.trainfabric.com";
|
|
8925
|
-
var CLI_VERSION = "0.1.
|
|
8925
|
+
var CLI_VERSION = "0.1.15";
|
|
8926
8926
|
var CONFIG_DIR = import_node_path3.default.join(import_node_os2.default.homedir(), ".trainfabric");
|
|
8927
8927
|
var CONFIG_PATH = import_node_path3.default.join(CONFIG_DIR, "config.json");
|
|
8928
8928
|
var FALLBACK_SECRET_PATH = import_node_path3.default.join(CONFIG_DIR, "session.enc");
|
|
@@ -9260,10 +9260,17 @@ function visibleConfig(config) {
|
|
|
9260
9260
|
refreshToken: config.refreshToken ? "<stored>" : void 0
|
|
9261
9261
|
};
|
|
9262
9262
|
}
|
|
9263
|
-
function
|
|
9263
|
+
function requireProjectId(options, config) {
|
|
9264
|
+
const projectId = options.project ?? config.projectId;
|
|
9265
|
+
if (!projectId) {
|
|
9266
|
+
throw new Error("Project is required. Pass --project <projectId> or run `trainfabric config:set-project <projectId>`.");
|
|
9267
|
+
}
|
|
9268
|
+
return projectId;
|
|
9269
|
+
}
|
|
9270
|
+
function buildRunInput(options, config = loadConfig()) {
|
|
9264
9271
|
const sourceOptions = buildSourceOptions(options);
|
|
9265
9272
|
return {
|
|
9266
|
-
projectId: options
|
|
9273
|
+
projectId: requireProjectId(options, config),
|
|
9267
9274
|
task: "sft",
|
|
9268
9275
|
method: "lora",
|
|
9269
9276
|
baseModel: normalizeBaseModel(options.model),
|
|
@@ -9285,6 +9292,9 @@ function assertQuoteOptions(bundle, options) {
|
|
|
9285
9292
|
return;
|
|
9286
9293
|
}
|
|
9287
9294
|
const constraints = [];
|
|
9295
|
+
if (options.mode) {
|
|
9296
|
+
constraints.push(`mode=${options.mode}`);
|
|
9297
|
+
}
|
|
9288
9298
|
if (options.accelerator) {
|
|
9289
9299
|
constraints.push(`accelerator=${options.accelerator}`);
|
|
9290
9300
|
}
|
|
@@ -9297,10 +9307,19 @@ function assertQuoteOptions(bundle, options) {
|
|
|
9297
9307
|
throw new Error(
|
|
9298
9308
|
`No quote options were returned for the requested run under the current hardware constraints (${constraints.join(
|
|
9299
9309
|
", "
|
|
9300
|
-
)}).
|
|
9310
|
+
)}). Try a different --mode, omit --accelerator, adjust --min-memory if it excludes available GPUs, or retry when capacity changes.`
|
|
9301
9311
|
);
|
|
9302
9312
|
}
|
|
9303
|
-
|
|
9313
|
+
function filterQuoteBundleForRequestedMode(bundle, options) {
|
|
9314
|
+
if (!options.mode) {
|
|
9315
|
+
return bundle;
|
|
9316
|
+
}
|
|
9317
|
+
return {
|
|
9318
|
+
...bundle,
|
|
9319
|
+
quotes: bundle.quotes.filter((item) => item.mode === options.mode || item.quote.mode === options.mode)
|
|
9320
|
+
};
|
|
9321
|
+
}
|
|
9322
|
+
async function watchRun(runId, json = false, timeoutMs, pollMs) {
|
|
9304
9323
|
const handle = await createClient(loadConfig()).runs.watch(runId);
|
|
9305
9324
|
if (json) {
|
|
9306
9325
|
const emit = (type, payload) => printJson({ type, payload });
|
|
@@ -9337,7 +9356,7 @@ async function watchRun(runId, json = false, timeoutMs) {
|
|
|
9337
9356
|
console.log(`[failed] ${payload.reason ?? "Run failed."}`);
|
|
9338
9357
|
});
|
|
9339
9358
|
}
|
|
9340
|
-
const detail = await handle.wait({ timeoutMs });
|
|
9359
|
+
const detail = await handle.wait({ timeoutMs, pollMs });
|
|
9341
9360
|
printJson(detail);
|
|
9342
9361
|
}
|
|
9343
9362
|
function parseDurationMs(value) {
|
|
@@ -9481,36 +9500,43 @@ program2.command("datasets:upload").argument("<file>").option("--project <projec
|
|
|
9481
9500
|
});
|
|
9482
9501
|
printJson(dataset);
|
|
9483
9502
|
});
|
|
9484
|
-
program2.command("runs:create").
|
|
9503
|
+
program2.command("runs:create").option("--project <projectId>").requiredOption("--dataset <datasetId>").requiredOption("--model <baseModel>").option("--eval <evalDatasetId>").option("--epochs <epochs>", "number of epochs", "3").option("--lr <lr>", "learning rate", "0.0002").option("--gpus <gpuCount>", "gpu count", "1").option("--nodes <nodeCount>", "node count", "1").option("--accelerator <acceleratorClass>", "optional hard accelerator constraint (for example: a10g, a100, h100)").option("--min-memory <gigabytes>", "minimum GPU memory in GB").option("--precision <precision>", "fp16_bf16, fp8, or fp32").option("--interconnect <interconnect>", "pcie or nvlink").option("--mode <mode>", "efficient, balanced, or power", "balanced").option("--quote <pricingQuoteId>", "launch the exact accepted quote id from runs:quote").option("--repo <path>", "local repo path for runtime autodetect").option("--git <url>", "git repo URL for runtime metadata").option("--branch <branch>", "git branch for runtime metadata").option("--yes", "confirm that you reviewed pricing with runs:quote --summary and accept fluctuating realized usage").description("Create a training run").action(async (options) => {
|
|
9485
9504
|
if (!options.yes) {
|
|
9486
9505
|
throw new Error("Refusing to launch without explicit cost acceptance. Run `trainfabric runs:quote --summary ...` first, then rerun `runs:create` with --yes.");
|
|
9487
9506
|
}
|
|
9488
|
-
const
|
|
9489
|
-
const
|
|
9507
|
+
const config = loadConfig();
|
|
9508
|
+
const client = createClient(config);
|
|
9509
|
+
const run = await client.runs.create(buildRunInput(options, config));
|
|
9490
9510
|
printJson(run.snapshot);
|
|
9491
9511
|
});
|
|
9492
|
-
program2.command("runtime:detect").
|
|
9512
|
+
program2.command("runtime:detect").option("--project <projectId>").option("--repo <path>").option("--git <url>").option("--branch <branch>").description("Detect a supported runtime from a local repo snapshot or git metadata").action(async (options) => {
|
|
9493
9513
|
const sourceOptions = buildSourceOptions(options);
|
|
9494
9514
|
if (!sourceOptions.source) {
|
|
9495
9515
|
throw new Error("Provide --repo or --git.");
|
|
9496
9516
|
}
|
|
9517
|
+
const config = loadConfig();
|
|
9497
9518
|
printJson(
|
|
9498
|
-
await createClient(
|
|
9499
|
-
projectId: options
|
|
9519
|
+
await createClient(config).runtime.detect({
|
|
9520
|
+
projectId: requireProjectId(options, config),
|
|
9500
9521
|
source: sourceOptions.source
|
|
9501
9522
|
})
|
|
9502
9523
|
);
|
|
9503
9524
|
});
|
|
9504
|
-
program2.command("runtime:build").
|
|
9525
|
+
program2.command("runtime:build").option("--project <projectId>").requiredOption("--detection <detectionId>").description("Build or reuse a cached runtime image from a runtime detection").action(async (options) => {
|
|
9526
|
+
const config = loadConfig();
|
|
9505
9527
|
printJson(
|
|
9506
|
-
await createClient(
|
|
9507
|
-
projectId: options
|
|
9528
|
+
await createClient(config).runtime.build({
|
|
9529
|
+
projectId: requireProjectId(options, config),
|
|
9508
9530
|
detectionId: options.detection
|
|
9509
9531
|
})
|
|
9510
9532
|
);
|
|
9511
9533
|
});
|
|
9512
|
-
program2.command("runs:quote").
|
|
9513
|
-
const
|
|
9534
|
+
program2.command("runs:quote").option("--project <projectId>").requiredOption("--dataset <datasetId>").requiredOption("--model <baseModel>").option("--eval <evalDatasetId>").option("--gpus <gpuCount>", "gpu count", "1").option("--nodes <nodeCount>", "node count", "1").option("--accelerator <acceleratorClass>", "optional hard accelerator constraint (for example: a10g, a100, h100)").option("--min-memory <gigabytes>", "minimum GPU memory in GB").option("--precision <precision>", "fp16_bf16, fp8, or fp32").option("--interconnect <interconnect>", "pcie or nvlink").option("--mode <mode>", "efficient, balanced, or power").option("--repo <path>").option("--git <url>").option("--branch <branch>").option("--summary", "print a human-readable price summary instead of raw JSON").description("Preview Efficient, Balanced, and Power launch options").action(async (options) => {
|
|
9535
|
+
const config = loadConfig();
|
|
9536
|
+
const bundle = filterQuoteBundleForRequestedMode(
|
|
9537
|
+
await createClient(config).runs.quote(buildRunInput(options, config)),
|
|
9538
|
+
options
|
|
9539
|
+
);
|
|
9514
9540
|
assertQuoteOptions(bundle, options);
|
|
9515
9541
|
if (options.summary) {
|
|
9516
9542
|
printQuoteSummary(bundle);
|
|
@@ -9535,8 +9561,8 @@ program2.command("runs:wait").argument("<runId>").option("--timeout <duration>",
|
|
|
9535
9561
|
})
|
|
9536
9562
|
);
|
|
9537
9563
|
});
|
|
9538
|
-
program2.command("runs:watch").argument("<runId>").option("--json", "emit event output as JSON").option("--timeout <duration>", "maximum watch duration, for example 30s, 10m, or 1h").description("Stream a run until it completes").action(async (runId, options) => {
|
|
9539
|
-
await watchRun(String(runId), Boolean(options.json), parseDurationMs(options.timeout));
|
|
9564
|
+
program2.command("runs:watch").argument("<runId>").option("--json", "emit event output as JSON").option("--timeout <duration>", "maximum watch duration, for example 30s, 10m, or 1h").option("--poll <duration>", "poll interval, for example 1s or 500ms").description("Stream a run until it completes").action(async (runId, options) => {
|
|
9565
|
+
await watchRun(String(runId), Boolean(options.json), parseDurationMs(options.timeout), parsePositiveMs(options.poll, 1e3));
|
|
9540
9566
|
});
|
|
9541
9567
|
program2.command("runs:usage").argument("<runId>").option("--summary", "print a human-readable cost summary instead of raw JSON").description("Fetch run usage summary").action(async (runId, options) => {
|
|
9542
9568
|
const usage = await createClient(loadConfig()).runs.usage(String(runId));
|