trainfabric 0.1.39 → 0.1.41

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 +41 -10
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -9180,6 +9180,7 @@ var PRECISION_MODES = /* @__PURE__ */ new Set(["fp16_bf16", "fp8", "fp32"]);
9180
9180
  var INTERCONNECT_TYPES = /* @__PURE__ */ new Set(["pcie", "nvlink"]);
9181
9181
  var BASE_MODELS = new Set(baseModels);
9182
9182
  var TRAINING_MODES = new Set(trainingModes);
9183
+ var MAX_MIN_GPU_MEMORY_GB = 192;
9183
9184
  function normalizePositiveInteger(value, label, fallback, max) {
9184
9185
  const parsed = Number(value ?? String(fallback));
9185
9186
  if (!Number.isInteger(parsed) || parsed <= 0) {
@@ -9266,6 +9267,9 @@ function buildComputeSpec(options) {
9266
9267
  compute.acceleratorClass = accelerator;
9267
9268
  }
9268
9269
  if (minMemory !== void 0) {
9270
+ if (minMemory > MAX_MIN_GPU_MEMORY_GB) {
9271
+ throw new Error(`Minimum GPU memory must be <= ${MAX_MIN_GPU_MEMORY_GB} GB.`);
9272
+ }
9269
9273
  compute.minGpuMemoryGb = minMemory;
9270
9274
  }
9271
9275
  if (precision) {
@@ -9279,7 +9283,7 @@ function buildComputeSpec(options) {
9279
9283
 
9280
9284
  // src/index.ts
9281
9285
  var DEFAULT_TRAINFABRIC_API_URL2 = "https://api.trainfabric.com";
9282
- var CLI_VERSION = "0.1.39";
9286
+ var CLI_VERSION = "0.1.41";
9283
9287
  var CONFIG_DIR = import_node_path3.default.join(import_node_os2.default.homedir(), ".trainfabric");
9284
9288
  var CONFIG_PATH = import_node_path3.default.join(CONFIG_DIR, "config.json");
9285
9289
  var FALLBACK_SECRET_PATH = import_node_path3.default.join(CONFIG_DIR, "session.enc");
@@ -9618,6 +9622,20 @@ function printUsageSummary(usage) {
9618
9622
  console.log(` ${item.label}: ${formatUsd(item.amountUsd)} - ${item.description}`);
9619
9623
  }
9620
9624
  }
9625
+ function summarizeRunDetail(detail) {
9626
+ return {
9627
+ runId: detail.run.id,
9628
+ status: detail.run.status,
9629
+ dispatchStatus: detail.run.dispatchStatus,
9630
+ durationSeconds: detail.run.durationSeconds,
9631
+ estimatedCostUsd: detail.run.estimatedCostUsd,
9632
+ customerChargeUsd: detail.usageSummary?.customerChargeUsd,
9633
+ reservedGpuSeconds: detail.usageSummary?.reservedGpuSeconds,
9634
+ artifactCount: detail.artifacts?.length ?? 0,
9635
+ metricCount: detail.metrics?.length ?? 0,
9636
+ modelId: detail.run.modelId
9637
+ };
9638
+ }
9621
9639
  function updateConfig(mutate) {
9622
9640
  const config = loadConfig();
9623
9641
  mutate(config);
@@ -9776,7 +9794,14 @@ async function watchRun(runId, json = false, timeoutMs, pollMs) {
9776
9794
  });
9777
9795
  }
9778
9796
  const detail = await handle.wait({ timeoutMs, pollMs });
9779
- printJson(detail);
9797
+ const summary = summarizeRunDetail(detail);
9798
+ if (json) {
9799
+ printJson({ type: "terminal", payload: summary });
9800
+ } else {
9801
+ console.log(
9802
+ `[terminal] status=${summary.status} charge=${formatUsd(summary.customerChargeUsd)} artifacts=${summary.artifactCount}`
9803
+ );
9804
+ }
9780
9805
  }
9781
9806
  function parseDurationMs(value) {
9782
9807
  if (!value) {
@@ -9963,7 +9988,14 @@ program2.command("datasets:get").argument("<datasetId>").description("Fetch data
9963
9988
  });
9964
9989
  program2.command("datasets:delete").argument("<datasetId>").description("Delete a dataset").action(async (datasetId) => {
9965
9990
  const normalizedDatasetId = normalizeId(datasetId, "dataset", "Dataset ID");
9966
- await createClient(loadConfig()).datasets.delete(normalizedDatasetId);
9991
+ const client = createClient(loadConfig());
9992
+ try {
9993
+ await client.datasets.get(normalizedDatasetId);
9994
+ } catch {
9995
+ printJson({ deleted: false, alreadyDeleted: true, id: normalizedDatasetId });
9996
+ return;
9997
+ }
9998
+ await client.datasets.delete(normalizedDatasetId);
9967
9999
  printJson({ deleted: true, id: normalizedDatasetId });
9968
10000
  });
9969
10001
  program2.command("datasets:upload").argument("<file>").option("--project <projectId>").option("--name <name>").description("Upload a dataset through upload sessions").action(async (file, options) => {
@@ -10048,14 +10080,13 @@ program2.command("runs:status").argument("<runId>").description("Fetch full run
10048
10080
  program2.command("runs:logs").argument("<runId>").description("Fetch run logs").action(async (runId) => {
10049
10081
  printJson(await createClient(loadConfig()).runs.logs(normalizeId(runId, "run", "Run ID")));
10050
10082
  });
10051
- program2.command("runs:wait").argument("<runId>").option("--timeout <duration>", "maximum wait duration, for example 30s, 10m, or 1h").option("--poll <duration>", "poll interval, for example 1s or 500ms").description("Wait for a run to reach a terminal state").action(async (runId, options) => {
10083
+ program2.command("runs:wait").argument("<runId>").option("--timeout <duration>", "maximum wait duration, for example 30s, 10m, or 1h").option("--poll <duration>", "poll interval, for example 1s or 500ms").option("--summary", "print a compact terminal run summary").description("Wait for a run to reach a terminal state").action(async (runId, options) => {
10052
10084
  const normalizedRunId = normalizeId(runId, "run", "Run ID");
10053
- printJson(
10054
- await createClient(loadConfig()).runs.wait(normalizedRunId, {
10055
- timeoutMs: parseDurationMs(options.timeout),
10056
- pollMs: parsePositiveMs(options.poll, 1e3)
10057
- })
10058
- );
10085
+ const detail = await createClient(loadConfig()).runs.wait(normalizedRunId, {
10086
+ timeoutMs: parseDurationMs(options.timeout),
10087
+ pollMs: parsePositiveMs(options.poll, 1e3)
10088
+ });
10089
+ printJson(options.summary ? summarizeRunDetail(detail) : detail);
10059
10090
  });
10060
10091
  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) => {
10061
10092
  await watchRun(normalizeId(runId, "run", "Run ID"), Boolean(options.json), parseDurationMs(options.timeout), parsePositiveMs(options.poll, 1e3));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trainfabric",
3
- "version": "0.1.39",
3
+ "version": "0.1.41",
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",