trainfabric 0.1.72 → 0.1.74

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 +48 -3
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -7778,6 +7778,13 @@ var creditAdjustmentCreateSchema = external_exports.object({
7778
7778
  reason: external_exports.string().trim().min(1).max(500),
7779
7779
  sourceId: external_exports.string().trim().min(1).max(128).optional()
7780
7780
  });
7781
+ var supportRequestCreateSchema = external_exports.object({
7782
+ category: external_exports.enum(["billing", "refund", "run", "abuse", "general"]).default("general"),
7783
+ message: external_exports.string().trim().min(10).max(5e3),
7784
+ runId: external_exports.string().trim().min(1).max(128).optional(),
7785
+ invoiceId: external_exports.string().trim().min(1).max(128).optional(),
7786
+ subject: external_exports.string().trim().min(1).max(160)
7787
+ });
7781
7788
  var treasuryCounterpartyCreateSchema = external_exports.object({
7782
7789
  providerId: external_exports.enum(treasuryProviderIds).default("mercury"),
7783
7790
  name: external_exports.string().min(1),
@@ -9248,6 +9255,7 @@ var INTERCONNECT_TYPES = /* @__PURE__ */ new Set(["pcie", "nvlink"]);
9248
9255
  var BASE_MODELS = new Set(baseModels);
9249
9256
  var TRAINING_MODES = new Set(trainingModes);
9250
9257
  var MAX_MIN_GPU_MEMORY_GB = 192;
9258
+ var MIN_PROFILED_QUOTE_MAX_COST_USD = 1;
9251
9259
  function normalizePositiveInteger(value, label, fallback, max) {
9252
9260
  const parsed = Number(value ?? String(fallback));
9253
9261
  if (!Number.isInteger(parsed) || parsed <= 0) {
@@ -9317,6 +9325,9 @@ function normalizeMaxCost(maxCost) {
9317
9325
  if (!Number.isFinite(parsed) || parsed <= 0 || parsed > 1e5) {
9318
9326
  throw new Error("Max cost must be a positive USD amount up to 100000.");
9319
9327
  }
9328
+ if (parsed < MIN_PROFILED_QUOTE_MAX_COST_USD) {
9329
+ throw new Error(`Max cost is below the minimum profiled quote floor of $${MIN_PROFILED_QUOTE_MAX_COST_USD.toFixed(2)}. Increase --max-cost before running quote profiling.`);
9330
+ }
9320
9331
  return Number(parsed.toFixed(2));
9321
9332
  }
9322
9333
  function buildComputeSpec(options) {
@@ -9360,7 +9371,7 @@ function buildComputeSpec(options) {
9360
9371
 
9361
9372
  // src/index.ts
9362
9373
  var DEFAULT_TRAINFABRIC_API_URL2 = "https://api.trainfabric.com";
9363
- var CLI_VERSION = "0.1.72";
9374
+ var CLI_VERSION = "0.1.74";
9364
9375
  var CONFIG_DIR = import_node_path3.default.join(import_node_os2.default.homedir(), ".trainfabric");
9365
9376
  var CONFIG_PATH = import_node_path3.default.join(CONFIG_DIR, "config.json");
9366
9377
  var FALLBACK_SECRET_PATH = import_node_path3.default.join(CONFIG_DIR, "session.enc");
@@ -9661,6 +9672,7 @@ function formatUsdPerGpuHour(amountUsd, gpuCount, runtimeSeconds) {
9661
9672
  function printQuoteSummary(bundle) {
9662
9673
  console.log(`Quote bundle ${bundle.id}`);
9663
9674
  console.log("Prices are estimates. GPU supplier prices, capacity, spot availability, streaming volume, and runtime can fluctuate before launch.");
9675
+ console.log("Accepted quotes are fixed-plan launches: if the selected pool, market, topology, or data path is unavailable at launch, TrainFabric fails safely without billing and asks you to request a fresh quote.");
9664
9676
  for (const item of bundle.quotes) {
9665
9677
  const quote = item.quote;
9666
9678
  const gpuCount = item.configuration.gpuCount;
@@ -9683,11 +9695,15 @@ function printQuoteSummary(bundle) {
9683
9695
  console.log(` data path: ${quote.dataPath ?? "auto"}`);
9684
9696
  console.log(` GPUs: ${gpuCount}`);
9685
9697
  console.log(` pool: ${quote.selectedPoolId}`);
9698
+ if (quote.topology) {
9699
+ console.log(` topology: ${quote.topology}`);
9700
+ }
9686
9701
  if (quote.fallbackPolicy) {
9687
9702
  console.log(` fallback: ${quote.fallbackPolicy.acceptedQuoteFallbackAllowed ? "allowed" : "disabled"} for accepted quote`);
9688
9703
  if (quote.fallbackPolicy.fallbackPoolId) {
9689
- console.log(` fallback candidate: ${quote.fallbackPolicy.fallbackPoolId}`);
9704
+ console.log(` fallback candidate: ${quote.fallbackPolicy.fallbackPoolId} (informational only; not used for accepted quote launch)`);
9690
9705
  }
9706
+ console.log(` fallback contract: ${quote.fallbackPolicy.message}`);
9691
9707
  }
9692
9708
  console.log(` launch with: --quote ${quote.id}`);
9693
9709
  }
@@ -9717,6 +9733,26 @@ function printUsageSummary(usage) {
9717
9733
  console.log(` ${item.label}: ${formatUsd(item.amountUsd)} - ${item.description}`);
9718
9734
  }
9719
9735
  }
9736
+ function summarizeUsageRecords(usage) {
9737
+ const sumMetric = (metric) => Number(
9738
+ usage.filter((record) => record.metric === metric).reduce((sum, record) => sum + record.quantity, 0).toFixed(6)
9739
+ );
9740
+ const customerChargeUsd = sumMetric("customer_charge_usd");
9741
+ const infraCostUsd = sumMetric("infra_cost_usd");
9742
+ const marginUsd = sumMetric("margin_usd");
9743
+ return {
9744
+ billableUnit: "normalized_tflop_seconds",
9745
+ normalizedTflopSeconds: sumMetric("normalized_tflop_seconds"),
9746
+ reservedGpuSeconds: sumMetric("reserved_gpu_seconds"),
9747
+ customerChargeUsd,
9748
+ usageChargeUsd: customerChargeUsd,
9749
+ infraCostUsd,
9750
+ supplierComputeCostUsd: sumMetric("supplier_compute_cost_usd"),
9751
+ dataPlaneCostUsd: sumMetric("data_plane_cost_usd"),
9752
+ marginUsd,
9753
+ marginRatio: customerChargeUsd > 0 ? Number((marginUsd / customerChargeUsd).toFixed(6)) : 0
9754
+ };
9755
+ }
9720
9756
  function printInvoiceSummary(invoices) {
9721
9757
  if (invoices.length === 0) {
9722
9758
  console.log("No invoices found.");
@@ -10309,7 +10345,13 @@ program2.command("runtime:detect").option("--project <projectId>").option("--rep
10309
10345
  }
10310
10346
  printJson(redactInlineSource(detection));
10311
10347
  });
10312
- program2.command("runtime:build").option("--json", "print raw JSON output; this is the default").option("--project <projectId>").requiredOption("--detection <detectionId>").description("Build or reuse a cached runtime image from a runtime detection").action(async (options) => {
10348
+ program2.command("runtime:build").option("--json", "print raw JSON output; this is the default").option("--project <projectId>").addOption(new Option("--repo <path>").hideHelp()).addOption(new Option("--git <url>").hideHelp()).addOption(new Option("--branch <branch>").hideHelp()).option("--detection <detectionId>").description("Build or reuse a cached runtime image from a runtime detection").action(async (options) => {
10349
+ if (options.repo || options.git || options.branch) {
10350
+ throw new Error("runtime:build requires --detection. Run runtime:detect --repo or --git first, then pass the returned detection ID.");
10351
+ }
10352
+ if (!options.detection) {
10353
+ throw new Error("Runtime detection ID is required. Run runtime:detect first, then pass --detection <detectionId>.");
10354
+ }
10313
10355
  const config = loadConfig();
10314
10356
  printJson(
10315
10357
  redactInlineSource(
@@ -10452,11 +10494,14 @@ program2.command("billing:usage").option("--json", "print raw JSON output; this
10452
10494
  return;
10453
10495
  }
10454
10496
  const usage = await client.billing.getUsage(unit);
10497
+ const totals = summarizeUsageRecords(usage);
10455
10498
  printJson({
10456
10499
  recordCount: usage.length,
10457
10500
  responseShape: "usage_summary",
10458
10501
  runId: null,
10459
10502
  unit: unit ?? "all",
10503
+ ...totals,
10504
+ usageTotals: totals,
10460
10505
  usage
10461
10506
  });
10462
10507
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trainfabric",
3
- "version": "0.1.72",
3
+ "version": "0.1.74",
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",