trainfabric 0.1.45 → 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.
- package/dist/index.cjs +93 -13
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -7648,6 +7648,7 @@ var runCreateSchema = external_exports.object({
|
|
|
7648
7648
|
runtimeManifestId: external_exports.string().min(1).optional(),
|
|
7649
7649
|
profileSessionId: external_exports.string().min(1).optional(),
|
|
7650
7650
|
pricingQuoteId: external_exports.string().min(1).optional(),
|
|
7651
|
+
maxCostUsd: external_exports.number().positive().max(1e5).optional(),
|
|
7651
7652
|
experimentTracking: experimentTrackingInputSchema.optional()
|
|
7652
7653
|
});
|
|
7653
7654
|
var jobProfileSchema = runCreateSchema;
|
|
@@ -7693,6 +7694,7 @@ var runQuoteSchema = external_exports.object({
|
|
|
7693
7694
|
hyperparameters: runHyperparametersSchema.optional(),
|
|
7694
7695
|
runtimeVersion: external_exports.string().min(1).optional(),
|
|
7695
7696
|
mode: external_exports.enum(trainingModes).optional(),
|
|
7697
|
+
maxCostUsd: external_exports.number().positive().max(1e5).optional(),
|
|
7696
7698
|
reservationClass: external_exports.enum(reservationClasses).optional(),
|
|
7697
7699
|
slaClass: external_exports.enum(slaClasses).optional(),
|
|
7698
7700
|
runtimeManifestId: external_exports.string().min(1).optional(),
|
|
@@ -7762,11 +7764,20 @@ var serviceAccountCreateSchema = external_exports.object({
|
|
|
7762
7764
|
scopes: external_exports.array(external_exports.enum(apiKeyScopes)).min(1)
|
|
7763
7765
|
});
|
|
7764
7766
|
var billingCheckoutSessionCreateSchema = external_exports.object({
|
|
7765
|
-
amountUsd: external_exports.number().
|
|
7767
|
+
amountUsd: external_exports.number().min(5).max(1e5).optional(),
|
|
7766
7768
|
mode: external_exports.enum(["subscription", "credits"]).default("subscription"),
|
|
7767
7769
|
planId: external_exports.enum(["hobby", "pro"]).optional(),
|
|
7768
7770
|
priceId: external_exports.string().min(1).optional()
|
|
7769
7771
|
});
|
|
7772
|
+
var couponRedeemSchema = external_exports.object({
|
|
7773
|
+
code: external_exports.string().trim().min(1).max(64)
|
|
7774
|
+
});
|
|
7775
|
+
var creditAdjustmentCreateSchema = external_exports.object({
|
|
7776
|
+
amountUsd: external_exports.number().min(-1e5).max(1e5).refine((value) => value !== 0, "Credit adjustment amount cannot be zero."),
|
|
7777
|
+
kind: external_exports.enum(["manual_adjustment", "refund_credit", "refund_debit"]),
|
|
7778
|
+
reason: external_exports.string().trim().min(1).max(500),
|
|
7779
|
+
sourceId: external_exports.string().trim().min(1).max(128).optional()
|
|
7780
|
+
});
|
|
7770
7781
|
var treasuryCounterpartyCreateSchema = external_exports.object({
|
|
7771
7782
|
providerId: external_exports.enum(treasuryProviderIds).default("mercury"),
|
|
7772
7783
|
name: external_exports.string().min(1),
|
|
@@ -8613,7 +8624,27 @@ function encodeRunId(runId) {
|
|
|
8613
8624
|
}
|
|
8614
8625
|
return encodeURIComponent(id);
|
|
8615
8626
|
}
|
|
8627
|
+
function isTransientQuoteError(error) {
|
|
8628
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
8629
|
+
return /status (502|503|504|429)\b|fetch failed|network|ECONNRESET|ETIMEDOUT/i.test(message);
|
|
8630
|
+
}
|
|
8616
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
|
+
}
|
|
8617
8648
|
describeEmptyQuoteFailure(input) {
|
|
8618
8649
|
const compute = input.compute && input.compute !== "auto" && input.compute !== "cpu-sim" ? input.compute : void 0;
|
|
8619
8650
|
const requestedAccelerator = compute?.acceleratorClass;
|
|
@@ -8628,7 +8659,15 @@ var RunsClient = class extends ResourceClient {
|
|
|
8628
8659
|
if (constraints.length === 0) {
|
|
8629
8660
|
return "No quote options were returned for the requested run.";
|
|
8630
8661
|
}
|
|
8631
|
-
|
|
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(", ")}.`;
|
|
8632
8671
|
}
|
|
8633
8672
|
profile(input) {
|
|
8634
8673
|
const payload = jobProfileSchema.parse({
|
|
@@ -8664,26 +8703,29 @@ var RunsClient = class extends ResourceClient {
|
|
|
8664
8703
|
if (profileSessionId) {
|
|
8665
8704
|
return this.waitForProfile(profileSessionId);
|
|
8666
8705
|
}
|
|
8667
|
-
const session = await this.profile(input);
|
|
8668
|
-
return this.waitForProfile(session.id);
|
|
8706
|
+
const session = await this.retryQuoteOperation(() => this.profile(input));
|
|
8707
|
+
return this.retryQuoteOperation(() => this.waitForProfile(session.id));
|
|
8669
8708
|
}
|
|
8670
8709
|
async quote(input) {
|
|
8671
|
-
const detail = await this.ensureReadyProfile(input);
|
|
8710
|
+
const detail = await this.retryQuoteOperation(() => this.ensureReadyProfile(input));
|
|
8672
8711
|
const payload = runQuotesSchema.parse({
|
|
8673
8712
|
...input,
|
|
8674
8713
|
projectId: input.projectId ?? this.parent.projectId,
|
|
8675
8714
|
profileSessionId: detail.session.id
|
|
8676
8715
|
});
|
|
8677
|
-
return this.
|
|
8716
|
+
return this.requestQuoteWithRetry("/v1/runs/quotes", payload);
|
|
8678
8717
|
}
|
|
8679
8718
|
async quoteLegacy(input) {
|
|
8680
|
-
const detail = await this.ensureReadyProfile(input);
|
|
8719
|
+
const detail = await this.retryQuoteOperation(() => this.ensureReadyProfile(input));
|
|
8681
8720
|
const payload = runQuoteSchema.parse({
|
|
8682
8721
|
...input,
|
|
8683
8722
|
projectId: input.projectId ?? this.parent.projectId,
|
|
8684
8723
|
profileSessionId: detail.session.id
|
|
8685
8724
|
});
|
|
8686
|
-
return this.
|
|
8725
|
+
return this.requestQuoteWithRetry("/v1/runs/quote", payload);
|
|
8726
|
+
}
|
|
8727
|
+
async requestQuoteWithRetry(pathname, payload) {
|
|
8728
|
+
return this.retryQuoteOperation(() => this.requestPost(pathname, payload));
|
|
8687
8729
|
}
|
|
8688
8730
|
async create(input) {
|
|
8689
8731
|
const projectId = input.projectId ?? this.parent.projectId;
|
|
@@ -9269,6 +9311,16 @@ function normalizeLearningRate(lr) {
|
|
|
9269
9311
|
}
|
|
9270
9312
|
return parsed;
|
|
9271
9313
|
}
|
|
9314
|
+
function normalizeMaxCost(maxCost) {
|
|
9315
|
+
if (maxCost === void 0) {
|
|
9316
|
+
return void 0;
|
|
9317
|
+
}
|
|
9318
|
+
const parsed = Number(maxCost);
|
|
9319
|
+
if (!Number.isFinite(parsed) || parsed <= 0 || parsed > 1e5) {
|
|
9320
|
+
throw new Error("Max cost must be a positive USD amount up to 100000.");
|
|
9321
|
+
}
|
|
9322
|
+
return Number(parsed.toFixed(2));
|
|
9323
|
+
}
|
|
9272
9324
|
function buildComputeSpec(options) {
|
|
9273
9325
|
const gpuCount = normalizePositiveInteger(options.gpus, "GPU count", 1, 64);
|
|
9274
9326
|
const nodeCount = normalizePositiveInteger(options.nodes, "Node count", 1, 16);
|
|
@@ -9310,7 +9362,7 @@ function buildComputeSpec(options) {
|
|
|
9310
9362
|
|
|
9311
9363
|
// src/index.ts
|
|
9312
9364
|
var DEFAULT_TRAINFABRIC_API_URL2 = "https://api.trainfabric.com";
|
|
9313
|
-
var CLI_VERSION = "0.1.
|
|
9365
|
+
var CLI_VERSION = "0.1.47";
|
|
9314
9366
|
var CONFIG_DIR = import_node_path3.default.join(import_node_os2.default.homedir(), ".trainfabric");
|
|
9315
9367
|
var CONFIG_PATH = import_node_path3.default.join(CONFIG_DIR, "config.json");
|
|
9316
9368
|
var FALLBACK_SECRET_PATH = import_node_path3.default.join(CONFIG_DIR, "session.enc");
|
|
@@ -9749,6 +9801,7 @@ function buildRunInput(options, config = loadConfig()) {
|
|
|
9749
9801
|
pricingQuoteId: quoteId,
|
|
9750
9802
|
evalDatasetId: normalizeOptionalId(options.eval, "dataset", "Eval dataset ID"),
|
|
9751
9803
|
...sourceOptions,
|
|
9804
|
+
maxCostUsd: normalizeMaxCost(options.maxCost),
|
|
9752
9805
|
mode: normalizeTrainingMode(options.mode)
|
|
9753
9806
|
};
|
|
9754
9807
|
if (projectId) {
|
|
@@ -9787,10 +9840,18 @@ function assertQuoteOptions(bundle, options) {
|
|
|
9787
9840
|
if (constraints.length === 0) {
|
|
9788
9841
|
throw new Error("No quote options were returned for the requested run.");
|
|
9789
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");
|
|
9790
9851
|
throw new Error(
|
|
9791
9852
|
`No quote options were returned for the requested run under the current hardware constraints (${constraints.join(
|
|
9792
9853
|
", "
|
|
9793
|
-
)}).
|
|
9854
|
+
)}). ${suggestions.join(", ")}.`
|
|
9794
9855
|
);
|
|
9795
9856
|
}
|
|
9796
9857
|
function filterQuoteBundleForRequestedMode(bundle, options) {
|
|
@@ -9843,7 +9904,8 @@ async function watchRun(runId, json = false, timeoutMs, pollMs) {
|
|
|
9843
9904
|
});
|
|
9844
9905
|
handle.on("log", (event) => {
|
|
9845
9906
|
const payload = event.payload;
|
|
9846
|
-
|
|
9907
|
+
const eventLabel = formatRunEventCode(payload.eventCode);
|
|
9908
|
+
console.log(`[${eventLabel ?? payload.phase ?? "run"}:${payload.level ?? "info"}] ${payload.message ?? ""}`);
|
|
9847
9909
|
});
|
|
9848
9910
|
handle.on("metric", (event) => {
|
|
9849
9911
|
const payload = event.payload;
|
|
@@ -9874,6 +9936,24 @@ async function watchRun(runId, json = false, timeoutMs, pollMs) {
|
|
|
9874
9936
|
);
|
|
9875
9937
|
}
|
|
9876
9938
|
}
|
|
9939
|
+
function formatRunEventCode(eventCode) {
|
|
9940
|
+
switch (eventCode) {
|
|
9941
|
+
case "provider_waiting_for_ssh":
|
|
9942
|
+
return "provider-waiting";
|
|
9943
|
+
case "relay_confirmation_timeout_nonfatal":
|
|
9944
|
+
return "relay-monitoring";
|
|
9945
|
+
case "dependency_installing":
|
|
9946
|
+
return "dependency-installing";
|
|
9947
|
+
case "runtime_bootstrap_fallback":
|
|
9948
|
+
return "runtime-bootstrap";
|
|
9949
|
+
case "training_started":
|
|
9950
|
+
return "training-started";
|
|
9951
|
+
case "artifact_syncing":
|
|
9952
|
+
return "artifact-syncing";
|
|
9953
|
+
default:
|
|
9954
|
+
return void 0;
|
|
9955
|
+
}
|
|
9956
|
+
}
|
|
9877
9957
|
function parseDurationMs(value) {
|
|
9878
9958
|
if (!value) {
|
|
9879
9959
|
return void 0;
|
|
@@ -10082,7 +10162,7 @@ program2.command("datasets:upload").argument("<file>").option("--project <projec
|
|
|
10082
10162
|
});
|
|
10083
10163
|
printJson(dataset);
|
|
10084
10164
|
});
|
|
10085
|
-
program2.command("runs:create").option("--project <projectId>").option("--dataset <datasetId>").option("--model <baseModel>").option("--eval <evalDatasetId>").option("--epochs <epochs>", "number of epochs", "3").option("--lr <lr>", "learning rate", "0.0002").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("--quote <pricingQuoteId>", "launch the exact accepted quote id from runs:quote; use only with --yes").option("--repo <path>", "local repo path for runtime autodetect").option("--git <url>", "git repo URL for runtime metadata").option("--branch <branch>", "git branch for runtime metadata").option("--yes", "confirm that you reviewed pricing with runs:quote --summary and accept fluctuating realized usage").description("Create a training run. When using --quote, do not pass project, dataset, model, compute, mode, source, or hyperparameter flags; launch with `trainfabric runs:create --quote <quoteId> --yes`.").action(async (options, command) => {
|
|
10165
|
+
program2.command("runs:create").option("--project <projectId>").option("--dataset <datasetId>").option("--model <baseModel>").option("--eval <evalDatasetId>").option("--epochs <epochs>", "number of epochs", "3").option("--lr <lr>", "learning rate", "0.0002").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("--max-cost <usd>", "maximum accepted quoted customer charge in USD").option("--quote <pricingQuoteId>", "launch the exact accepted quote id from runs:quote; use only with --yes").option("--repo <path>", "local repo path for runtime autodetect").option("--git <url>", "git repo URL for runtime metadata").option("--branch <branch>", "git branch for runtime metadata").option("--yes", "confirm that you reviewed pricing with runs:quote --summary and accept fluctuating realized usage").description("Create a training run. When using --quote, do not pass project, dataset, model, compute, mode, source, or hyperparameter flags; launch with `trainfabric runs:create --quote <quoteId> --yes`.").action(async (options, command) => {
|
|
10086
10166
|
const config = loadConfig();
|
|
10087
10167
|
assertQuoteCreateHasNoLaunchOverrides(options, command);
|
|
10088
10168
|
const runInput = buildRunInput(options, config);
|
|
@@ -10129,7 +10209,7 @@ program2.command("runtime:build").option("--project <projectId>").requiredOption
|
|
|
10129
10209
|
)
|
|
10130
10210
|
);
|
|
10131
10211
|
});
|
|
10132
|
-
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) => {
|
|
10212
|
+
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("--max-cost <usd>", "maximum accepted quoted customer charge in USD").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) => {
|
|
10133
10213
|
const config = loadConfig();
|
|
10134
10214
|
const bundle = filterQuoteBundleForRequestedMode(
|
|
10135
10215
|
await createClient(config).runs.quote(buildRunInput(options, config)),
|