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.
Files changed (2) hide show
  1. package/dist/index.cjs +45 -19
  2. 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.13";
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 buildRunInput(options) {
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.project,
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
- )}). Omit --accelerator or increase --min-memory.`
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
- async function watchRun(runId, json = false, timeoutMs) {
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").requiredOption("--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) => {
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 client = createClient(loadConfig());
9489
- const run = await client.runs.create(buildRunInput(options));
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").requiredOption("--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) => {
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(loadConfig()).runtime.detect({
9499
- projectId: options.project,
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").requiredOption("--project <projectId>").requiredOption("--detection <detectionId>").description("Build or reuse a cached runtime image from a runtime detection").action(async (options) => {
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(loadConfig()).runtime.build({
9507
- projectId: options.project,
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").requiredOption("--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) => {
9513
- const bundle = await createClient(loadConfig()).runs.quote(buildRunInput(options));
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));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trainfabric",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "description": "Trainfabric CLI for launching GPU training jobs on the hosted Trainfabric backend.",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",