@tuned-tensor/cli 0.13.1-beta.0 → 0.13.1-beta.2

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.
@@ -2,6 +2,7 @@
2
2
  import {
3
3
  DEFAULT_LOCAL_SPEC_PATH,
4
4
  assertArtifactManifest,
5
+ assertFoundationSpecReady,
5
6
  assertLocalRunInputReady,
6
7
  assertUsableModelArtifact,
7
8
  baseModelRevisionSchema,
@@ -29,16 +30,21 @@ import {
29
30
  fineTuneRunRequestSchema,
30
31
  fingerprintLocalBaseModel,
31
32
  forwardStreamLines,
33
+ foundationHyperparametersSchema,
34
+ foundationPlaceholderIssues,
32
35
  generatedPlaceholderIssues,
33
36
  initLocalRunnerConfigFile,
34
37
  initLocalSpecFile,
38
+ isFoundationSpecFile,
35
39
  isTerminalRunState,
36
40
  jsonFieldMetricsSchema,
37
41
  loadJsonFile,
38
42
  loadLocalRunInput,
39
43
  loadLocalRunnerConfig,
40
44
  loadRunRequest,
45
+ localAdapterSpecFileSchema,
41
46
  localBehaviorSpecFileSchema,
47
+ localFoundationSpecFileSchema,
42
48
  localRunnerConfigSchema,
43
49
  localRuntimePackageRoot,
44
50
  localStorePaths,
@@ -66,7 +72,7 @@ import {
66
72
  withHuggingFaceCacheEnvironment,
67
73
  withOfflineHuggingFaceCacheEnvironment,
68
74
  writeJsonAtomic
69
- } from "./chunk-YJYCGSHJ.js";
75
+ } from "./chunk-2P2RL23O.js";
70
76
 
71
77
  // src/local-runtime/index.ts
72
78
  import { readFileSync, realpathSync } from "fs";
@@ -295,6 +301,14 @@ function buildDoctorPythonPlans(config) {
295
301
  })
296
302
  ];
297
303
  }
304
+ function foundationPlaceholderCheck(spec) {
305
+ const issues = foundationPlaceholderIssues(spec);
306
+ return {
307
+ name: "spec-content",
308
+ ok: issues.length === 0,
309
+ message: issues.length > 0 ? "The spec still contains generated placeholder content; edit it before training." : `${spec.examples.length} spec example(s); foundation engine`
310
+ };
311
+ }
298
312
  function placeholderSpecCheck(request) {
299
313
  const placeholder = request.spec_snapshot.examples.some(
300
314
  (example) => /replace this with/i.test(example.input) || /replace this with/i.test(example.output)
@@ -324,7 +338,7 @@ async function localBaseModelCheck(path, expectedModelId, modelCache) {
324
338
  };
325
339
  }
326
340
  }
327
- async function runDoctor(config, request) {
341
+ async function runDoctor(config, request, foundationSpec) {
328
342
  const checks = [];
329
343
  const nodeVersion = process.versions.node;
330
344
  const nodeMajor = Number(nodeVersion.split(".")[0]);
@@ -342,7 +356,9 @@ async function runDoctor(config, request) {
342
356
  config.paths.modelCache
343
357
  ));
344
358
  }
