@tuned-tensor/cli 0.21.0 → 0.22.1

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.
@@ -1,11 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  DEFAULT_LOCAL_SPEC_PATH,
4
+ DatasetNotDownloadedError,
4
5
  assertArtifactManifest,
5
6
  assertFoundationSpecReady,
6
7
  assertLocalRunInputReady,
7
8
  assertUsableModelArtifact,
8
9
  assessHardware,
10
+ auditRun,
9
11
  baseModelRevisionSchema,
10
12
  behaviorSpecExampleSchema,
11
13
  behaviorSpecSchema,
@@ -18,14 +20,19 @@ import {
18
20
  comparisonReportSchema,
19
21
  compileSpecToJsonl,
20
22
  createLocalStore,
23
+ createRunConsoleReporter,
24
+ datasetColumnsSchema,
21
25
  datasetFormatSchema,
26
+ datasetInputIdentity,
22
27
  datasetPrebuiltSchema,
28
+ datasetSourceSchema,
23
29
  decisionHyperparametersSchema,
24
30
  decisionLabels,
25
31
  decisionPlaceholderIssues,
26
32
  decisionQuestionSchema,
27
33
  defaultBaseModelRevision,
28
34
  defaultLocalHome,
35
+ ensureDatasetCached,
29
36
  evalExampleResultSchema,
30
37
  evalReportSchema,
31
38
  evalSplitSchema,
@@ -42,10 +49,14 @@ import {
42
49
  foundationPlaceholderIssues,
43
50
  generatedPlaceholderIssues,
44
51
  hardenExistingLocalStore,
52
+ huggingFaceDataset,
53
+ huggingFaceDatasetSourceSchema,
54
+ huggingFaceRepoIdSchema,
45
55
  initLocalRunnerConfigFile,
46
56
  initLocalSpecFile,
47
57
  isDecisionSpecFile,
48
58
  isFoundationSpecFile,
59
+ isRepoRelativePath,
49
60
  isTerminalRunState,
50
61
  jsonFieldMetricsSchema,
51
62
  loadJsonFile,
@@ -66,6 +77,7 @@ import {
66
77
  parseLocalRunnerConfig,
67
78
  pipelineForRunInput,
68
79
  prefetchBaseModel,
80
+ prefetchHuggingFaceDataset,
69
81
  projectRuntimeSchema,
70
82
  pythonEnvironmentPath,
71
83
  reportInBackground,
@@ -77,8 +89,10 @@ import {
77
89
  runGpuProcess,
78
90
  runLocalFineTune,
79
91
  runLocalPipeline,
92
+ runProvenanceSchema,
80
93
  runReportSchema,
81
94
  runRequestFromLocalSpec,
95
+ safeName,
82
96
  sanitizeLogLine,
83
97
  specHash,
84
98
  specSnapshotSchema,
@@ -94,13 +108,13 @@ import {
94
108
  withHuggingFaceCacheEnvironment,
95
109
  withOfflineHuggingFaceCacheEnvironment,
96
110
  writePrivateJsonAtomic
97
- } from "./chunk-PVLX7LJI.js";
111
+ } from "./chunk-RPWOCVIL.js";
98
112
 
99
113
  // src/local-runtime/index.ts
100
114
  import { readFileSync as readFileSync3, realpathSync } from "fs";
101
115
  import { createHash as createHash2 } from "crypto";
102
116
  import { readFile as readFile2, stat } from "fs/promises";
103
- import { basename, dirname, join as join5, resolve as resolve3 } from "path";
117
+ import { basename, dirname, join as join5, relative, resolve as resolve3 } from "path";
104
118
  import { cwd } from "process";
105
119
  import { fileURLToPath as fileURLToPath2 } from "url";
106
120
 
@@ -932,8 +946,9 @@ Commands:
932
946
  validate [tunedtensor.json] [--config local-runner.json]
933
947
  run [tunedtensor.json] [--config local-runner.json] [--dry-run] [--verbose] [--quiet]
934
948
  serve <model-id|active|base|foundation> [--config local-runner.json] [--host 127.0.0.1] [--port 8000]
935
- runs list|get|events|report|compare [args] [--config local-runner.json]
949
+ runs list|get|events|report|compare|audit [args] [--config local-runner.json]
936
950
  models list|get|verify|prefetch|verify-base|active|activate|rollback|serve [args] [--config local-runner.json]
951
+ datasets prefetch|verify [tunedtensor.json]
937
952
 
938
953
  Global options:
939
954
  -h, --help Show help
@@ -1037,6 +1052,7 @@ var COMMAND_GROUPS = {
1037
1052
  get: { usage: "tt runs get <run-id> [--config path]", description: "Get a local run.", options: [CONFIG_OPTION], minPositionals: 1, maxPositionals: 1, missingPositionalsMessage: "runs get requires <run-id>" },
1038
1053
  events: { usage: "tt runs events <run-id> [--config path]", description: "List run events.", options: [CONFIG_OPTION], minPositionals: 1, maxPositionals: 1, missingPositionalsMessage: "runs events requires <run-id>" },
1039
1054
  report: { usage: "tt runs report <run-id> [--config path]", description: "Show the baseline-vs-tuned report, including deltas and regressions.", options: [CONFIG_OPTION], minPositionals: 1, maxPositionals: 1, missingPositionalsMessage: "runs report requires <run-id>" },
1055
+ audit: { usage: "tt runs audit <run-id> [--config path]", description: "Verify the run's event chain and report digest, and show its timeline and provenance.", options: [CONFIG_OPTION], minPositionals: 1, maxPositionals: 1, missingPositionalsMessage: "runs audit requires <run-id>" },
1040
1056
  compare: { usage: "tt runs compare <run-id-a> <run-id-b> [--config path]", description: "Compare two run reports.", options: [CONFIG_OPTION], minPositionals: 2, maxPositionals: 2, missingPositionalsMessage: "runs compare requires <run-id-a> <run-id-b>" }
1041
1057
  }
1042
1058
  },
@@ -1095,6 +1111,24 @@ var COMMAND_GROUPS = {
1095
1111
  missingPositionalsMessage: "models serve requires <model-id>"
1096
1112
  }
1097
1113
  }
1114
+ },
1115
+ datasets: {
1116
+ description: "Download or verify the Hugging Face dataset a behavior spec trains on.",
1117
+ defaultSubcommand: "prefetch",
1118
+ subcommands: {
1119
+ prefetch: {
1120
+ usage: "tt datasets prefetch [tunedtensor.json] [options]",
1121
+ description: "Download dataset_prebuilt.huggingface files into the local Hugging Face cache. Resumes after interruption.",
1122
+ options: [CONFIG_OPTION, VERBOSE_OPTION, QUIET_OPTION],
1123
+ maxPositionals: 1
1124
+ },
1125
+ verify: {
1126
+ usage: "tt datasets verify [tunedtensor.json] [options]",
1127
+ description: "Verify the cached dataset files and checksums without network access.",
1128
+ options: [CONFIG_OPTION, QUIET_OPTION],
1129
+ maxPositionals: 1
1130
+ }
1131
+ }
1098
1132
  }
