@tuned-tensor/cli 0.15.1 → 0.17.0

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.
@@ -14,6 +14,7 @@ import {
14
14
  buildModelPrefetchPayload,
15
15
  buildSystemMessage,
16
16
  canonicalLocalPipeline,
17
+ checkAwsGpu,
17
18
  comparisonReportSchema,
18
19
  compileSpecToJsonl,
19
20
  createLocalStore,
@@ -64,14 +65,17 @@ import {
64
65
  resolveModelLoader,
65
66
  resolveRequestedBaseModelRevision,
66
67
  resolveTrainingModel,
68
+ runGpuProcess,
67
69
  runLocalFineTune,
68
70
  runLocalPipeline,
69
71
  runReportSchema,
70
72
  runRequestFromLocalSpec,
71
73
  sanitizeLogLine,
74
+ specHash,
72
75
  specSnapshotSchema,
73
76
  tokenF1,
74
77
  trainingReportSchema,
78
+ validateBehaviorSpec,
75
79
  validateLocalFineTuneInput,
76
80
  validateLocalPipeline,
77
81
  verifyLocalBaseModel,
@@ -81,13 +85,13 @@ import {
81
85
  withHuggingFaceCacheEnvironment,
82
86
  withOfflineHuggingFaceCacheEnvironment,
83
87
  writePrivateJsonAtomic
84
- } from "./chunk-VVKC563R.js";
88
+ } from "./chunk-KRKISPHG.js";
85
89
 
86
90
  // src/local-runtime/index.ts
87
- import { readFileSync as readFileSync2, realpathSync } from "fs";
91
+ import { readFileSync as readFileSync3, realpathSync } from "fs";
88
92
  import { createHash as createHash2 } from "crypto";
89
93
  import { readFile as readFile2, stat } from "fs/promises";
90
- import { basename, dirname, join as join4, resolve as resolve3 } from "path";
94
+ import { basename, dirname, join as join5, resolve as resolve3 } from "path";
91
95
  import { cwd } from "process";
92
96
  import { fileURLToPath as fileURLToPath2 } from "url";
93
97
 
@@ -290,6 +294,22 @@ function foundationPythonProbePlan(requireBf16) {
290
294
  env: withFoundationPythonEnvironment(process.env)
291
295
  };
292
296
  }
