trainfabric 0.1.36 → 0.1.38

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 +31 -11
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -8480,18 +8480,28 @@ var RunHandle = class {
8480
8480
  const startedAt = Date.now();
8481
8481
  const pollMs = options?.pollMs ?? 1e3;
8482
8482
  const timeoutMs = options?.timeoutMs;
8483
+ let transientFailures = 0;
8483
8484
  for (; ; ) {
8484
- const detail = await this.client.runs.get(this.snapshot.id);
8485
- this.snapshot = detail.run;
8486
- if (["completed", "failed", "canceled", "terminated"].includes(detail.run.status)) {
8487
- this.close();
8488
- return detail;
8485
+ try {
8486
+ const detail = await this.client.runs.get(this.snapshot.id);
8487
+ transientFailures = 0;
8488
+ this.snapshot = detail.run;
8489
+ if (["completed", "failed", "canceled", "terminated"].includes(detail.run.status)) {
8490
+ this.close();
8491
+ return detail;
8492
+ }
8493
+ } catch (error) {
8494
+ if (!this.isRetryablePollingError(error)) {
8495
+ this.close();
8496
+ throw error;
8497
+ }
8498
+ transientFailures += 1;
8489
8499
  }
8490
8500
  if (timeoutMs !== void 0 && Date.now() - startedAt > timeoutMs) {
8491
8501
  this.close();
8492
8502
  throw new Error(`Timed out waiting for run ${this.snapshot.id}.`);
8493
8503
  }
8494
- await new Promise((resolve) => setTimeout(resolve, pollMs));
8504
+ await new Promise((resolve) => setTimeout(resolve, Math.min(pollMs * Math.max(transientFailures, 1), 1e4)));
8495
8505
  }
8496
8506
  }
8497
8507
  close() {
@@ -8505,6 +8515,12 @@ var RunHandle = class {
8505
8515
  this.streaming = true;
8506
8516
  void this.streamLoop();
8507
8517
  }
8518
+ isRetryablePollingError(error) {
8519
+ if (!(error instanceof Error)) {
8520
+ return false;
8521
+ }
8522
+ return /status (502|503|504|429)\b|fetch failed|network|ECONNRESET|ETIMEDOUT|ENOTFOUND/i.test(error.message);
8523
+ }
8508
8524
  async streamLoop() {
8509
8525
  while (this.shouldStream) {
8510
8526
  this.abortController = new AbortController();
@@ -8607,7 +8623,8 @@ var RunsClient = class extends ResourceClient {
8607
8623
  }
8608
8624
  async waitForProfile(profileSessionId, options) {
8609
8625
  const pollMs = options?.pollMs ?? 250;
8610
- const timeoutMs = options?.timeoutMs ?? 2e4;
8626
+ const envTimeoutMs = Number(process.env.TRAINFABRIC_PROFILE_TIMEOUT_MS);
8627
+ const timeoutMs = options?.timeoutMs ?? (Number.isFinite(envTimeoutMs) && envTimeoutMs > 0 ? envTimeoutMs : 9e4);
8611
8628
  const startedAt = Date.now();
8612
8629
  for (; ; ) {
8613
8630
  const detail = await this.profileStatus(profileSessionId);
@@ -9262,7 +9279,7 @@ function buildComputeSpec(options) {
9262
9279
 
9263
9280
  // src/index.ts
9264
9281
  var DEFAULT_TRAINFABRIC_API_URL2 = "https://api.trainfabric.com";
9265
- var CLI_VERSION = "0.1.36";
9282
+ var CLI_VERSION = "0.1.38";
9266
9283
  var CONFIG_DIR = import_node_path3.default.join(import_node_os2.default.homedir(), ".trainfabric");
9267
9284
  var CONFIG_PATH = import_node_path3.default.join(CONFIG_DIR, "config.json");
9268
9285
  var FALLBACK_SECRET_PATH = import_node_path3.default.join(CONFIG_DIR, "session.enc");
@@ -9562,8 +9579,11 @@ function printQuoteSummary(bundle) {
9562
9579
  console.log(` estimated infra cost: ${formatUsd(quote.expectedInfraCostUsd)}`);
9563
9580
  console.log(` infra GPU-hour equivalent: ${formatUsdPerGpuHour(quote.expectedInfraCostUsd, gpuCount, quote.estimatedRuntimeSeconds)}`);
9564
9581
  console.log(` estimated margin: ${formatUsd(quote.expectedMarginUsd)} (${formatPercent(quote.expectedMarginRatio)})`);
9565
- console.log(` estimated runtime: ${Math.round(quote.estimatedRuntimeSeconds / 60)} min`);
9566
- console.log(` reserved GPU time: ${formatGpuHours(gpuCount, quote.estimatedRuntimeSeconds)}`);
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`);
9585
+ }
9586
+ console.log(` reserved GPU time: ${formatGpuHours(gpuCount, quote.reservationWindowSeconds ?? quote.estimatedRuntimeSeconds)}`);
9567
9587
  console.log(` data path: ${quote.dataPath ?? "auto"}`);
9568
9588
  console.log(` GPUs: ${gpuCount}`);
9569
9589
  console.log(` pool: ${quote.selectedPoolId}`);
@@ -10002,7 +10022,7 @@ program2.command("runtime:build").option("--project <projectId>").requiredOption
10002
10022
  )
10003
10023
  );
10004
10024
  });
10005
- 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) => {
10025
+ 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("--json", "print raw JSON output; this is the default unless --summary is used").option("--summary", "print a human-readable price summary instead of raw JSON").description("Preview Efficient, Balanced, and Power launch options").action(async (options) => {
10006
10026
  const config = loadConfig();
10007
10027
  const bundle = filterQuoteBundleForRequestedMode(
10008
10028
  await createClient(config).runs.quote(buildRunInput(options, config)),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trainfabric",
3
- "version": "0.1.36",
3
+ "version": "0.1.38",
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",