1099
1133
  };
1100
1134
  function hasHelpFlag(argv) {
@@ -1255,38 +1289,9 @@ async function loadCliBehaviorSpec(inputPath, runId) {
1255
1289
  function printJson(value) {
1256
1290
  console.log(JSON.stringify(value, null, 2));
1257
1291
  }
1258
- function shortValue(value) {
1259
- if (value === void 0 || value === null) return null;
1260
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
1261
- return String(value);
1262
- }
1263
- if (Array.isArray(value)) return `[${value.length} items]`;
1264
- return null;
1265
- }
1266
- function formatEvent(event) {
1267
- const detailText = Object.entries(event.details ?? {}).filter(([key]) => key !== "metrics").map(([key, value]) => {
1268
- const formatted = key === "command" && Array.isArray(value) ? value.join(" ") : shortValue(value);
1269
- return formatted ? `${key}=${formatted}` : null;
1270
- }).filter((value) => Boolean(value)).slice(0, 5).join(" ");
1271
- return sanitizeLogLine(`[tt] ${event.stage}: ${event.message}${detailText ? ` (${detailText})` : ""}`);
1272
- }
1273
1292
  function createConsoleReporter(options) {
1274
1293
  if (options.quiet) return void 0;
1275
- let lastLogLine = "";
1276
- return {
1277
- verbose: options.verbose,
1278
- onEvent(event) {
1279
- process.stderr.write(`${formatEvent(event)}
1280
- `);
1281
- },
1282
- onLog(log) {
1283
- const line = sanitizeLogLine(`[tt] ${log.stage}${log.stream ? ` ${log.stream}` : ""}: ${log.message}`);
1284
- if (line === lastLogLine) return;
1285
- lastLogLine = line;
1286
- process.stderr.write(`${line}
1287
- `);
1288
- }
1289
- };
1294
+ return createRunConsoleReporter({ verbose: options.verbose });
1290
1295
  }
1291
1296
  async function verifyStoredModel(model, config) {
1292
1297
  const manifestPath = join5(model.artifact_dir, "artifact-manifest.json");
@@ -1805,10 +1810,32 @@ ${validation.errors.join("\n")}`);
1805
1810
  const input = loaded;
1806
1811
  assertLocalRunInputReady(input.request);
1807
1812
  const configSelection = await configSelectionFromArgv(argv, inputPath);
1808
- const validated = await validateLocalFineTuneInput({
1809
- request: input.request,
1810
- config: configSelection.config
1811
- });
1813
+ const remoteDataset = huggingFaceDataset(input.request);
1814
+ let validated;
1815
+ try {
1816
+ validated = await validateLocalFineTuneInput({
1817
+ request: input.request,
1818
+ config: configSelection.config
1819
+ });
1820
+ } catch (error) {
1821
+ if (!(error instanceof DatasetNotDownloadedError) || !remoteDataset) throw error;
1822
+ const config2 = localRunnerConfigSchema.parse(configSelection.config);
1823
+ printJson({
1824
+ ok: true,
1825
+ input_path: input.path,
1826
+ config_path: configSelection.path ?? null,
1827
+ behavior_spec_id: input.request.behavior_spec_id,
1828
+ base_model: input.request.spec_snapshot.base_model,
1829
+ dataset_format: remoteDataset.format,
1830
+ dataset_status: "not_downloaded",
1831
+ dataset_huggingface: remoteDataset.huggingface,
1832
+ next_step: `tt datasets prefetch ${relative(cwd(), input.path) || input.path}`,
1833
+ artifact_root: config2.artifactRoot,
1834
+ store_root: config2.storeRoot,
1835
+ dry_run: config2.dryRun
1836
+ });
1837
+ return;
1838
+ }
1812
1839
  const request = validated.request;
1813
1840
  const config = validated.config;
1814
1841
  printJson({
@@ -1818,6 +1845,7 @@ ${validation.errors.join("\n")}`);
1818
1845
  behavior_spec_id: request.behavior_spec_id,
1819
1846
  base_model: request.spec_snapshot.base_model,
1820
1847
  dataset_format: request.dataset_prebuilt?.format ?? null,
1848
+ ...request.dataset_source ? { dataset_status: "cached", dataset_source: request.dataset_source } : {},
1821
1849
  artifact_root: config.artifactRoot,
1822
1850
  store_root: config.storeRoot,
1823
1851
  dry_run: config.dryRun
@@ -1834,15 +1862,16 @@ ${validation.errors.join("\n")}`);
1834
1862
  dryRun: hasFlag(argv, "--dry-run") ? true : configInput.dryRun
1835
1863
  });
1836
1864
  assertLocalRunInputReady(input.request);
1837
- const validated = await validateLocalFineTuneInput({
1838
- request: input.request,
1839
- config
1840
- });
1841
- let request = validated.request;
1842
1865
  const reporter = createConsoleReporter({
1843
1866
  verbose: hasFlag(argv, "--verbose"),
1844
1867
  quiet: hasFlag(argv, "--quiet")
1845
1868
  });
1869
+ const ensured = await ensureDatasetCached({ request: input.request, config, reporter });
1870
+ const validated = await validateLocalFineTuneInput({
1871
+ request: ensured.request,
1872
+ config
1873
+ });
1874
+ let request = validated.request;
1846
1875
  if (!config.dryRun && !config.paths.baseModel && !request.hyperparameters.base_model_revision) {
1847
1876
  const prefetch = await prefetchBaseModel({
1848
1877
  request,
@@ -1860,12 +1889,13 @@ ${validation.errors.join("\n")}`);
1860
1889
  }