297
+ function localPreparationProbePlan(foundation) {
298
+ const source = [
299
+ "import json",
300
+ foundation ? "import numpy, safetensors, tokenizers, torch" : "import torch, transformers, peft, huggingface_hub",
301
+ "assert torch.ones(1, device='cpu').item() == 1",
302
+ "print(json.dumps({'python_ok': True, 'device': 'cpu', 'purpose': 'local preparation and CPU work'}))"
303
+ ].join("; ");
304
+ const entrypoint = foundation ? buildFoundationPythonCommand("-c", [source]) : buildBundledPythonCommand("-c", [source]);
305
+ const env = minimalMachineLearningEnvironment(process.env);
306
+ return {
307
+ name: "python-runtime",
308
+ command: entrypoint.command,
309
+ args: entrypoint.commandArgs,
310
+ env: foundation ? withFoundationPythonEnvironment(env) : withBundledPythonEnvironment(env)
311
+ };
312
+ }
293
313
  function pythonProbeSource(device) {
294
314
  return [
295
315
  "import json",
@@ -430,7 +450,7 @@ async function runDoctor(config, request, foundationSpec) {
430
450
  checks.push(placeholderSpecCheck(request));
431
451
  resolveTrainingModel(request.spec_snapshot.base_model);
432
452
  }
433
- const pythonPlans = foundationSpec && !config.dryRun ? [foundationPythonProbePlan(foundationSpec.foundation.bf16 !== false)] : buildDoctorPythonPlans(config);
453
+ const pythonPlans = config.dryRun ? [] : config.gpu ? [localPreparationProbePlan(Boolean(foundationSpec))] : foundationSpec ? [foundationPythonProbePlan(foundationSpec.foundation.bf16 !== false)] : buildDoctorPythonPlans(config);
434
454
  if (pythonPlans.length > 0) {
435
455
  const uvVersion = await runCommand("uv", ["--version"]);
436
456
  checks.push({
@@ -465,7 +485,28 @@ async function runDoctor(config, request, foundationSpec) {
465
485
  });
466
486
  }
467
487
  const device = config.evaluation.inference.device;
468
- if (!config.dryRun) {
488
+ if (config.gpu && !config.dryRun) {
489
+ try {
490
+ await checkAwsGpu(config.gpu);
491
+ const plans = foundationSpec ? [foundationPythonProbePlan(foundationSpec.foundation.bf16 !== false)] : buildDoctorPythonPlans(config);
492
+ for (const plan of plans) {
493
+ const result = await runGpuProcess({
494
+ gpu: config.gpu,
495
+ runtime: foundationSpec ? "foundation" : "adapter",
496
+ files: [],
497
+ command: plan.command,
498
+ commandArgs: plan.args,
499
+ env: plan.env,
500
+ stage: "gpu_check",
501
+ timeoutMs: 18e5
502
+ });
503
+ if (result.exitCode !== 0) throw new Error(`Remote Python/CUDA check failed: ${result.stderr}`);
504
+ }
505
+ checks.push({ name: "aws-gpu", ok: true, message: `GPU execution on ${config.gpu.instanceId}; orchestration stays local.` });
506
+ } catch (error) {
507
+ checks.push({ name: "aws-gpu", ok: false, message: error instanceof Error ? error.message : String(error) });
508
+ }
509
+ } else if (!config.dryRun) {
469
510
  const queried = await runCommand("nvidia-smi", [
470
511
  "--query-gpu=name,driver_version",
471
512
  "--format=csv,noheader"
@@ -503,8 +544,9 @@ async function runDoctor(config, request, foundationSpec) {
503
544
  }
504
545
 
505
546
  // src/local-runtime/model-server.ts
547
+ import { readFileSync as readFileSync2, statSync } from "fs";
506
548
  import { spawn as spawn2 } from "child_process";
507
- import { resolve as resolve2 } from "path";
549
+ import { resolve as resolve2, join as join3 } from "path";
508
550
  import { fileURLToPath } from "url";
509
551
 
510
552
  // src/local-runtime/serving-runtime.ts
@@ -562,7 +604,16 @@ function buildModelServerLaunch(args) {
562
604
  const options = args.options ?? {};
563
605
  const device = options.device ?? args.config.evaluation.inference.device;
564
606
  if (device !== "cuda") throw new Error("The pinned vLLM serving runtime requires CUDA; CPU serving is not supported.");
565
- const contextLength = boundedNumber("contextLength", options.contextLength ?? 16384, 512, 131072, true);
607
+ const contextLength = boundedNumber(
608
+ "contextLength",
609
+ options.contextLength ?? args.foundation?.contextLength ?? 16384,
610
+ args.foundation ? 1 : 512,
611
+ 131072,
612
+ true
613
+ );
614
+ if (args.foundation && contextLength > args.foundation.contextLength) {
615
+ throw new Error("Context length exceeds the foundation checkpoint sequence_length.");
616
+ }
566
617
  const gpuMemoryUtilization = boundedNumber("gpuMemoryUtilization", options.gpuMemoryUtilization ?? 0.8, 0.05, 0.95);
567
618
  const host = options.host ?? "127.0.0.1";
568
619
  const remote = !isLoopbackHost(host);
@@ -575,7 +626,7 @@ function buildModelServerLaunch(args) {
575
626
  throw new Error("Non-loopback serving requires --api-key-env with a populated environment variable.");
576
627
  }
577
628
  const port = boundedNumber("port", options.port ?? 8e3, 1, 65535, true);
578
- const maxTokens = boundedNumber("maxTokens", options.maxTokens ?? 512, 1, 8192, true);
629
+ const maxTokens = boundedNumber("maxTokens", options.maxTokens ?? Math.min(512, contextLength), 1, 8192, true);
579
630
  const temperature = boundedNumber("temperature", options.temperature ?? 0, 0, 5);
580
631
  const topP = boundedNumber("topP", options.topP ?? 1, 0, 1);
581
632
  const maxConcurrentRequests = boundedNumber(
@@ -587,14 +638,14 @@ function buildModelServerLaunch(args) {
587
638
  );
588
639
  const artifactPath = args.artifactUri ? localArtifactPath(args.artifactUri) : void 0;
589
640
  const recordedBaseModelPath = options.baseModelArtifactUri ? localArtifactPath(options.baseModelArtifactUri) : void 0;
590
- const configuredBaseModelPath = args.config.paths.baseModel ? resolve2(args.config.paths.baseModel) : void 0;
641
+ const configuredBaseModelPath = !args.foundation && args.config.paths.baseModel ? resolve2(args.config.paths.baseModel) : void 0;
591
642
  if (recordedBaseModelPath && configuredBaseModelPath && resolve2(recordedBaseModelPath) !== configuredBaseModelPath) {
592
643
  throw new Error(
593
644
  `Configured paths.baseModel ${configuredBaseModelPath} does not match the base model recorded for this artifact: ` + recordedBaseModelPath
594
645
  );
595
646
  }
596
647
  const localBaseModelPath = recordedBaseModelPath ?? configuredBaseModelPath;
597
- const requestedBaseModelRevision = resolveRequestedBaseModelRevision(
648
+ const requestedBaseModelRevision = args.foundation ? void 0 : resolveRequestedBaseModelRevision(
598
649
  args.baseModel,
599
650
  options.baseModelRevision
600
651
  );
@@ -610,7 +661,11 @@ function buildModelServerLaunch(args) {
610
661
  TT_MODEL_NAME: args.modelName,
611
662
  TT_CONTEXT_LENGTH: String(contextLength),
612
663
  TT_GPU_MEMORY_UTILIZATION: String(gpuMemoryUtilization),
613
- TT_MODEL_LOADER: resolveModelLoader(args.baseModel),
664
+ TT_MODEL_LOADER: args.foundation ? "foundation" : resolveModelLoader(args.baseModel),
665
+ ...args.foundation ? {
666
+ TT_FOUNDATION_CHECKPOINT: args.foundation.checkpoint,
667
+ TT_FOUNDATION_TOKENIZER: args.foundation.tokenizer
668
+ } : {},
614
669
  TT_HOST: host,
615
670
  TT_PORT: String(port),
616
671
  TT_DEVICE: device,
@@ -710,16 +765,32 @@ async function serveLocalModel(launch) {
710
765
  });
711
766
  });
712
767
  }
768
+ function buildFoundationModelServerLaunch(args) {
769
+ const checkpoint = resolve2(args.checkpoint);
770
+ const tokenizer = resolve2(args.tokenizer);
771
+ for (const path of [join3(checkpoint, "model.safetensors"), tokenizer]) {
772
+ if (!statSync(path).isFile()) throw new Error(`Expected foundation artifact file: ${path}`);
773
+ }
774
+ const metadata = JSON.parse(readFileSync2(join3(checkpoint, "config.json"), "utf8"));
775
+ const contextLength = boundedNumber("sequence_length", metadata.sequence_length, 1, 131072, true);
776
+ return buildModelServerLaunch({
777
+ modelName: "foundation",
778
+ baseModel: "foundation",
779
+ config: args.config,
780
+ options: args.options,
781
+ foundation: { checkpoint, tokenizer, contextLength }
782
+ });
783
+ }
713
784
 
714
785
  // src/local-runtime/active-model.ts
715
786
  import { randomUUID } from "crypto";
716
787
  import { appendFile, chmod, readFile, rename, writeFile as writeFile2 } from "fs/promises";
717
- import { join as join3 } from "path";
788
+ import { join as join4 } from "path";
718
789
  function pointerPath(store) {
719
- return join3(store.root, "active-model.json");
790
+ return join4(store.root, "active-model.json");
720
791
  }
721
792
  function historyPath(store) {
722
- return join3(store.root, "activation-history.jsonl");
793
+ return join4(store.root, "activation-history.jsonl");
723
794
  }
724
795
  async function readPointer(store) {
725
796
  if (!await hardenExistingLocalStore(store.root)) return null;
@@ -759,7 +830,7 @@ async function assertModelCanActivate(store, modelId) {
759
830
  throw new Error(`Model ${model.id} belongs to run ${run.id}, which is not completed.`);
760
831
  }
761
832
  const report = runReportSchema.parse(
762
- JSON.parse(await readFile(join3(model.artifact_dir, "run-report.json"), "utf8"))
833
+ JSON.parse(await readFile(join4(model.artifact_dir, "run-report.json"), "utf8"))
763
834
  );
764
835
  if (!report.general_regression) {
765
836
  throw new Error(`Model ${model.id} has no general regression evaluation.`);
@@ -816,7 +887,7 @@ async function rollbackActiveModel(store) {
816
887
  function packageVersion() {
817
888
  try {
818
889
  const packageJson = JSON.parse(
819
- readFileSync2(resolve3(localRuntimePackageRoot(import.meta.url), "package.json"), "utf8")
890
+ readFileSync3(resolve3(localRuntimePackageRoot(import.meta.url), "package.json"), "utf8")
820
891
  );
821
892
  return typeof packageJson.version === "string" ? packageJson.version : "unknown";
822
893
  } catch {
@@ -851,7 +922,7 @@ Commands:
851
922
  hardware [--config local-runner.json] [--quick]
852
923
  validate [tunedtensor.json] [--config local-runner.json]
853
924
  run [tunedtensor.json] [--config local-runner.json] [--dry-run] [--verbose] [--quiet]
854
- serve <model-id|active|base> [--config local-runner.json] [--host 127.0.0.1] [--port 8000]
925
+ serve <model-id|active|base|foundation> [--config local-runner.json] [--host 127.0.0.1] [--port 8000]
855
926
  runs list|get|events|report|compare [args] [--config local-runner.json]
856
927
  models list|get|verify|prefetch|verify-base|active|activate|rollback|serve [args] [--config local-runner.json]
857
928
 
@@ -869,6 +940,8 @@ var VERBOSE_OPTION = { name: "--verbose", description: "Stream subprocess output
869
940
  var QUIET_OPTION = { name: "--quiet", description: "Suppress progress output on stderr" };
870
941
  var MODEL_SERVE_OPTIONS = [
871
942
  CONFIG_OPTION,
943
+ { name: "--checkpoint", value: "path", description: "Foundation model directory (target: foundation)" },
944
+ { name: "--tokenizer", value: "path", description: "Foundation tokenizer.json (target: foundation)" },
872
945
  { name: "--host", value: "host", description: "Bind host (localhost by default)" },
873
946
  { name: "--port", value: "port", description: "Bind port" },
874
947
  { name: "--device", value: "device", description: "cuda (pinned vLLM runtime)" },
@@ -876,7 +949,7 @@ var MODEL_SERVE_OPTIONS = [
876
949
  { name: "--temperature", value: "number", description: "Default sampling temperature" },
877
950
  { name: "--top-p", value: "number", description: "Default nucleus sampling threshold" },
878
951
  { name: "--max-concurrent-requests", value: "count", description: "Maximum sequences in an upstream generation batch" },
879
- { name: "--context-length", value: "count", description: "Total context token budget (default 16384)" },
952
+ { name: "--context-length", value: "count", description: "Total context token budget (foundation: checkpoint limit; otherwise 16384)" },
880
953
  { name: "--gpu-memory-utilization", value: "fraction", description: "vLLM GPU memory budget fraction (default 0.8)" },
881
954
  { name: "--spec", value: "path", description: "Behavior spec whose instructions are enforced" },
882
955
  { name: "--no-spec-prompt", description: "Do not enforce the stored behavior-spec prompt" },
@@ -939,8 +1012,8 @@ var COMMAND_DEFINITIONS = {
939
1012
  maxPositionals: 1
940
1013
  },
941
1014
  serve: {
942
- usage: "tt serve <model-id|active|base> [options]",
943
- description: "Serve a verified adapter, the active model, or the protected base.",
1015
+ usage: "tt serve <model-id|active|base|foundation> [options]",
1016
+ description: "Serve an adapter, pretrained base, or foundation checkpoint with vLLM.",
944
1017
  options: MODEL_SERVE_OPTIONS,
945
1018
  minPositionals: 1,
946
1019
  maxPositionals: 1,
@@ -1006,7 +1079,7 @@ var COMMAND_GROUPS = {
1006
1079
  maxPositionals: 0
1007
1080
  },
1008
1081
  serve: {
1009
- usage: "tt models serve <model-id|active|base> [options]",
1082
+ usage: "tt models serve <model-id|active|base|foundation> [options]",
1010
1083
  description: "Alias for `tt serve`.",
1011
1084
  options: MODEL_SERVE_OPTIONS,
1012
1085
  minPositionals: 1,
@@ -1146,7 +1219,7 @@ function readNumberOption(argv, name) {
1146
1219
  async function selectedConfigPath(argv, adjacentTo) {
1147
1220
  const explicitPath = readOption(argv, "--config");
1148
1221
  if (explicitPath) return resolve3(explicitPath);
1149
- const candidate = join4(adjacentTo ? dirname(resolve3(adjacentTo)) : cwd(), "local-runner.json");
1222
+ const candidate = join5(adjacentTo ? dirname(resolve3(adjacentTo)) : cwd(), "local-runner.json");
1150
1223
  const metadata = await stat(candidate).catch(() => null);
1151
1224
  return metadata?.isFile() ? candidate : void 0;
1152
1225
  }
@@ -1211,7 +1284,7 @@ function createConsoleReporter(options) {
1211
1284
  };
1212
1285
  }
1213
1286
  async function verifyStoredModel(model, config) {
1214
- const manifestPath = join4(model.artifact_dir, "artifact-manifest.json");
1287
+ const manifestPath = join5(model.artifact_dir, "artifact-manifest.json");
1215
1288
  const integrity = await assertArtifactManifest(manifestPath, {
1216
1289
  requiredPaths: ["stage-metadata.json", "training-report.json"],
1217
1290
  scopeToRequired: true,
@@ -1246,8 +1319,8 @@ async function verifyStoredModel(model, config) {
1246
1319
  };
1247
1320
  }
1248
1321
  async function verifyActivationEvidence(model) {
1249
- const generalBaseline = join4(model.artifact_dir, "general-baseline-eval.json");
1250
- const generalCandidate = join4(model.artifact_dir, "general-candidate-eval.json");
1322
+ const generalBaseline = join5(model.artifact_dir, "general-baseline-eval.json");
1323
+ const generalCandidate = join5(model.artifact_dir, "general-candidate-eval.json");
1251
1324
  const [hasBaseline, hasCandidate] = await Promise.all([
1252
1325
  stat(generalBaseline).then((metadata) => metadata.isFile(), () => false),
1253
1326
  stat(generalCandidate).then((metadata) => metadata.isFile(), () => false)
@@ -1257,7 +1330,7 @@ async function verifyActivationEvidence(model) {
1257
1330
  "This model cannot be activated because the run did not include a general-regression suite. Add evaluation.generalRegression to local-runner.json with a held-out dataset, re-run training, then activate. Until then, serve the adapter with `tt serve local-<run-id>`."
1258
1331
  );
1259
1332
  }
1260
- await assertArtifactManifest(join4(model.artifact_dir, "artifact-manifest.json"), {
1333
+ await assertArtifactManifest(join5(model.artifact_dir, "artifact-manifest.json"), {
1261
1334
  requiredPaths: [
1262
1335
  "run-report.json",
1263
1336
  "general-baseline-eval.json",
@@ -1283,7 +1356,7 @@ async function verifyModelArtifactPath(input, config) {
1283
1356
  if (!metadata) throw new Error(`Model not found and artifact path does not exist: ${input}`);
1284
1357
  let current = metadata.isDirectory() ? inputPath : dirname(inputPath);
1285
1358
  for (let depth = 0; depth < 8; depth += 1) {
1286
- const candidate = join4(current, "artifact-manifest.json");
1359
+ const candidate = join5(current, "artifact-manifest.json");
1287
1360
  const raw = await readFile2(candidate, "utf8").catch(() => null);
1288
1361
  if (raw) {
1289
1362
  const parsed = JSON.parse(raw);
@@ -1337,11 +1410,11 @@ async function modelSystemPrompt(args) {
1337
1410
  throw new Error(`--spec must contain a tunedtensor.json behavior spec: ${resolve3(specPath)}`);
1338
1411
  }
1339
1412
  if (isFoundationSpecFile(local.data)) {
1340
- throw new Error("Foundation specs have no Hugging Face base model. `tt serve` cannot host them yet.");
1413
+ throw new Error("Foundation specs have no Hugging Face base model. Use `tt serve foundation --checkpoint <model-dir> --tokenizer <tokenizer.json>`.");
1341
1414
  }
1342
1415
  spec = local.data;
1343
1416
  } else {
1344
- const runRequestPath = join4(args.store.paths.runsDir, args.model.run_id, "request.json");
1417
+ const runRequestPath = join5(args.store.paths.runsDir, args.model.run_id, "request.json");
1345
1418
  let persistedRequest = null;
1346
1419
  try {
1347
1420
  persistedRequest = fineTuneRunRequestSchema.parse(JSON.parse(await readFile2(runRequestPath, "utf8")));
@@ -1357,7 +1430,7 @@ async function modelSystemPrompt(args) {
1357
1430
  }
1358
1431
  const prompt = buildSystemMessage(spec);
1359
1432
  const metadata = JSON.parse(
1360
- await readFile2(join4(args.model.artifact_dir, "stage-metadata.json"), "utf8")
1433
+ await readFile2(join5(args.model.artifact_dir, "stage-metadata.json"), "utf8")
1361
1434
  );
1362
1435
  const promptHash = createHash2("sha256").update(prompt).digest("hex");
1363
1436
  if (metadata.system_prompt_sha256 !== promptHash) {
@@ -1400,7 +1473,7 @@ function printServeClientConfig(argv, launch) {
1400
1473
  supportsUsageInStreaming: true,
1401
1474
  maxTokensField: "max_tokens"
1402
1475
  },
1403
- models: [.../* @__PURE__ */ new Set([launch.modelName, `base:${launch.env.TT_BASE_MODEL}`])].map((id) => ({
1476
+ models: [...new Set(launch.env.TT_FOUNDATION_CHECKPOINT ? [launch.modelName] : [launch.modelName, `base:${launch.env.TT_BASE_MODEL}`])].map((id) => ({
1404
1477
  id,
1405
1478
  name: id,
1406
1479
  // This endpoint exports ordinary text/tool calls, not reasoning-effort controls.
@@ -1488,7 +1561,7 @@ async function serveBaseModelFromCli(args) {
1488
1561
  JSON.parse(await readFile2(specPath, "utf8"))
1489
1562
  ) : void 0;
1490
1563
  if (spec && isFoundationSpecFile(spec)) {
1491
- throw new Error("Foundation specs have no Hugging Face base model. `tt serve` cannot host them yet.");
1564
+ throw new Error("Foundation specs have no Hugging Face base model. Use `tt serve foundation --checkpoint <model-dir> --tokenizer <tokenizer.json>`.");
1492
1565
  }
1493
1566
  let baseModel = spec?.base_model;
1494
1567
  if (!baseModel) {
@@ -1525,6 +1598,45 @@ async function serveBaseModelFromCli(args) {
1525
1598
  await serveLocalModel(launch);
1526
1599
  }
1527
1600
  async function serveModelTargetFromCli(args) {
1601
+ if (args.target === "foundation") {
1602
+ const checkpoint = readOption(args.argv, "--checkpoint");
1603
+ const tokenizer = readOption(args.argv, "--tokenizer");
1604
+ if (!checkpoint || !tokenizer) {
1605
+ throw new Error("Foundation serving requires --checkpoint <model-dir> and --tokenizer <tokenizer.json>.");
1606
+ }
1607
+ const specPath = readOption(args.argv, "--spec");
1608
+ if (specPath && hasFlag(args.argv, "--no-spec-prompt")) {
1609
+ throw new Error("Use only one of --spec or --no-spec-prompt.");
1610
+ }
1611
+ const spec = specPath ? localBehaviorSpecFileSchema.parse(JSON.parse(await readFile2(resolve3(specPath), "utf8"))) : void 0;
1612
+ if (spec && !isFoundationSpecFile(spec)) throw new Error("Foundation serving requires a foundation spec.");
1613
+ const launch = buildFoundationModelServerLaunch({
1614
+ checkpoint,
1615
+ tokenizer,
1616
+ config: args.config,
1617
+ options: {
1618
+ ...serveOptionsFromArgv(args.argv),
1619
+ systemPrompt: spec ? buildSystemMessage(spec) : void 0
1620
+ }
1621
+ });
1622
+ if (printServeClientConfig(args.argv, launch)) return;
1623
+ if (hasFlag(args.argv, "--print-command")) {
1624
+ printJson({
1625
+ ok: true,
1626
+ model_id: launch.modelName,
1627
+ url: launch.url,
1628
+ command: launch.displayCommand,
1629
+ checkpoint: launch.env.TT_FOUNDATION_CHECKPOINT,
1630
+ tokenizer: launch.env.TT_FOUNDATION_TOKENIZER
1631
+ });
1632
+ return;
1633
+ }
1634
+ await serveLocalModel(launch);
1635
+ return;
1636
+ }
1637
+ if (readOption(args.argv, "--checkpoint") || readOption(args.argv, "--tokenizer")) {
1638
+ throw new Error("--checkpoint and --tokenizer require the foundation target.");
1639
+ }
1528
1640
  if (args.target === "base") {
1529
1641
  return serveBaseModelFromCli(args);
1530
1642
  }
@@ -1903,6 +2015,7 @@ export {
1903
2015
  baseModelRevisionSchema,
1904
2016
  behaviorSpecExampleSchema,
1905
2017
  behaviorSpecSchema,
2018
+ buildFoundationModelServerLaunch,
1906
2019
  buildLocalBaseModelServerLaunch,
1907
2020
  buildLocalModelServerLaunch,
1908
2021
  buildModelPrefetchPayload,
@@ -1961,8 +2074,10 @@ export {
1961
2074
  runRequestFromLocalSpec,
1962
2075
  sanitizeLogLine,
1963
2076
  serveLocalModel,
2077
+ specHash,
1964
2078
  specSnapshotSchema,
1965
2079
  trainingReportSchema,
2080
+ validateBehaviorSpec,
1966
2081
  validateLocalFineTuneInput,
1967
2082
  validateLocalPipeline,
1968
2083
  verifyLocalBaseModel,