345
- if (request) {
359
+ if (foundationSpec) {
360
+ checks.push(foundationPlaceholderCheck(foundationSpec));
361
+ } else if (request) {
346
362
  checks.push(placeholderSpecCheck(request));
347
363
  resolveTrainingModel(request.spec_snapshot.base_model);
348
364
  }
@@ -749,6 +765,7 @@ var COMMAND_DEFINITIONS = {
749
765
  description: "Create a local tunedtensor.json behavior spec.",
750
766
  options: [
751
767
  { name: "--name", value: "name", description: "Behavior spec name" },
768
+ { name: "--engine", value: "engine", description: "adapter (default) or foundation" },
752
769
  { name: "--model", value: "model", description: "Base model ID" },
753
770
  { name: "--output", value: "path", description: "Output spec path" },
754
771
  { name: "--profile", value: "profile", description: "Write a durable runner config (spark)" },
@@ -1006,6 +1023,11 @@ async function loadCliBehaviorSpec(inputPath, runId) {
1006
1023
  const input = await loadLocalRunInput(inputPath, {
1007
1024
  ...runId ? { runId } : {}
1008
1025
  });
1026
+ if (input.kind === "foundation-spec") {
1027
+ throw new Error(
1028
+ `This spec uses engine "foundation". Use \`tt pipeline run --spec ${input.path}\` instead of adapter commands like \`tt run\`.`
1029
+ );
1030
+ }
1009
1031
  if (input.kind !== "spec") {
1010
1032
  throw new Error(`TT Local CLI expects a tunedtensor.json behavior spec, not a full run request: ${input.path}`);
1011
1033
  }
@@ -1173,6 +1195,9 @@ async function modelSystemPrompt(args) {
1173
1195
  if (!local.success) {
1174
1196
  throw new Error(`--spec must contain a tunedtensor.json behavior spec: ${resolve3(specPath)}`);
1175
1197
  }
1198
+ if (isFoundationSpecFile(local.data)) {
1199
+ throw new Error("Foundation specs have no Hugging Face base model. `tt serve` cannot host them yet.");
1200
+ }
1176
1201
  spec = local.data;
1177
1202
  } else {
1178
1203
  const runRequestPath = join3(args.store.paths.runsDir, args.model.run_id, "request.json");
@@ -1275,6 +1300,9 @@ async function serveBaseModelFromCli(args) {
1275
1300
  const spec = specPath ? localBehaviorSpecFileSchema.parse(
1276
1301
  JSON.parse(await readFile2(specPath, "utf8"))
1277
1302
  ) : void 0;
1303
+ if (spec && isFoundationSpecFile(spec)) {
1304
+ throw new Error("Foundation specs have no Hugging Face base model. `tt serve` cannot host them yet.");
1305
+ }
1278
1306
  let baseModel = spec?.base_model;
1279
1307
  if (!baseModel) {
1280
1308
  const store = createLocalStore(args.config.storeRoot);
@@ -1362,8 +1390,19 @@ async function main(argv) {
1362
1390
  const inputPath = resolve3(cli.positionals[0] ?? DEFAULT_LOCAL_SPEC_PATH);
1363
1391
  const configSelection = await configSelectionFromArgv(argv, inputPath);
1364
1392
  const hasDefaultSpec = cli.positionals[0] ? true : Boolean((await stat(inputPath).catch(() => null))?.isFile());
1365
- const request = hasDefaultSpec ? (await loadCliBehaviorSpec(inputPath)).request : void 0;
1366
- const checks = await runDoctor(configSelection.config, request);
1393
+ let request;
1394
+ let foundationSpec;
1395
+ if (hasDefaultSpec) {
1396
+ const input = await loadLocalRunInput(inputPath);
1397
+ if (input.kind === "foundation-spec") {
1398
+ foundationSpec = input.spec;
1399
+ } else if (input.kind === "spec") {
1400
+ request = input.request;
1401
+ } else {
1402
+ throw new Error(`TT Local CLI expects a tunedtensor.json behavior spec, not a full run request: ${input.path}`);
1403
+ }
1404
+ }
1405
+ const checks = await runDoctor(configSelection.config, request, foundationSpec);
1367
1406
  const ok = checks.every((check) => check.ok);
1368
1407
  printJson({
1369
1408
  ok,
@@ -1379,10 +1418,18 @@ async function main(argv) {
1379
1418
  if (profile !== void 0 && profile !== "spark") {
1380
1419
  throw new Error(`--profile must be spark, got: ${profile}`);
1381
1420
  }
1421
+ const engine = readOption(argv, "--engine") ?? "adapter";
1422
+ if (engine !== "adapter" && engine !== "foundation") {
1423
+ throw new Error(`--engine must be adapter or foundation, got: ${engine}`);
1424
+ }
1425
+ if (engine === "foundation" && readOption(argv, "--model")) {
1426
+ throw new Error("Foundation specs do not take --model; they train a tokenizer and GPT from scratch.");
1427
+ }
1382
1428
  const spec = await initLocalSpecFile({
1383
1429
  outputPath,
1384
- name: readOption(argv, "--name") ?? "Local Tuned Tensor Spec",
1385
- baseModel: readOption(argv, "--model") ?? "Qwen/Qwen3.5-2B",
1430
+ name: readOption(argv, "--name") ?? (engine === "foundation" ? "Foundation chat model" : "Local Tuned Tensor Spec"),
1431
+ engine,
1432
+ baseModel: engine === "foundation" ? void 0 : readOption(argv, "--model") ?? "Qwen/Qwen3.5-2B",
1386
1433
  force: hasFlag(argv, "--force")
1387
1434
  });
1388
1435
  const configPath = profile ? resolve3(readOption(argv, "--config") ?? resolve3(dirname(outputPath), "local-runner.json")) : await selectedConfigPath(argv, outputPath);
@@ -1400,14 +1447,29 @@ async function main(argv) {
1400
1447
  path: outputPath,
1401
1448
  id: spec.id,
1402
1449
  name: spec.name,
1403
- base_model: spec.base_model,
1450
+ engine: spec.engine ?? "adapter",
1451
+ base_model: isFoundationSpecFile(spec) ? null : spec.base_model,
1404
1452
  config_path: configPath ?? null
1405
1453
  });
1406
1454
  return;
1407
1455
  }
1408
1456
  if (command === "validate") {
1409
1457
  const inputPath = resolve3(cli.positionals[0] ?? DEFAULT_LOCAL_SPEC_PATH);
1410
- const input = await loadCliBehaviorSpec(inputPath);
1458
+ const loaded = await loadLocalRunInput(inputPath);
1459
+ if (loaded.kind === "foundation-spec") {
1460
+ assertFoundationSpecReady(loaded.spec);
1461
+ printJson({
1462
+ ok: true,
1463
+ input_path: loaded.path,
1464
+ engine: "foundation",
1465
+ pipeline: "tt pipeline run --spec"
1466
+ });
1467
+ return;
1468
+ }
1469
+ if (loaded.kind !== "spec") {
1470
+ throw new Error(`TT Local CLI expects a tunedtensor.json behavior spec, not a full run request: ${loaded.path}`);
1471
+ }
1472
+ const input = loaded;
1411
1473
  assertLocalRunInputReady(input.request);
1412
1474
  const configSelection = await configSelectionFromArgv(argv, inputPath);
1413
1475
  const validated = await validateLocalFineTuneInput({
@@ -1629,6 +1691,7 @@ export {
1629
1691
  DEFAULT_LOCAL_SPEC_PATH,
1630
1692
  TT_LOCAL_VERSION,
1631
1693
  activateModel,
1694
+ assertFoundationSpecReady,
1632
1695
  assertLocalRunInputReady,
1633
1696
  baseModelRevisionSchema,
1634
1697
  behaviorSpecExampleSchema,
@@ -1656,18 +1719,23 @@ export {
1656
1719
  fineTuneRunRequestSchema,
1657
1720
  fingerprintLocalBaseModel,
1658
1721
  forwardStreamLines,
1722
+ foundationHyperparametersSchema,
1723
+ foundationPlaceholderIssues,
1659
1724
  generatedPlaceholderIssues,
1660
1725
  getActiveModel,
1661
1726
  getLocalRunnerInfo,
1662
1727
  initLocalRunnerConfigFile,
1663
1728
  initLocalSpecFile,
1729
+ isFoundationSpecFile,
1664
1730
  isTerminalRunState,
1665
1731
  jsonFieldMetricsSchema,
1666
1732
  loadJsonFile,
1667
1733
  loadLocalRunInput,
1668
1734
  loadLocalRunnerConfig,
1669
1735
  loadRunRequest,
1736
+ localAdapterSpecFileSchema,
1670
1737
  localBehaviorSpecFileSchema,
1738
+ localFoundationSpecFileSchema,
1671
1739
  localRunnerConfigSchema,
1672
1740
  localStorePaths,
1673
1741
  normalizeChatJsonlForRelocation,