1861
1890
  });
1862
1891
  }
1892
+ const specFile = /^\..+\.tt-local-/.test(basename(input.path)) ? void 0 : { path: input.path, sha256: specHash(await readFile2(input.path, "utf8")) };
1863
1893
  if (input.spec.pipeline) {
1864
- const result2 = await runLocalPipeline({ request, config, reporter, pipeline: pipelineForRunInput(input), projectSpec: input.spec });
1894
+ const result2 = await runLocalPipeline({ request, config, reporter, pipeline: pipelineForRunInput(input), projectSpec: input.spec, specFile });
1865
1895
  printJson(result2);
1866
1896
  return;
1867
1897
  }
1868
- const result = await runLocalFineTune({ request, config, reporter });
1898
+ const result = await runLocalFineTune({ request, config, reporter, specFile });
1869
1899
  printJson({
1870
1900
  status: result.report.status,
1871
1901
  run_id: result.report.run_id,
@@ -1913,6 +1943,14 @@ ${validation.errors.join("\n")}`);
1913
1943
  if (!id) throw new Error("runs report requires <run-id>");
1914
1944
  return printJson(await store.getRunReport(id));
1915
1945
  }
1946
+ if (subcommand === "audit") {
1947
+ const id = cli.positionals[0];
1948
+ if (!id) throw new Error("runs audit requires <run-id>");
1949
+ const audit = await auditRun(store, id);
1950
+ printJson(audit);
1951
+ if (audit.verdict === "tampered") process.exitCode = 2;
1952
+ return;
1953
+ }
1916
1954
  if (subcommand === "compare") {
1917
1955
  const idA = cli.positionals[0];
1918
1956
  const idB = cli.positionals[1];
@@ -1925,6 +1963,23 @@ ${validation.errors.join("\n")}`);
1925
1963
  }
