trainfabric 0.1.46 → 0.1.47

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 -22
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -8626,9 +8626,25 @@ function encodeRunId(runId) {
8626
8626
  }
8627
8627
  function isTransientQuoteError(error) {
8628
8628
  const message = error instanceof Error ? error.message : String(error);
8629
- return /status (502|503|504)\b/i.test(message);
8629
+ return /status (502|503|504|429)\b|fetch failed|network|ECONNRESET|ETIMEDOUT/i.test(message);
8630
8630
  }
8631
8631
  var RunsClient = class extends ResourceClient {
8632
+ async retryQuoteOperation(operation) {
8633
+ const attempts = Math.max(1, Number(process.env.TRAINFABRIC_QUOTE_RETRY_ATTEMPTS ?? 5));
8634
+ let lastError;
8635
+ for (let attempt = 1; attempt <= attempts; attempt += 1) {
8636
+ try {
8637
+ return await operation();
8638
+ } catch (error) {
8639
+ lastError = error;
8640
+ if (!isTransientQuoteError(error) || attempt === attempts) {
8641
+ throw error;
8642
+ }
8643
+ await wait(Math.min(5e3, 400 * 2 ** (attempt - 1)));
8644
+ }
8645
+ }
8646
+ throw lastError instanceof Error ? lastError : new Error("Quote request failed.");
8647
+ }
8632
8648
  describeEmptyQuoteFailure(input) {
8633
8649
  const compute = input.compute && input.compute !== "auto" && input.compute !== "cpu-sim" ? input.compute : void 0;
8634
8650
  const requestedAccelerator = compute?.acceleratorClass;
@@ -8643,7 +8659,15 @@ var RunsClient = class extends ResourceClient {
8643
8659
  if (constraints.length === 0) {
8644
8660
  return "No quote options were returned for the requested run.";
8645
8661
  }
8646
- return `No quote options were returned for the requested run under the current hardware constraints (${constraints.join(", ")}). Omit the accelerator constraint or request a larger GPU memory floor.`;
8662
+ const suggestions = [];
8663
+ if (requestedAccelerator) {
8664
+ suggestions.push("omit the accelerator constraint");
8665
+ }
8666
+ if (requestedMemory) {
8667
+ suggestions.push("lower --min-memory if it excludes available GPUs");
8668
+ }
8669
+ suggestions.push("try a different mode or retry when capacity changes");
8670
+ return `No quote options were returned for the requested run under the current hardware constraints (${constraints.join(", ")}). ${suggestions.join(", ")}.`;
8647
8671
  }
8648
8672
  profile(input) {
8649
8673
  const payload = jobProfileSchema.parse({
@@ -8679,11 +8703,11 @@ var RunsClient = class extends ResourceClient {
8679
8703
  if (profileSessionId) {
8680
8704
  return this.waitForProfile(profileSessionId);
8681
8705
  }
8682
- const session = await this.profile(input);
8683
- return this.waitForProfile(session.id);
8706
+ const session = await this.retryQuoteOperation(() => this.profile(input));
8707
+ return this.retryQuoteOperation(() => this.waitForProfile(session.id));
8684
8708
  }
8685
8709
  async quote(input) {
8686
- const detail = await this.ensureReadyProfile(input);
8710
+ const detail = await this.retryQuoteOperation(() => this.ensureReadyProfile(input));
8687
8711
  const payload = runQuotesSchema.parse({
8688
8712
  ...input,
8689
8713
  projectId: input.projectId ?? this.parent.projectId,
@@ -8692,7 +8716,7 @@ var RunsClient = class extends ResourceClient {
8692
8716
  return this.requestQuoteWithRetry("/v1/runs/quotes", payload);
8693
8717
  }
8694
8718
  async quoteLegacy(input) {
8695
- const detail = await this.ensureReadyProfile(input);
8719
+ const detail = await this.retryQuoteOperation(() => this.ensureReadyProfile(input));
8696
8720
  const payload = runQuoteSchema.parse({
8697
8721
  ...input,
8698
8722
  projectId: input.projectId ?? this.parent.projectId,
@@ -8701,20 +8725,7 @@ var RunsClient = class extends ResourceClient {
8701
8725
  return this.requestQuoteWithRetry("/v1/runs/quote", payload);
8702
8726
  }
8703
8727
  async requestQuoteWithRetry(pathname, payload) {
8704
- const attempts = Math.max(1, Number(process.env.TRAINFABRIC_QUOTE_RETRY_ATTEMPTS ?? 3));
8705
- let lastError;
8706
- for (let attempt = 1; attempt <= attempts; attempt += 1) {
8707
- try {
8708
- return await this.requestPost(pathname, payload);
8709
- } catch (error) {
8710
- lastError = error;
8711
- if (!isTransientQuoteError(error) || attempt === attempts) {
8712
- throw error;
8713
- }
8714
- await wait(500 * attempt);
8715
- }
8716
- }
8717
- throw lastError instanceof Error ? lastError : new Error("Quote request failed.");
8728
+ return this.retryQuoteOperation(() => this.requestPost(pathname, payload));
8718
8729
  }
8719
8730
  async create(input) {
8720
8731
  const projectId = input.projectId ?? this.parent.projectId;
@@ -9351,7 +9362,7 @@ function buildComputeSpec(options) {
9351
9362
 
9352
9363
  // src/index.ts
9353
9364
  var DEFAULT_TRAINFABRIC_API_URL2 = "https://api.trainfabric.com";
9354
- var CLI_VERSION = "0.1.46";
9365
+ var CLI_VERSION = "0.1.47";
9355
9366
  var CONFIG_DIR = import_node_path3.default.join(import_node_os2.default.homedir(), ".trainfabric");
9356
9367
  var CONFIG_PATH = import_node_path3.default.join(CONFIG_DIR, "config.json");
9357
9368
  var FALLBACK_SECRET_PATH = import_node_path3.default.join(CONFIG_DIR, "session.enc");
@@ -9829,10 +9840,18 @@ function assertQuoteOptions(bundle, options) {
9829
9840
  if (constraints.length === 0) {
9830
9841
  throw new Error("No quote options were returned for the requested run.");
9831
9842
  }
9843
+ const suggestions = [];
9844
+ if (options.accelerator) {
9845
+ suggestions.push("omit --accelerator");
9846
+ }
9847
+ if (options.minMemory) {
9848
+ suggestions.push("adjust --min-memory if it excludes available GPUs");
9849
+ }
9850
+ suggestions.push("try a different --mode or retry when capacity changes");
9832
9851
  throw new Error(
9833
9852
  `No quote options were returned for the requested run under the current hardware constraints (${constraints.join(
9834
9853
  ", "
9835
- )}). Try a different --mode, omit --accelerator, adjust --min-memory if it excludes available GPUs, or retry when capacity changes.`
9854
+ )}). ${suggestions.join(", ")}.`
9836
9855
  );
9837
9856
  }
9838
9857
  function filterQuoteBundleForRequestedMode(bundle, options) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trainfabric",
3
- "version": "0.1.46",
3
+ "version": "0.1.47",
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",