@tuned-tensor/cli 0.13.1-beta.3 → 0.13.1-beta.5

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.
@@ -5,6 +5,7 @@ import {
5
5
  assertFoundationSpecReady,
6
6
  assertLocalRunInputReady,
7
7
  assertUsableModelArtifact,
8
+ assessHardware,
8
9
  baseModelRevisionSchema,
9
10
  behaviorSpecExampleSchema,
10
11
  buildBundledPythonCommand,
@@ -33,6 +34,7 @@ import {
33
34
  foundationHyperparametersSchema,
34
35
  foundationPlaceholderIssues,
35
36
  generatedPlaceholderIssues,
37
+ hardenExistingLocalStore,
36
38
  initLocalRunnerConfigFile,
37
39
  initLocalSpecFile,
38
40
  isFoundationSpecFile,
@@ -71,8 +73,8 @@ import {
71
73
  withBundledPythonEnvironment,
72
74
  withHuggingFaceCacheEnvironment,
73
75
  withOfflineHuggingFaceCacheEnvironment,
74
- writeJsonAtomic
75
- } from "./chunk-2P2RL23O.js";
76
+ writePrivateJsonAtomic
77
+ } from "./chunk-AVMRHDFY.js";
76
78
 
77
79
  // src/local-runtime/index.ts
78
80
  import { readFileSync, realpathSync } from "fs";
@@ -604,7 +606,8 @@ async function serveLocalModel(launch) {
604
606
  }
605
607
 
606
608
  // src/local-runtime/active-model.ts
607
- import { appendFile, readFile } from "fs/promises";
609
+ import { randomUUID } from "crypto";
610
+ import { appendFile, chmod, readFile, rename, writeFile as writeFile2 } from "fs/promises";
608
611
  import { join as join2 } from "path";
609
612
  function pointerPath(store) {
610
613
  return join2(store.root, "active-model.json");
@@ -613,6 +616,7 @@ function historyPath(store) {
613
616
  return join2(store.root, "activation-history.jsonl");
614
617
  }
615
618
  async function readPointer(store) {
619
+ if (!await hardenExistingLocalStore(store.root)) return null;
616
620
  try {
617
621
  const value = JSON.parse(await readFile(pointerPath(store), "utf8"));
618
622
  if (value.schema_version !== 1 || !["activate", "rollback"].includes(value.action) || value.model_id !== null && typeof value.model_id !== "string" || value.run_id !== null && typeof value.run_id !== "string" || value.previous_model_id !== null && typeof value.previous_model_id !== "string") {
@@ -624,6 +628,24 @@ async function readPointer(store) {
624
628
  throw error;
625
629
  }
626
630
  }
631
+ async function writePrivatePointer(path, pointer) {
632
+ const temporary = `${path}.${process.pid}.${Date.now()}.${randomUUID()}.tmp`;
633
+ await writeFile2(temporary, `${JSON.stringify(pointer, null, 2)}
634
+ `, {
635
+ encoding: "utf8",
636
+ mode: 384
637
+ });
638
+ await rename(temporary, path);
639
+ await chmod(path, 384);
640
+ }
641
+ async function appendPrivateHistory(path, pointer) {
642
+ await appendFile(path, `${JSON.stringify(pointer)}
643
+ `, {
644
+ encoding: "utf8",
645
+ mode: 384
646
+ });
647
+ await chmod(path, 384);
648
+ }
627
649
  async function assertModelCanActivate(store, modelId) {
628
650
  const model = await store.getModel(modelId);
629
651
  const run = await store.getRun(model.run_id);
@@ -645,9 +667,8 @@ async function assertModelCanActivate(store, modelId) {
645
667
  }
646
668
  async function publishPointer(store, pointer) {
647
669
  await store.ensure();
648
- await writeJsonAtomic(pointerPath(store), pointer);
649
- await appendFile(historyPath(store), `${JSON.stringify(pointer)}
650
- `, "utf8");
670
+ await writePrivatePointer(pointerPath(store), pointer);
671
+ await appendPrivateHistory(historyPath(store), pointer);
651
672
  return pointer;
652
673
  }
653
674
  async function getActiveModel(store) {
@@ -721,6 +742,7 @@ Commands:
721
742
  info Show package and runner information
722
743
  init [--name "My Local Model"] [--model Qwen/Qwen3.5-2B] [--output tunedtensor.json] [--profile spark] [--force]
723
744
  doctor [tunedtensor.json] [--config local-runner.json]
745
+ hardware [--config local-runner.json] [--quick]
724
746
  validate [tunedtensor.json] [--config local-runner.json]
725
747
  run [tunedtensor.json] [--config local-runner.json] [--dry-run] [--verbose] [--quiet]
726
748
  serve <model-id|active|base> [--config local-runner.json] [--host 127.0.0.1] [--port 8000]
@@ -732,8 +754,9 @@ Global options:
732
754
  -V, --version Show the installed version
733
755
 
734
756
  The run command writes local artifacts under config.artifactRoot, defaulting to
735
- .tt-local/artifacts. The file-backed local store defaults to
736
- ~/.tuned-tensor-local unless config.storeRoot or TT_LOCAL_HOME is set.`);
757
+ .tuned-tensor/artifacts. The file-backed local store defaults to
758
+ ~/.tuned-tensor/store unless config.storeRoot, TT_LOCAL_HOME, or
759
+ TUNED_TENSOR_HOME is set.`);
737
760
  }
738
761
  var CONFIG_OPTION = { name: "--config", value: "path", description: "Local runner config JSON path" };
739
762
  var VERBOSE_OPTION = { name: "--verbose", description: "Stream subprocess output" };
@@ -780,6 +803,15 @@ var COMMAND_DEFINITIONS = {
780
803
  options: [CONFIG_OPTION],
781
804
  maxPositionals: 1
782
805
  },
806
+ hardware: {
807
+ usage: "tt hardware [--config path] [--quick]",
808
+ description: "Inventory this host and report what TT can train, fine-tune, or infer.",
809
+ options: [
810
+ CONFIG_OPTION,
811
+ { name: "--quick", description: "Skip the bundled torch/uv runtime probe" }
812
+ ],
813
+ maxPositionals: 0
814
+ },
783
815
  validate: {
784
816
  usage: "tt validate [tunedtensor.json] [options]",
785
817
  description: "Validate a local behavior spec without executing it.",
@@ -1409,9 +1441,28 @@ async function main(argv) {
1409
1441
  config_path: configSelection.path ?? null,
1410
1442
  checks
1411
1443
  });
1444
+ try {
1445
+ await assessHardware({
1446
+ config: configSelection.config,
1447
+ quick: true
1448
+ });
1449
+ } catch {
1450
+ }
1412
1451
  if (!ok) process.exitCode = 1;
1413
1452
  return;
1414
1453
  }
1454
+ if (command === "hardware") {
1455
+ const configSelection = await configSelectionFromArgv(argv);
1456
+ const report = await assessHardware({
1457
+ config: configSelection.config,
1458
+ quick: hasFlag(argv, "--quick")
1459
+ });
1460
+ printJson({
1461
+ ...report,
1462
+ config_path: configSelection.path ?? null
1463
+ });
1464
+ return;
1465
+ }
1415
1466
  if (command === "init") {
1416
1467
  const outputPath = resolve3(readOption(argv, "--output") ?? DEFAULT_LOCAL_SPEC_PATH);
1417
1468
  const profile = readOption(argv, "--profile");
@@ -1724,6 +1775,7 @@ export {
1724
1775
  generatedPlaceholderIssues,
1725
1776
  getActiveModel,
1726
1777
  getLocalRunnerInfo,
1778
+ hardenExistingLocalStore,
1727
1779
  initLocalRunnerConfigFile,
1728
1780
  initLocalSpecFile,
1729
1781
  isFoundationSpecFile,
@@ -1755,6 +1807,7 @@ export {
1755
1807
  validateLocalPipeline,
1756
1808
  verifyLocalBaseModel,
1757
1809
  verifyLocalModelServerLaunch,
1758
- verifyModelPrefetchCacheReport
1810
+ verifyModelPrefetchCacheReport,
1811
+ writePrivateJsonAtomic
1759
1812
  };
1760
1813
  //# sourceMappingURL=local-runtime.js.map