1926
1964
  throw new Error(`Unknown runs command: ${subcommand}`);
1927
1965
  }
1966
+ if (command === "datasets") {
1967
+ const subcommand = cli.subcommand;
1968
+ const inputPath = resolve3(cli.positionals[0] ?? DEFAULT_LOCAL_SPEC_PATH);
1969
+ const config = await configFromArgv(argv, inputPath);
1970
+ const input = await loadCliBehaviorSpec(inputPath);
1971
+ if (subcommand !== "prefetch" && subcommand !== "verify") throw new Error(`Unknown datasets command: ${subcommand}`);
1972
+ const report = await prefetchHuggingFaceDataset({
1973
+ request: input.request,
1974
+ config,
1975
+ localOnly: subcommand === "verify",
1976
+ reporter: createConsoleReporter({
1977
+ verbose: hasFlag(argv, "--verbose"),
1978
+ quiet: hasFlag(argv, "--quiet")
1979
+ })
1980
+ });
1981
+ return printJson({ ...report, input_path: input.path });
1982
+ }
1928
1983
  if (command === "models") {
1929
1984
  const subcommand = cli.subcommand;
1930
1985
  const modelInputPath = subcommand === "prefetch" || subcommand === "verify-base" ? resolve3(cli.positionals[0] ?? DEFAULT_LOCAL_SPEC_PATH) : void 0;
@@ -2040,8 +2095,11 @@ export {
2040
2095
  comparisonReportSchema,
2041
2096
  compileSpecToJsonl,
2042
2097
  createLocalStore,
2098
+ datasetColumnsSchema,
2043
2099
  datasetFormatSchema,
2100
+ datasetInputIdentity,
2044
2101
  datasetPrebuiltSchema,
2102
+ datasetSourceSchema,
2045
2103
  decisionHyperparametersSchema,
2046
2104
  decisionLabels,
2047
2105
  decisionPlaceholderIssues,
@@ -2065,10 +2123,13 @@ export {
2065
2123
  getActiveModel,
2066
2124
  getLocalRunnerInfo,
2067
2125
  hardenExistingLocalStore,
2126
+ huggingFaceDatasetSourceSchema,
2127
+ huggingFaceRepoIdSchema,
2068
2128
  initLocalRunnerConfigFile,
2069
2129
  initLocalSpecFile,
2070
2130
  isDecisionSpecFile,
2071
2131
  isFoundationSpecFile,
2132
+ isRepoRelativePath,
2072
2133
  isTerminalRunState,
2073
2134
  jsonFieldMetricsSchema,
2074
2135
  loadJsonFile,
@@ -2092,8 +2153,10 @@ export {
2092
2153
  rollbackActiveModel,
2093
2154
  runLocalFineTune,
2094
2155
  runLocalPipeline,
2156
+ runProvenanceSchema,
2095
2157
  runReportSchema,
2096
2158
  runRequestFromLocalSpec,
2159
+ safeName,
2097
2160
  sanitizeLogLine,
2098
2161
  serveLocalModel,
2099
2162
  specHash,