trainfabric 0.1.38 → 0.1.40

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 +43 -13
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -9279,7 +9279,7 @@ function buildComputeSpec(options) {
9279
9279
 
9280
9280
  // src/index.ts
9281
9281
  var DEFAULT_TRAINFABRIC_API_URL2 = "https://api.trainfabric.com";
9282
- var CLI_VERSION = "0.1.38";
9282
+ var CLI_VERSION = "0.1.40";
9283
9283
  var CONFIG_DIR = import_node_path3.default.join(import_node_os2.default.homedir(), ".trainfabric");
9284
9284
  var CONFIG_PATH = import_node_path3.default.join(CONFIG_DIR, "config.json");
9285
9285
  var FALLBACK_SECRET_PATH = import_node_path3.default.join(CONFIG_DIR, "session.enc");
@@ -9579,9 +9579,12 @@ function printQuoteSummary(bundle) {
9579
9579
  console.log(` estimated infra cost: ${formatUsd(quote.expectedInfraCostUsd)}`);
9580
9580
  console.log(` infra GPU-hour equivalent: ${formatUsdPerGpuHour(quote.expectedInfraCostUsd, gpuCount, quote.estimatedRuntimeSeconds)}`);
9581
9581
  console.log(` estimated margin: ${formatUsd(quote.expectedMarginUsd)} (${formatPercent(quote.expectedMarginRatio)})`);
9582
- console.log(` profiled runtime estimate: ${Math.round(quote.estimatedRuntimeSeconds / 60)} min`);
9583
- if (quote.reservationWindowSeconds && quote.reservationWindowSeconds !== quote.estimatedRuntimeSeconds) {
9584
- console.log(` reservation window: ${Math.round(quote.reservationWindowSeconds / 60)} min`);
9582
+ if (quote.profiledRuntimeSeconds && quote.profiledRuntimeSeconds !== quote.estimatedRuntimeSeconds) {
9583
+ console.log(` profiled compute estimate: ${Math.round(quote.profiledRuntimeSeconds / 60)} min`);
9584
+ }
9585
+ console.log(` estimated runtime: ${Math.round(quote.estimatedRuntimeSeconds / 60)} min`);
9586
+ if (quote.estimatedCompletionSeconds && quote.estimatedCompletionSeconds !== quote.estimatedRuntimeSeconds) {
9587
+ console.log(` estimated completion window: ${Math.round(quote.estimatedCompletionSeconds / 60)} min`);
9585
9588
  }
9586
9589
  console.log(` reserved GPU time: ${formatGpuHours(gpuCount, quote.reservationWindowSeconds ?? quote.estimatedRuntimeSeconds)}`);
9587
9590
  console.log(` data path: ${quote.dataPath ?? "auto"}`);
@@ -9615,6 +9618,20 @@ function printUsageSummary(usage) {
9615
9618
  console.log(` ${item.label}: ${formatUsd(item.amountUsd)} - ${item.description}`);
9616
9619
  }
9617
9620
  }
9621
+ function summarizeRunDetail(detail) {
9622
+ return {
9623
+ runId: detail.run.id,
9624
+ status: detail.run.status,
9625
+ dispatchStatus: detail.run.dispatchStatus,
9626
+ durationSeconds: detail.run.durationSeconds,
9627
+ estimatedCostUsd: detail.run.estimatedCostUsd,
9628
+ customerChargeUsd: detail.usageSummary?.customerChargeUsd,
9629
+ reservedGpuSeconds: detail.usageSummary?.reservedGpuSeconds,
9630
+ artifactCount: detail.artifacts?.length ?? 0,
9631
+ metricCount: detail.metrics?.length ?? 0,
9632
+ modelId: detail.run.modelId
9633
+ };
9634
+ }
9618
9635
  function updateConfig(mutate) {
9619
9636
  const config = loadConfig();
9620
9637
  mutate(config);
@@ -9773,7 +9790,14 @@ async function watchRun(runId, json = false, timeoutMs, pollMs) {
9773
9790
  });
9774
9791
  }
9775
9792
  const detail = await handle.wait({ timeoutMs, pollMs });
9776
- printJson(detail);
9793
+ const summary = summarizeRunDetail(detail);
9794
+ if (json) {
9795
+ printJson({ type: "terminal", payload: summary });
9796
+ } else {
9797
+ console.log(
9798
+ `[terminal] status=${summary.status} charge=${formatUsd(summary.customerChargeUsd)} artifacts=${summary.artifactCount}`
9799
+ );
9800
+ }
9777
9801
  }
9778
9802
  function parseDurationMs(value) {
9779
9803
  if (!value) {
@@ -9960,7 +9984,14 @@ program2.command("datasets:get").argument("<datasetId>").description("Fetch data
9960
9984
  });
9961
9985
  program2.command("datasets:delete").argument("<datasetId>").description("Delete a dataset").action(async (datasetId) => {
9962
9986
  const normalizedDatasetId = normalizeId(datasetId, "dataset", "Dataset ID");
9963
- await createClient(loadConfig()).datasets.delete(normalizedDatasetId);
9987
+ const client = createClient(loadConfig());
9988
+ try {
9989
+ await client.datasets.get(normalizedDatasetId);
9990
+ } catch {
9991
+ printJson({ deleted: false, alreadyDeleted: true, id: normalizedDatasetId });
9992
+ return;
9993
+ }
9994
+ await client.datasets.delete(normalizedDatasetId);
9964
9995
  printJson({ deleted: true, id: normalizedDatasetId });
9965
9996
  });
9966
9997
  program2.command("datasets:upload").argument("<file>").option("--project <projectId>").option("--name <name>").description("Upload a dataset through upload sessions").action(async (file, options) => {
@@ -10045,14 +10076,13 @@ program2.command("runs:status").argument("<runId>").description("Fetch full run
10045
10076
  program2.command("runs:logs").argument("<runId>").description("Fetch run logs").action(async (runId) => {
10046
10077
  printJson(await createClient(loadConfig()).runs.logs(normalizeId(runId, "run", "Run ID")));
10047
10078
  });
10048
- 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) => {
10079
+ 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) => {
10049
10080
  const normalizedRunId = normalizeId(runId, "run", "Run ID");
10050
- printJson(
10051
- await createClient(loadConfig()).runs.wait(normalizedRunId, {
10052
- timeoutMs: parseDurationMs(options.timeout),
10053
- pollMs: parsePositiveMs(options.poll, 1e3)
10054
- })
10055
- );
10081
+ const detail = await createClient(loadConfig()).runs.wait(normalizedRunId, {
10082
+ timeoutMs: parseDurationMs(options.timeout),
10083
+ pollMs: parsePositiveMs(options.poll, 1e3)
10084
+ });
10085
+ printJson(options.summary ? summarizeRunDetail(detail) : detail);
10056
10086
  });
10057
10087
  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) => {
10058
10088
  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.38",
3
+ "version": "0.1.40",
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",