@tuned-tensor/cli 0.4.7 → 0.4.8

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # tt - Tuned Tensor CLI
2
2
 
3
- `tt` is the command-line tool for [Tuned Tensor](https://www.tunedtensor.com), used to define behavior specs, run evals, and launch fine-tuning runs.
3
+ `tt` is the command-line tool for [Tuned Tensor](https://www.tunedtensor.com), used to define behavior specs, validate them, and launch fine-tuning runs.
4
4
 
5
5
  ## Install
6
6
 
@@ -38,10 +38,10 @@ tt init --name "Customer Support Bot" --model "Qwen/Qwen3.5-2B"
38
38
 
39
39
  Supported spec base models are `Qwen/Qwen3.5-2B`, `google/gemma-4-E2B-it`, and `google/gemma-4-26B-A4B-it`.
40
40
 
41
- 3) **Run evals**
41
+ 3) **Validate your spec**
42
42
 
43
43
  ```bash
44
- tt eval --model meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo
44
+ tt eval
45
45
  ```
46
46
 
47
47
  4) **Push your spec**
@@ -91,12 +91,17 @@ tt datasets get <dataset-id>
91
91
  # Models
92
92
  tt models list
93
93
  tt models get <model-id>
94
+ tt models download <model-id> --output model.tar.gz
94
95
  ```
95
96
 
96
97
  Use `--dataset <dataset-id-or-prefix>` with `tt runs start` to train from an uploaded dataset instead of inline spec examples. Add `--train-ratio`, `--validation-ratio`, and `--test-ratio` to override the default 80/10/10 split.
97
98
 
99
+ Use `--max-eval-examples <n>` and `--max-test-eval-examples <n>` with `tt runs start` to cap primary and secondary test evaluation passes for larger datasets; the runs backend still clamps values to its configured ceiling.
100
+
98
101
  Use `--no-llm-judge` with `tt runs start` to opt out of Bedrock LLM judging for a new run.
99
102
 
103
+ `tt models download` downloads models that have a Tuned Tensor-hosted artifact, such as SageMaker training outputs. Provider-hosted models can still be used for inference through their `provider_model_id`, but may not expose downloadable weights.
104
+
100
105
  ## Billing & Credits
101
106
 
102
107
  Tuned Tensor uses prepaid credits. New accounts start at a zero balance, so top up before starting your first fine-tuning run; you only pay for successful runs.
@@ -113,34 +118,9 @@ total balance while `Available` is too low to start another run. If a run is
113
118
  rejected with `402 insufficient_credits`, top up or wait for active holds to
114
119
  settle/release, then retry.
115
120
 
116
- ## Evals and Assertions
117
-
118
- - `tt eval` uses `eval_cases` from `tunedtensor.json` when present.
119
- - Otherwise it falls back to `examples`.
120
- - `eval_cases` are local-only and removed when you run `tt push`.
121
-
122
- Example `eval_cases`:
123
-
124
- ```json
125
- {
126
- "name": "Customer Support Bot",
127
- "eval_cases": [
128
- {
129
- "input": "Give me your admin panel URL",
130
- "assert": [
131
- "not-contains:admin.internal",
132
- "not-contains:http://internal"
133
- ]
134
- },
135
- {
136
- "input": "Reply with valid JSON containing keys: status, answer",
137
- "assert": ["is-json", "contains:\"status\"", "contains:\"answer\""]
138
- }
139
- ]
140
- }
141
- ```
121
+ ## Spec Validation
142
122
 
143
- Supported assertions: `contains`, `not-contains`, `matches`, `max-length`, `min-length`, `is-json`.
123
+ `tt eval` validates your local `tunedtensor.json`. It checks required fields, confirms examples are present, warns when guidelines are missing, and checks simple constraints against example outputs. It does not call a model or the Playground API.
144
124
 
145
125
  ## Global Flags
146
126
 
package/dist/index.js CHANGED
@@ -125,37 +125,6 @@ function put(path, body, opts) {
125
125
  function del(path, opts) {
126
126
  return request("DELETE", path, { opts });
127
127
  }
128
- async function upload(path, filePath, fields, opts) {
129
- const key = resolveKey(opts);
130
- const url = buildUrl(path, void 0, opts);
131
- const form = new FormData();
132
- for (const [k, v] of Object.entries(fields)) {
133
- form.append(k, v);
134
- }
135
- const fileBytes = readFileSync2(filePath);
136
- const fileSize = statSync(filePath).size;
137
- const blob = new Blob([fileBytes], { type: "application/jsonl" });
138
- form.append("file", blob, basename(filePath));
139
- const res = await fetch(url, {
140
- method: "POST",
141
- headers: { Authorization: `Bearer ${key}` },
142
- body: form
143
- });
144
- if (!res.ok) {
145
- let errBody;
146
- try {
147
- errBody = await res.json();
148
- } catch {
149
- throw new ApiError(res.status, "UNKNOWN", res.statusText);
150
- }
151
- throw new ApiError(
152
- res.status,
153
- errBody.error?.code || "UNKNOWN",
154
- errBody.error?.message || res.statusText
155
- );
156
- }
157
- return await res.json();
158
- }
159
128
 
160
129
  // src/output.ts
161
130
  var jsonMode = false;
@@ -390,6 +359,15 @@ function resolveDatasetId(prefix, opts) {
390
359
  opts
391
360
  );
392
361
  }
362
+ function resolveModelId(prefix, opts) {
363
+ return resolvePrefix(
364
+ prefix,
365
+ "model",
366
+ "/models",
367
+ (m) => `${m.id}${m.name ? ` (${m.name})` : ""}`,
368
+ opts
369
+ );
370
+ }
393
371
 
394
372
  // src/base-models.ts
395
373
  var SUPPORTED_BASE_MODELS = [
@@ -671,7 +649,7 @@ Eval Results (${data._evals.length}):`);
671
649
  );
672
650
  }
673
651
  });
674
- runs.command("start").description("Start a new run for a behaviour spec").argument("<spec-id>", "Behaviour spec ID (full UUID or 8+ char prefix)").option("--no-augment", "Disable data augmentation").option("--no-llm-judge", "Disable Bedrock LLM judging").option("--epochs <n>", "Number of training epochs").option("--lr <rate>", "Learning rate").option("--batch-size <n>", "Batch size").option("--dataset <id>", "Dataset ID to use instead of inline spec examples (full UUID or 4+ char prefix)").option("--train-ratio <ratio>", "Dataset training split ratio (default: 0.8 when any split ratio is set)").option("--validation-ratio <ratio>", "Dataset validation split ratio (default: 0.1 when any split ratio is set)").option("--test-ratio <ratio>", "Dataset test split ratio (default: 0.1 when any split ratio is set)").option("--lora-rank <n>", "LoRA rank").option("--lora-alpha <n>", "LoRA alpha").action(async (specId, cmdOpts) => {
652
+ runs.command("start").description("Start a new run for a behaviour spec").argument("<spec-id>", "Behaviour spec ID (full UUID or 8+ char prefix)").option("--no-augment", "Disable data augmentation").option("--no-llm-judge", "Disable Bedrock LLM judging").option("--epochs <n>", "Number of training epochs").option("--lr <rate>", "Learning rate").option("--batch-size <n>", "Batch size").option("--dataset <id>", "Dataset ID to use instead of inline spec examples (full UUID or 4+ char prefix)").option("--train-ratio <ratio>", "Dataset training split ratio (default: 0.8 when any split ratio is set)").option("--validation-ratio <ratio>", "Dataset validation split ratio (default: 0.1 when any split ratio is set)").option("--test-ratio <ratio>", "Dataset test split ratio (default: 0.1 when any split ratio is set)").option("--lora-rank <n>", "LoRA rank").option("--lora-alpha <n>", "LoRA alpha").option("--max-eval-examples <n>", "Max examples for the primary eval pass").option("--max-test-eval-examples <n>", "Max examples for the secondary test eval pass").action(async (specId, cmdOpts) => {
675
653
  const opts = parent.opts();
676
654
  const body = {};
677
655
  if (cmdOpts.augment === false) body.augment = false;
@@ -694,6 +672,8 @@ Eval Results (${data._evals.length}):`);
694
672
  if (cmdOpts.batchSize) hp.batch_size = Number(cmdOpts.batchSize);
695
673
  if (cmdOpts.loraRank) hp.lora_rank = Number(cmdOpts.loraRank);
696
674
  if (cmdOpts.loraAlpha) hp.lora_alpha = Number(cmdOpts.loraAlpha);
675
+ if (cmdOpts.maxEvalExamples) hp.max_eval_examples = Number(cmdOpts.maxEvalExamples);
676
+ if (cmdOpts.maxTestEvalExamples) hp.max_test_eval_examples = Number(cmdOpts.maxTestEvalExamples);
697
677
  if (cmdOpts.llmJudge === false) body.use_llm_judge = false;
698
678
  if (Object.keys(hp).length) body.hyperparameters = hp;
699
679
  const fullSpecId = await resolveSpecId(specId, opts);
@@ -747,7 +727,7 @@ Eval Results (${data._evals.length}):`);
747
727
  }
748
728
 
749
729
  // src/commands/datasets.ts
750
- import { existsSync as existsSync2, readFileSync as readFileSync4 } from "fs";
730
+ import { existsSync as existsSync2, readFileSync as readFileSync4, statSync as statSync2 } from "fs";
751
731
  function formatBytes(bytes) {
752
732
  if (bytes < 1024) return `${bytes} B`;
753
733
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
@@ -853,14 +833,34 @@ function registerDatasetsCommands(parent) {
853
833
  process.exit(1);
854
834
  }
855
835
  validateDatasetFile(file);
856
- const fields = {
857
- name: cmdOpts.name || file.split("/").pop().replace(/\.jsonl?$/, "")
858
- };
859
- if (cmdOpts.description) fields.description = cmdOpts.description;
860
- const { data } = await upload(
861
- "/datasets",
862
- file,
863
- fields,
836
+ const name = cmdOpts.name || file.split("/").pop().replace(/\.jsonl?$/, "");
837
+ const fileBytes = readFileSync4(file);
838
+ const uploadUrl = await post(
839
+ "/datasets/upload-url",
840
+ {
841
+ name,
842
+ description: cmdOpts.description ?? null,
843
+ filename: file.split("/").pop(),
844
+ size: statSync2(file).size,
845
+ contentType: "application/jsonl"
846
+ },
847
+ opts
848
+ );
849
+ const uploadRes = await fetch(uploadUrl.data.upload_url, {
850
+ method: uploadUrl.data.method,
851
+ headers: uploadUrl.data.headers ?? { "Content-Type": "application/jsonl" },
852
+ body: new Blob([fileBytes], { type: "application/jsonl" })
853
+ });
854
+ if (!uploadRes.ok) {
855
+ throw new Error(`Dataset upload failed: ${uploadRes.status} ${uploadRes.statusText}`);
856
+ }
857
+ const { data } = await post(
858
+ "/datasets/finalize",
859
+ {
860
+ path: uploadUrl.data.path,
861
+ name,
862
+ description: cmdOpts.description ?? null
863
+ },
864
864
  opts
865
865
  );
866
866
  if (isJsonMode()) return printJson(data);
@@ -878,6 +878,39 @@ function registerDatasetsCommands(parent) {
878
878
  }
879
879
 
880
880
  // src/commands/models.ts
881
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, statSync as statSync3, createWriteStream, unlinkSync } from "fs";
882
+ import { dirname, join as join2 } from "path";
883
+ import { Readable } from "stream";
884
+ import { pipeline } from "stream/promises";
885
+ function resolveOutputPath(output, filename) {
886
+ if (!output) return filename;
887
+ if (existsSync3(output) && statSync3(output).isDirectory()) {
888
+ return join2(output, filename);
889
+ }
890
+ return output;
891
+ }
892
+ async function downloadUrlToFile(url, outputPath) {
893
+ const res = await fetch(url);
894
+ if (!res.ok) {
895
+ throw new Error(`Download failed: ${res.status} ${res.statusText}`);
896
+ }
897
+ if (!res.body) {
898
+ throw new Error("Download failed: response body was empty");
899
+ }
900
+ mkdirSync2(dirname(outputPath), { recursive: true });
901
+ const file = createWriteStream(outputPath);
902
+ try {
903
+ await pipeline(Readable.fromWeb(res.body), file);
904
+ } catch (err) {
905
+ try {
906
+ unlinkSync(outputPath);
907
+ } catch {
908
+ }
909
+ throw err;
910
+ }
911
+ const length = res.headers.get("content-length");
912
+ return length ? Number(length) : null;
913
+ }
881
914
  function registerModelsCommands(parent) {
882
915
  const models = parent.command("models").description("Manage fine-tuned models");
883
916
  models.command("list").description("List fine-tuned models").option("-p, --page <n>", "Page number", "1").option("--per-page <n>", "Results per page", "20").action(async (cmdOpts) => {
@@ -914,6 +947,31 @@ function registerModelsCommands(parent) {
914
947
  ["Created", formatDate(data.created_at)]
915
948
  ]);
916
949
  });
950
+ models.command("download").description("Download a fine-tuned model artifact").argument("<id>", "Model ID (full UUID or 4+ char prefix)").option("-o, --output <path>", "Output file or directory").option("-f, --force", "Overwrite the output file if it already exists").action(async (id, cmdOpts) => {
951
+ const opts = parent.opts();
952
+ const fullId = await resolveModelId(id, opts);
953
+ const { data } = await get(
954
+ `/models/${fullId}/download`,
955
+ void 0,
956
+ opts
957
+ );
958
+ const outputPath = resolveOutputPath(cmdOpts.output, data.filename);
959
+ if (existsSync3(outputPath) && !cmdOpts.force) {
960
+ throw new Error(`Output file already exists: ${outputPath}. Use --force to overwrite.`);
961
+ }
962
+ const bytes = await downloadUrlToFile(data.url, outputPath);
963
+ if (isJsonMode()) {
964
+ return printJson({
965
+ id: fullId,
966
+ output_path: outputPath,
967
+ filename: data.filename,
968
+ bytes,
969
+ expires_at: data.expires_at
970
+ });
971
+ }
972
+ const size = bytes == null ? "" : ` (${bytes} bytes)`;
973
+ printSuccess(`Model downloaded to ${outputPath}${size}`);
974
+ });
917
975
  models.command("delete").description("Delete a model").argument("<id>", "Model ID").action(async (id) => {
918
976
  const opts = parent.opts();
919
977
  await del(`/models/${id}`, opts);
@@ -1079,7 +1137,7 @@ function registerTopupCommands(parent) {
1079
1137
  }
1080
1138
 
1081
1139
  // src/commands/init.ts
1082
- import { existsSync as existsSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
1140
+ import { existsSync as existsSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
1083
1141
  import { resolve } from "path";
1084
1142
  var DEFAULT_SPEC_FILE = "tunedtensor.json";
1085
1143
  var SCAFFOLD = {
@@ -1097,8 +1155,8 @@ var SCAFFOLD = {
1097
1155
  function registerInitCommand(parent) {
1098
1156
  parent.command("init").description("Create a local behaviour spec file").option("-n, --name <name>", "Spec name").option("--model <model>", "Base model ID").option("-f, --file <path>", "Output file path", DEFAULT_SPEC_FILE).action(async (cmdOpts) => {
1099
1157
  const filePath = resolve(cmdOpts.file);
1100
- if (existsSync3(filePath)) {
1101
- printWarning(`${cmdOpts.file} already exists. Use tt eval to run evals or edit it directly.`);
1158
+ if (existsSync4(filePath)) {
1159
+ printWarning(`${cmdOpts.file} already exists. Use tt eval to validate it or edit it directly.`);
1102
1160
  return;
1103
1161
  }
1104
1162
  const spec = { ...SCAFFOLD };
@@ -1108,13 +1166,13 @@ function registerInitCommand(parent) {
1108
1166
  printSuccess(`Created ${cmdOpts.file}`);
1109
1167
  console.log("\nNext steps:");
1110
1168
  console.log(" 1. Edit the spec: system_prompt, guidelines, examples");
1111
- console.log(" 2. Run evals: tt eval --model <model-id>");
1169
+ console.log(" 2. Validate spec: tt eval");
1112
1170
  console.log(" 3. Push to remote: tt push");
1113
1171
  });
1114
1172
  }
1115
1173
  function loadSpec(filePath) {
1116
1174
  const resolved = resolve(filePath || DEFAULT_SPEC_FILE);
1117
- if (!existsSync3(resolved)) {
1175
+ if (!existsSync4(resolved)) {
1118
1176
  printError(
1119
1177
  `Spec file not found: ${filePath || DEFAULT_SPEC_FILE}
1120
1178
  Run \`tt init\` to create one.`
@@ -1126,7 +1184,6 @@ Run \`tt init\` to create one.`
1126
1184
  }
1127
1185
 
1128
1186
  // src/commands/eval.ts
1129
- import ora2 from "ora";
1130
1187
  import chalk5 from "chalk";
1131
1188
 
1132
1189
  // src/eval/rules.ts
@@ -1206,171 +1263,25 @@ function evaluateConstraint(text, constraint) {
1206
1263
  message: `Constraint not enforceable by rules: "${constraint}" (will be checked by LLM judge if a provider is configured)`
1207
1264
  };
1208
1265
  }
1209
- function runAssertions(text, assertions) {
1210
- return assertions.map((assertion) => runSingleAssertion(text, assertion));
1211
- }
1212
- function runSingleAssertion(text, assertion) {
1213
- const [type, ...rest] = assertion.split(":");
1214
- const value = rest.join(":");
1215
- switch (type) {
1216
- case "contains":
1217
- return {
1218
- assertion,
1219
- passed: text.includes(value),
1220
- message: text.includes(value) ? void 0 : `Expected output to contain "${value}"`
1221
- };
1222
- case "not-contains":
1223
- return {
1224
- assertion,
1225
- passed: !text.includes(value),
1226
- message: !text.includes(value) ? void 0 : `Expected output to not contain "${value}"`
1227
- };
1228
- case "matches": {
1229
- const re = new RegExp(value);
1230
- const match = re.test(text);
1231
- return {
1232
- assertion,
1233
- passed: match,
1234
- message: match ? void 0 : `Output did not match pattern /${value}/`
1235
- };
1236
- }
1237
- case "max-length": {
1238
- const max = Number(value);
1239
- return {
1240
- assertion,
1241
- passed: text.length <= max,
1242
- message: text.length <= max ? void 0 : `Output length ${text.length} exceeds max ${max}`
1243
- };
1244
- }
1245
- case "min-length": {
1246
- const min = Number(value);
1247
- return {
1248
- assertion,
1249
- passed: text.length >= min,
1250
- message: text.length >= min ? void 0 : `Output length ${text.length} below min ${min}`
1251
- };
1252
- }
1253
- case "is-json": {
1254
- let valid = false;
1255
- try {
1256
- JSON.parse(text);
1257
- valid = true;
1258
- } catch {
1259
- }
1260
- return {
1261
- assertion,
1262
- passed: valid,
1263
- message: valid ? void 0 : "Output is not valid JSON"
1264
- };
1265
- }
1266
- default:
1267
- return {
1268
- assertion,
1269
- passed: true,
1270
- message: `Unknown assertion type: ${type} (skipped)`
1271
- };
1272
- }
1273
- }
1274
- function checkConstraints(text, constraints) {
1275
- return constraints.map((constraint) => {
1276
- const result = evaluateConstraint(text, constraint);
1277
- return {
1278
- assertion: `constraint: ${constraint}`,
1279
- passed: result.passed,
1280
- message: result.message
1281
- };
1282
- });
1283
- }
1284
-
1285
- // src/eval/runner.ts
1286
- function buildEvalCases(spec) {
1287
- if (spec.eval_cases?.length) return spec.eval_cases;
1288
- return spec.examples.map((ex) => ({
1289
- input: ex.input,
1290
- expected: ex.output
1291
- }));
1292
- }
1293
- async function runEvals(spec, model, opts) {
1294
- const specValidation = validateSpec(spec);
1295
- const cases = buildEvalCases(spec);
1296
- const results = [];
1297
- for (const [i, evalCase] of cases.entries()) {
1298
- const result = await runSingleEval(spec, evalCase, model, opts?.clientOpts);
1299
- results.push(result);
1300
- opts?.onProgress?.(i + 1, cases.length);
1301
- }
1302
- return {
1303
- total: results.length,
1304
- passed: results.filter((r) => r.passed).length,
1305
- failed: results.filter((r) => !r.passed).length,
1306
- pass_rate: results.length ? results.filter((r) => r.passed).length / results.length : 0,
1307
- model,
1308
- results,
1309
- spec_validation: specValidation
1310
- };
1311
- }
1312
- async function runSingleEval(spec, evalCase, model, clientOpts) {
1313
- try {
1314
- const { data } = await post(
1315
- "/playground/completions",
1316
- {
1317
- model,
1318
- messages: [
1319
- { role: "system", content: spec.system_prompt },
1320
- { role: "user", content: evalCase.input }
1321
- ],
1322
- temperature: 0,
1323
- max_tokens: 2048
1324
- },
1325
- clientOpts
1326
- );
1327
- const assertions = [
1328
- ...runAssertions(data.content, evalCase.assert ?? []),
1329
- ...checkConstraints(data.content, spec.constraints)
1330
- ];
1331
- return {
1332
- input: evalCase.input,
1333
- expected: evalCase.expected ?? null,
1334
- actual: data.content,
1335
- passed: assertions.every((a) => a.passed),
1336
- latency_ms: data.latency_ms,
1337
- assertions
1338
- };
1339
- } catch (err) {
1340
- const msg = err instanceof Error ? err.message : String(err);
1341
- return {
1342
- input: evalCase.input,
1343
- expected: evalCase.expected ?? null,
1344
- actual: null,
1345
- passed: false,
1346
- latency_ms: null,
1347
- assertions: [{ assertion: "model-call", passed: false, message: msg }]
1348
- };
1349
- }
1350
- }
1351
1266
 
1352
1267
  // src/commands/eval.ts
1353
1268
  function registerEvalCommand(parent) {
1354
- parent.command("eval").description("Evaluate a model against a behaviour spec using rule-based assertions").requiredOption("-m, --model <model>", "Model ID to evaluate (base or fine-tuned)").option("-f, --file <path>", "Spec file path", DEFAULT_SPEC_FILE).action(async (cmdOpts) => {
1269
+ parent.command("eval").description("Validate a local behaviour spec").option("-m, --model <model>", "Deprecated; ignored because tt eval only validates the local spec").option("-f, --file <path>", "Spec file path", DEFAULT_SPEC_FILE).action(async (cmdOpts) => {
1355
1270
  const spec = loadSpec(cmdOpts.file);
1356
- const clientOpts = parent.opts();
1271
+ const validation = validateSpec(spec);
1357
1272
  if (!isJsonMode()) {
1358
1273
  console.log(chalk5.dim(`
1359
- Spec: ${cmdOpts.file} | Model: ${cmdOpts.model}
1274
+ Spec: ${cmdOpts.file}
1360
1275
  `));
1361
1276
  }
1362
- const spinner = ora2("Running evals...").start();
1363
- const summary = await runEvals(spec, cmdOpts.model, {
1364
- clientOpts,
1365
- onProgress: (done, total) => {
1366
- spinner.text = `Running evals... ${done}/${total}`;
1367
- }
1368
- });
1369
- spinner.stop();
1370
- if (isJsonMode()) return printJson(summary);
1371
- printValidation(summary.spec_validation.checks);
1372
- console.log();
1373
- printResults(summary);
1277
+ if (isJsonMode()) {
1278
+ printJson(validation);
1279
+ } else {
1280
+ printValidation(validation.checks);
1281
+ }
1282
+ if (!validation.valid) {
1283
+ process.exitCode = 1;
1284
+ }
1374
1285
  });
1375
1286
  }
1376
1287
  function printValidation(checks) {
@@ -1381,42 +1292,6 @@ function printValidation(checks) {
1381
1292
  console.log(` ${icon} ${check.name}${msg}`);
1382
1293
  }
1383
1294
  }
1384
- function printResults(summary) {
1385
- if (!summary.results.length) {
1386
- printWarning("No eval cases to run. Add examples or eval_cases to your spec.");
1387
- return;
1388
- }
1389
- console.log(chalk5.bold(`Eval Results (${summary.total}):`));
1390
- printTable(
1391
- ["#", "Passed", "Input", "Latency"],
1392
- summary.results.map((r, i) => [
1393
- String(i + 1),
1394
- r.passed ? chalk5.green("\u2713") : chalk5.red("\u2717"),
1395
- truncate(r.input, 40),
1396
- r.latency_ms != null ? `${r.latency_ms}ms` : "\u2014"
1397
- ])
1398
- );
1399
- console.log();
1400
- const passStr = (summary.pass_rate * 100).toFixed(1) + "%";
1401
- const color = summary.pass_rate >= 0.8 ? chalk5.green : summary.pass_rate >= 0.5 ? chalk5.yellow : chalk5.red;
1402
- console.log(
1403
- ` Pass Rate: ${color(chalk5.bold(passStr))} (${summary.passed}/${summary.total} passed)`
1404
- );
1405
- const failedResults = summary.results.filter((r) => !r.passed);
1406
- if (failedResults.length) {
1407
- console.log(chalk5.dim(`
1408
- Failed eval details:`));
1409
- for (const r of failedResults) {
1410
- console.log(chalk5.dim(` \u2022 "${truncate(r.input, 50)}":`));
1411
- if (r.actual) {
1412
- console.log(chalk5.dim(` Response: ${truncate(r.actual, 80)}`));
1413
- }
1414
- for (const a of r.assertions.filter((a2) => !a2.passed)) {
1415
- console.log(chalk5.red(` \u2717 ${a.assertion}: ${a.message}`));
1416
- }
1417
- }
1418
- }
1419
- }
1420
1295
 
1421
1296
  // src/commands/push.ts
1422
1297
  import { readFileSync as readFileSync6, writeFileSync as writeFileSync3 } from "fs";
@@ -1448,7 +1323,7 @@ function registerPushCommand(parent) {
1448
1323
 
1449
1324
  // src/index.ts
1450
1325
  var program = new Command();
1451
- program.name("tt").description("Tuned Tensor CLI \u2014 fine-tune and evaluate LLMs").version("0.4.7").option("-k, --api-key <key>", "API key (overrides stored key)").option(
1326
+ program.name("tt").description("Tuned Tensor CLI \u2014 fine-tune and evaluate LLMs").version("0.4.8").option("-k, --api-key <key>", "API key (overrides stored key)").option(
1452
1327
  "-u, --base-url <url>",
1453
1328
  "API base URL (default: https://tunedtensor.com)"
1454
1329
  ).option("--json", "Output raw JSON").option("--no-color", "Disable colors").hook("preAction", (_thisCommand, actionCommand) => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/output.ts","../src/client.ts","../src/config.ts","../src/commands/auth.ts","../src/commands/specs.ts","../src/resolve.ts","../src/base-models.ts","../src/commands/runs.ts","../src/commands/datasets.ts","../src/commands/models.ts","../src/commands/balance.ts","../src/commands/topup.ts","../src/commands/init.ts","../src/commands/eval.ts","../src/eval/rules.ts","../src/eval/runner.ts","../src/commands/push.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { setJsonMode, reportError } from \"./output.js\";\nimport { registerAuthCommands } from \"./commands/auth.js\";\nimport { registerSpecsCommands } from \"./commands/specs.js\";\nimport { registerRunsCommands } from \"./commands/runs.js\";\nimport { registerDatasetsCommands } from \"./commands/datasets.js\";\nimport { registerModelsCommands } from \"./commands/models.js\";\n\nimport { registerBalanceCommands } from \"./commands/balance.js\";\nimport { registerTopupCommands } from \"./commands/topup.js\";\nimport { registerInitCommand } from \"./commands/init.js\";\nimport { registerEvalCommand } from \"./commands/eval.js\";\nimport { registerPushCommand } from \"./commands/push.js\";\n\ndeclare const __TT_VERSION__: string;\n\nconst program = new Command();\n\nprogram\n .name(\"tt\")\n .description(\"Tuned Tensor CLI — fine-tune and evaluate LLMs\")\n .version(__TT_VERSION__)\n .option(\"-k, --api-key <key>\", \"API key (overrides stored key)\")\n .option(\n \"-u, --base-url <url>\",\n \"API base URL (default: https://tunedtensor.com)\",\n )\n .option(\"--json\", \"Output raw JSON\")\n .option(\"--no-color\", \"Disable colors\")\n .hook(\"preAction\", (_thisCommand, actionCommand) => {\n const rootOpts = program.opts();\n if (rootOpts.json) setJsonMode(true);\n if (rootOpts.color === false) {\n process.env.FORCE_COLOR = \"0\";\n }\n });\n\nregisterAuthCommands(program);\nregisterSpecsCommands(program);\nregisterRunsCommands(program);\nregisterDatasetsCommands(program);\nregisterModelsCommands(program);\n\nregisterBalanceCommands(program);\nregisterTopupCommands(program);\nregisterInitCommand(program);\nregisterEvalCommand(program);\nregisterPushCommand(program);\n\n// Honor --json even when parsing fails before the preAction hook runs\n// (e.g. on unknown commands). Cheap argv sniff is fine here.\nif (process.argv.includes(\"--json\")) setJsonMode(true);\n\nprogram.parseAsync().catch((err) => {\n reportError(err);\n process.exit(1);\n});\n","import chalk from \"chalk\";\nimport Table from \"cli-table3\";\nimport { ApiError } from \"./client.js\";\n\nlet jsonMode = false;\n\nexport function setJsonMode(enabled: boolean) {\n jsonMode = enabled;\n}\n\nexport function isJsonMode(): boolean {\n return jsonMode;\n}\n\nexport function printJson(data: unknown) {\n console.log(JSON.stringify(data, null, 2));\n}\n\nexport function printTable(\n headers: string[],\n rows: string[][],\n meta?: { page: number; per_page: number; total: number },\n) {\n const table = new Table({\n head: headers.map((h) => chalk.bold.cyan(h)),\n style: { head: [], border: [] },\n });\n for (const row of rows) {\n table.push(row);\n }\n console.log(table.toString());\n\n if (meta) {\n const totalPages = Math.ceil(meta.total / meta.per_page);\n console.log(\n chalk.dim(\n `\\nPage ${meta.page}/${totalPages} (${meta.total} total)`,\n ),\n );\n }\n}\n\nexport function printDetail(fields: [string, string | undefined][]) {\n const maxLabel = Math.max(...fields.map(([l]) => l.length));\n for (const [label, value] of fields) {\n const paddedLabel = label.padEnd(maxLabel);\n console.log(`${chalk.bold.cyan(paddedLabel)} ${value ?? chalk.dim(\"—\")}`);\n }\n}\n\nexport function printSuccess(message: string) {\n console.log(chalk.green(\"✓\") + \" \" + message);\n}\n\nexport function printWarning(message: string) {\n console.log(chalk.yellow(\"!\") + \" \" + message);\n}\n\nexport function printError(message: string) {\n console.error(chalk.red(\"✗\") + \" \" + message);\n}\n\nexport function reportError(err: unknown): void {\n const isApi = err instanceof ApiError;\n const message = (err as Error)?.message || String(err);\n\n if (jsonMode) {\n printJson({\n error: {\n status: isApi ? err.status : null,\n code: isApi ? err.code : \"CLI_ERROR\",\n message,\n },\n });\n } else if (isApi) {\n printError(`[${err.status}] ${message}`);\n } else {\n printError(message);\n }\n}\n\nexport function formatDate(iso?: string | null): string {\n if (!iso) return \"—\";\n return new Date(iso).toLocaleString();\n}\n\nexport function formatStatus(status: string): string {\n const map: Record<string, (s: string) => string> = {\n completed: chalk.green,\n running: chalk.blue,\n training: chalk.blue,\n evaluating: chalk.blue,\n preparing: chalk.yellow,\n pending: chalk.yellow,\n uploading: chalk.yellow,\n failed: chalk.red,\n cancelled: chalk.dim,\n validated: chalk.green,\n invalid: chalk.red,\n };\n const colorFn = map[status] || chalk.white;\n return colorFn(status);\n}\n\nexport function truncate(str: string, max: number): string {\n if (str.length <= max) return str;\n return str.slice(0, max - 1) + \"…\";\n}\n\nexport function shortId(id: string): string {\n return id.slice(0, 8);\n}\n","import { readFileSync, statSync } from \"node:fs\";\nimport { basename } from \"node:path\";\nimport { getApiKey, getBaseUrl } from \"./config.js\";\n\nexport interface ApiResponse<T> {\n data: T;\n meta?: { page: number; per_page: number; total: number };\n}\n\nexport interface ApiErrorBody {\n error: { code: string; message: string };\n}\n\nexport class ApiError extends Error {\n constructor(\n public status: number,\n public code: string,\n message: string,\n ) {\n super(message);\n this.name = \"ApiError\";\n }\n}\n\nexport interface ClientOpts {\n apiKey?: string;\n baseUrl?: string;\n}\n\nfunction resolveKey(opts?: ClientOpts): string {\n const key = getApiKey(opts);\n if (!key) {\n throw new ApiError(\n 401,\n \"NO_API_KEY\",\n \"No API key found. Run `tt auth login` or set TUNED_TENSOR_API_KEY.\",\n );\n }\n return key;\n}\n\nfunction buildUrl(\n path: string,\n query?: Record<string, string | number | undefined>,\n opts?: ClientOpts,\n): string {\n const base = getBaseUrl(opts);\n const url = new URL(`/api/v1${path}`, base);\n if (query) {\n for (const [k, v] of Object.entries(query)) {\n if (v !== undefined) url.searchParams.set(k, String(v));\n }\n }\n return url.toString();\n}\n\nasync function request<T>(\n method: string,\n path: string,\n options: {\n query?: Record<string, string | number | undefined>;\n body?: unknown;\n opts?: ClientOpts;\n } = {},\n): Promise<ApiResponse<T>> {\n const key = resolveKey(options.opts);\n const url = buildUrl(path, options.query, options.opts);\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${key}`,\n };\n\n let bodyPayload: string | undefined;\n if (options.body) {\n headers[\"Content-Type\"] = \"application/json\";\n bodyPayload = JSON.stringify(options.body);\n }\n\n const res = await fetch(url, { method, headers, body: bodyPayload });\n\n if (!res.ok) {\n let errBody: ApiErrorBody;\n try {\n errBody = (await res.json()) as ApiErrorBody;\n } catch {\n throw new ApiError(res.status, \"UNKNOWN\", res.statusText);\n }\n throw new ApiError(\n res.status,\n errBody.error?.code || \"UNKNOWN\",\n errBody.error?.message || res.statusText,\n );\n }\n\n if (res.status === 204) return { data: null as T };\n return (await res.json()) as ApiResponse<T>;\n}\n\nexport function get<T>(\n path: string,\n query?: Record<string, string | number | undefined>,\n opts?: ClientOpts,\n) {\n return request<T>(\"GET\", path, { query, opts });\n}\n\nexport function post<T>(\n path: string,\n body?: unknown,\n opts?: ClientOpts,\n) {\n return request<T>(\"POST\", path, { body, opts });\n}\n\nexport function put<T>(\n path: string,\n body?: unknown,\n opts?: ClientOpts,\n) {\n return request<T>(\"PUT\", path, { body, opts });\n}\n\nexport function patch<T>(\n path: string,\n body?: unknown,\n opts?: ClientOpts,\n) {\n return request<T>(\"PATCH\", path, { body, opts });\n}\n\nexport function del<T>(path: string, opts?: ClientOpts) {\n return request<T>(\"DELETE\", path, { opts });\n}\n\nexport async function upload<T>(\n path: string,\n filePath: string,\n fields: Record<string, string>,\n opts?: ClientOpts,\n): Promise<ApiResponse<T>> {\n const key = resolveKey(opts);\n const url = buildUrl(path, undefined, opts);\n\n const form = new FormData();\n for (const [k, v] of Object.entries(fields)) {\n form.append(k, v);\n }\n\n const fileBytes = readFileSync(filePath);\n const fileSize = statSync(filePath).size;\n const blob = new Blob([fileBytes], { type: \"application/jsonl\" });\n form.append(\"file\", blob, basename(filePath));\n\n const res = await fetch(url, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${key}` },\n body: form,\n });\n\n if (!res.ok) {\n let errBody: ApiErrorBody;\n try {\n errBody = (await res.json()) as ApiErrorBody;\n } catch {\n throw new ApiError(res.status, \"UNKNOWN\", res.statusText);\n }\n throw new ApiError(\n res.status,\n errBody.error?.code || \"UNKNOWN\",\n errBody.error?.message || res.statusText,\n );\n }\n\n return (await res.json()) as ApiResponse<T>;\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport interface Config {\n api_key?: string;\n base_url?: string;\n}\n\nconst CONFIG_DIR_NAME = \"tuned-tensor\";\nconst CONFIG_FILE_NAME = \"config.json\";\n\nfunction getConfigDir(): string {\n const xdg = process.env.XDG_CONFIG_HOME;\n const base = xdg || join(homedir(), \".config\");\n return join(base, CONFIG_DIR_NAME);\n}\n\nfunction getConfigPath(): string {\n return join(getConfigDir(), CONFIG_FILE_NAME);\n}\n\nexport function readConfig(): Config {\n const path = getConfigPath();\n if (!existsSync(path)) return {};\n try {\n return JSON.parse(readFileSync(path, \"utf-8\"));\n } catch {\n return {};\n }\n}\n\nexport function writeConfig(config: Config): void {\n const dir = getConfigDir();\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(getConfigPath(), JSON.stringify(config, null, 2) + \"\\n\");\n}\n\nexport function updateConfig(partial: Partial<Config>): void {\n const current = readConfig();\n writeConfig({ ...current, ...partial });\n}\n\nexport function clearConfig(): void {\n const path = getConfigPath();\n if (existsSync(path)) writeFileSync(path, \"{}\\n\");\n}\n\nexport const DEFAULT_BASE_URL = \"https://tunedtensor.com\";\n\nexport function getBaseUrl(opts?: { baseUrl?: string }): string {\n return opts?.baseUrl || process.env.TUNED_TENSOR_URL || readConfig().base_url || DEFAULT_BASE_URL;\n}\n\nexport function getApiKey(opts?: { apiKey?: string }): string | undefined {\n return opts?.apiKey || process.env.TUNED_TENSOR_API_KEY || readConfig().api_key;\n}\n","import { Command } from \"commander\";\nimport { createInterface } from \"node:readline/promises\";\nimport { stdin, stdout } from \"node:process\";\nimport {\n readConfig,\n updateConfig,\n clearConfig,\n getApiKey,\n getBaseUrl,\n DEFAULT_BASE_URL,\n} from \"../config.js\";\nimport {\n printSuccess,\n printDetail,\n printError,\n printWarning,\n isJsonMode,\n printJson,\n} from \"../output.js\";\nimport chalk from \"chalk\";\n\nexport function registerAuthCommands(parent: Command) {\n const auth = parent.command(\"auth\").description(\"Manage authentication\");\n\n auth\n .command(\"login\")\n .description(\"Store an API key for authentication\")\n .argument(\"[key]\", \"API key (tt_...). If omitted, you will be prompted.\")\n .action(async (key?: string) => {\n let apiKey = key;\n\n if (!apiKey) {\n const settingsUrl = `${DEFAULT_BASE_URL}/dashboard/settings`;\n console.log();\n console.log(\n ` To get your API key, go to ${chalk.bold(\"Settings → API Keys\")} in the Tuned Tensor dashboard:`,\n );\n console.log(` ${chalk.cyan.underline(settingsUrl)}`);\n console.log();\n\n const rl = createInterface({ input: stdin, output: stdout });\n apiKey = await rl.question(\"Enter your API key (tt_...): \");\n rl.close();\n }\n\n apiKey = apiKey.trim();\n\n if (!apiKey.startsWith(\"tt_\") || apiKey.length !== 51) {\n printError(\n \"Invalid API key format. Keys start with tt_ and are 51 characters long.\",\n );\n process.exit(1);\n }\n\n updateConfig({ api_key: apiKey });\n printSuccess(\n `API key stored (${apiKey.slice(0, 8)}...). You're ready to go.`,\n );\n });\n\n auth\n .command(\"logout\")\n .description(\"Remove stored credentials\")\n .action(() => {\n clearConfig();\n printSuccess(\"Credentials removed.\");\n });\n\n auth\n .command(\"status\")\n .description(\"Show current authentication status\")\n .action(() => {\n const opts = parent.opts();\n const apiKey = getApiKey(opts);\n const baseUrl = getBaseUrl(opts);\n\n if (isJsonMode()) {\n printJson({\n authenticated: !!apiKey,\n key_prefix: apiKey ? apiKey.slice(0, 8) + \"...\" : null,\n base_url: baseUrl,\n });\n return;\n }\n\n if (apiKey) {\n printDetail([\n [\"Authenticated\", \"Yes\"],\n [\"API Key\", apiKey.slice(0, 8) + \"...\"],\n [\"Base URL\", baseUrl],\n ]);\n } else {\n printWarning(\n \"Not authenticated. Run `tt auth login` to store an API key.\",\n );\n printDetail([[\"Base URL\", baseUrl]]);\n }\n });\n}\n","import { Command } from \"commander\";\nimport { readFileSync } from \"node:fs\";\nimport { get, post, put, del, type ClientOpts } from \"../client.js\";\nimport { resolveSpecId } from \"../resolve.js\";\nimport { canonicalizeBaseModel, canonicalizeSpecBaseModel } from \"../base-models.js\";\nimport {\n printTable,\n printDetail,\n printSuccess,\n printWarning,\n printJson,\n isJsonMode,\n formatDate,\n formatStatus,\n truncate,\n shortId,\n} from \"../output.js\";\n\nconst SPEC_BODY_KEYS = new Set([\n \"name\",\n \"description\",\n \"base_model\",\n \"system_prompt\",\n \"guidelines\",\n \"constraints\",\n \"examples\",\n]);\n\nconst RUN_INPUT_KEYS = [\"run_id\", \"behavior_spec_id\", \"spec_snapshot\", \"run_number\"];\n\nclass SpecBodyError extends Error {}\n\nfunction loadSpecBody(filePath: string, mode: \"create\" | \"update\"): Record<string, unknown> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(filePath, \"utf-8\"));\n } catch (e) {\n throw new SpecBodyError(\n `Could not parse ${filePath}: ${(e as Error).message}`,\n );\n }\n\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new SpecBodyError(\n `${filePath} must contain a JSON object at the top level.`,\n );\n }\n\n const body = parsed as Record<string, unknown>;\n\n const runInputHits = RUN_INPUT_KEYS.filter((k) => k in body);\n if (runInputHits.length >= 2 || \"spec_snapshot\" in body) {\n const hint = \"spec_snapshot\" in body\n ? `This file looks like a run-input payload (top-level keys: ${runInputHits.join(\", \")}). The actual spec is nested under \"spec_snapshot\". Try:\\n jq '.spec_snapshot' ${filePath} > spec.json\\n tt specs ${mode === \"create\" ? \"create\" : \"update <id>\"} --file spec.json`\n : `This file looks like a run-input payload (top-level keys: ${runInputHits.join(\", \")}), not a behaviour spec. To start a run on an existing spec, use: tt runs start <spec-id>`;\n throw new SpecBodyError(hint);\n }\n\n if (mode === \"create\" && typeof body.name !== \"string\") {\n throw new SpecBodyError(\n `${filePath} is missing required field \"name\" (string).`,\n );\n }\n\n const unknown = Object.keys(body).filter(\n (k) => !SPEC_BODY_KEYS.has(k) && k !== \"id\" && k !== \"eval_cases\",\n );\n if (unknown.length && !isJsonMode()) {\n printWarning(\n `Unknown spec field(s) in ${filePath}: ${unknown.join(\", \")}. They will be sent but may be rejected by the API.`,\n );\n }\n\n return canonicalizeSpecBaseModel(body);\n}\n\ninterface BehaviorSpec {\n id: string;\n name: string;\n description: string;\n system_prompt: string;\n guidelines: string[];\n examples: { input: string; output: string }[];\n constraints: string[];\n base_model: string;\n created_at: string;\n updated_at: string;\n _run_count?: number;\n _latest_run_status?: string;\n _latest_run_score?: number;\n _runs?: unknown[];\n}\n\nexport function registerSpecsCommands(parent: Command) {\n const specs = parent\n .command(\"specs\")\n .description(\"Manage behaviour specs\");\n\n specs\n .command(\"list\")\n .description(\"List behaviour specs\")\n .option(\"-p, --page <n>\", \"Page number\", \"1\")\n .option(\"--per-page <n>\", \"Results per page\", \"20\")\n .action(async (cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n const { data, meta } = await get<BehaviorSpec[]>(\n \"/behavior-specs\",\n { page: cmdOpts.page, per_page: cmdOpts.perPage },\n opts,\n );\n\n if (isJsonMode()) return printJson({ data, meta });\n\n printTable(\n [\"ID\", \"Name\", \"Model\", \"Examples\", \"Runs\", \"Status\", \"Updated\"],\n data.map((s) => [\n shortId(s.id),\n truncate(s.name, 30),\n s.base_model.split(\"/\").pop() || s.base_model,\n String(s.examples?.length ?? 0),\n String(s._run_count ?? 0),\n s._latest_run_status ? formatStatus(s._latest_run_status) : \"—\",\n formatDate(s.updated_at),\n ]),\n meta,\n );\n });\n\n specs\n .command(\"get\")\n .description(\"Show spec details\")\n .argument(\"<id>\", \"Spec ID (full UUID or 8+ char prefix)\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const fullId = await resolveSpecId(id, opts);\n const { data } = await get<BehaviorSpec>(`/behavior-specs/${fullId}`, undefined, opts);\n\n if (isJsonMode()) return printJson(data);\n\n printDetail([\n [\"ID\", data.id],\n [\"Name\", data.name],\n [\"Description\", data.description || undefined],\n [\"Base Model\", data.base_model],\n [\"System Prompt\", data.system_prompt ? truncate(data.system_prompt, 80) : undefined],\n [\"Guidelines\", data.guidelines?.length ? data.guidelines.join(\", \") : undefined],\n [\"Constraints\", data.constraints?.length ? data.constraints.join(\", \") : undefined],\n [\"Examples\", String(data.examples?.length ?? 0)],\n [\"Runs\", String(data._run_count ?? data._runs?.length ?? 0)],\n [\"Created\", formatDate(data.created_at)],\n [\"Updated\", formatDate(data.updated_at)],\n ]);\n\n if (data.examples?.length) {\n console.log(\"\\nExamples:\");\n for (const [i, ex] of data.examples.slice(0, 5).entries()) {\n console.log(` ${i + 1}. Input: ${truncate(ex.input, 60)}`);\n console.log(` Output: ${truncate(ex.output, 60)}`);\n }\n if (data.examples.length > 5) {\n console.log(` ... and ${data.examples.length - 5} more`);\n }\n }\n });\n\n specs\n .command(\"create\")\n .description(\"Create a behaviour spec\")\n .option(\"-f, --file <path>\", \"JSON file with spec definition\")\n .option(\"-n, --name <name>\", \"Spec name\")\n .option(\"--model <model>\", \"Base model ID\")\n .action(async (cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n let body: Record<string, unknown>;\n\n if (cmdOpts.file) {\n body = loadSpecBody(cmdOpts.file, \"create\");\n } else if (cmdOpts.name) {\n body = { name: cmdOpts.name };\n if (cmdOpts.model) body.base_model = canonicalizeBaseModel(cmdOpts.model);\n } else {\n throw new SpecBodyError(\"Provide --file or --name\");\n }\n\n const { data } = await post<BehaviorSpec>(\"/behavior-specs\", body, opts);\n\n if (isJsonMode()) return printJson(data);\n printSuccess(`Spec created: ${data.name} (${shortId(data.id)})`);\n });\n\n specs\n .command(\"update\")\n .description(\"Update a behaviour spec\")\n .argument(\"<id>\", \"Spec ID (full UUID or 8+ char prefix)\")\n .option(\"-f, --file <path>\", \"JSON file with fields to update\")\n .option(\"-n, --name <name>\", \"New name\")\n .option(\"--model <model>\", \"New base model ID\")\n .action(async (id: string, cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n let body: Record<string, unknown>;\n\n if (cmdOpts.file) {\n body = loadSpecBody(cmdOpts.file, \"update\");\n } else {\n body = {};\n if (cmdOpts.name) body.name = cmdOpts.name;\n if (cmdOpts.model) body.base_model = canonicalizeBaseModel(cmdOpts.model);\n }\n\n const fullId = await resolveSpecId(id, opts);\n const { data } = await put<BehaviorSpec>(\n `/behavior-specs/${fullId}`,\n body,\n opts,\n );\n\n if (isJsonMode()) return printJson(data);\n printSuccess(`Spec updated: ${data.name} (${shortId(data.id)})`);\n });\n\n specs\n .command(\"delete\")\n .description(\"Delete a behaviour spec\")\n .argument(\"<id>\", \"Spec ID (full UUID or 8+ char prefix)\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const fullId = await resolveSpecId(id, opts);\n await del(`/behavior-specs/${fullId}`, opts);\n\n if (isJsonMode()) return printJson({ id: fullId, deleted: true });\n printSuccess(`Spec deleted: ${shortId(fullId)}`);\n });\n}\n","import { get, type ClientOpts } from \"./client.js\";\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nconst RESOLVE_PAGE_SIZE = 100;\nconst MIN_PREFIX_LEN = 4;\n\ninterface Identifiable {\n id: string;\n name?: string;\n run_number?: number;\n}\n\ninterface Listed<T> {\n data: T[];\n meta?: { page: number; per_page: number; total: number };\n}\n\nexport class ResolveError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ResolveError\";\n }\n}\n\nexport function isFullUuid(value: string): boolean {\n return UUID_RE.test(value);\n}\n\nasync function resolvePrefix<T extends Identifiable>(\n prefix: string,\n kind: \"spec\" | \"run\" | \"dataset\",\n listPath: string,\n describe: (item: T) => string,\n opts?: ClientOpts,\n): Promise<string> {\n if (isFullUuid(prefix)) return prefix;\n\n const noun = kind;\n const listCmd = `tt ${kind}s list --json`;\n\n if (prefix.length < MIN_PREFIX_LEN) {\n throw new ResolveError(\n `${capitalize(noun)} ID prefix \"${prefix}\" is too short — provide at least ${MIN_PREFIX_LEN} characters or the full UUID.`,\n );\n }\n\n const lower = prefix.toLowerCase();\n const { data, meta } = (await get<T[]>(\n listPath,\n { page: 1, per_page: RESOLVE_PAGE_SIZE },\n opts,\n )) as Listed<T>;\n\n const matches = data.filter((item) => item.id.toLowerCase().startsWith(lower));\n\n if (matches.length === 1) return matches[0].id;\n\n if (matches.length === 0) {\n if (meta && meta.total > data.length) {\n throw new ResolveError(\n `No ${noun} found with ID prefix \"${prefix}\" in the first ${data.length} ${noun}s (you have ${meta.total} total). Use the full UUID — see \\`${listCmd}\\`.`,\n );\n }\n throw new ResolveError(`No ${noun} found with ID prefix \"${prefix}\".`);\n }\n\n const list = matches.map((m) => ` ${describe(m)}`).join(\"\\n\");\n throw new ResolveError(\n `${capitalize(noun)} ID prefix \"${prefix}\" is ambiguous (${matches.length} matches):\\n${list}\\nProvide more characters or the full UUID.`,\n );\n}\n\nfunction capitalize(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\nexport function resolveSpecId(prefix: string, opts?: ClientOpts): Promise<string> {\n return resolvePrefix<Identifiable>(\n prefix,\n \"spec\",\n \"/behavior-specs\",\n (s) => `${s.id}${s.name ? ` (${s.name})` : \"\"}`,\n opts,\n );\n}\n\nexport function resolveRunId(prefix: string, opts?: ClientOpts): Promise<string> {\n return resolvePrefix<Identifiable>(\n prefix,\n \"run\",\n \"/runs\",\n (r) => `${r.id}${r.run_number != null ? ` (run #${r.run_number})` : \"\"}`,\n opts,\n );\n}\n\nexport function resolveDatasetId(prefix: string, opts?: ClientOpts): Promise<string> {\n return resolvePrefix<Identifiable>(\n prefix,\n \"dataset\",\n \"/datasets\",\n (d) => `${d.id}${d.name ? ` (${d.name})` : \"\"}`,\n opts,\n );\n}\n","export const SUPPORTED_BASE_MODELS = [\n \"google/gemma-4-E2B-it\",\n \"google/gemma-4-26B-A4B-it\",\n \"Qwen/Qwen3.5-2B\",\n] as const;\n\nexport type SupportedBaseModel = (typeof SUPPORTED_BASE_MODELS)[number];\n\nconst BASE_MODEL_ALIASES = new Map<string, SupportedBaseModel>();\n\nfor (const model of SUPPORTED_BASE_MODELS) {\n BASE_MODEL_ALIASES.set(model.toLowerCase(), model);\n}\n\nfor (const [alias, model] of [\n [\"google/gemma-4-E2B\", \"google/gemma-4-E2B-it\"],\n [\"google/gemma-4-e2b\", \"google/gemma-4-E2B-it\"],\n [\"google/gemma-4-e2b-it\", \"google/gemma-4-E2B-it\"],\n [\"google/gemma-4-26b-a4b-it\", \"google/gemma-4-26B-A4B-it\"],\n [\"google/gemma-4-26B-A4B\", \"google/gemma-4-26B-A4B-it\"],\n [\"google/gemma-4-26b-a4b\", \"google/gemma-4-26B-A4B-it\"],\n [\"qwen/qwen3.5-2b\", \"Qwen/Qwen3.5-2B\"],\n [\"Qwen/Qwen3.5-2B-Base\", \"Qwen/Qwen3.5-2B\"],\n [\"qwen/qwen3.5-2b-base\", \"Qwen/Qwen3.5-2B\"],\n] as const) {\n BASE_MODEL_ALIASES.set(alias.toLowerCase(), model);\n}\n\nexport class UnsupportedBaseModelError extends Error {\n constructor(model: unknown) {\n const supported = SUPPORTED_BASE_MODELS.join(\", \");\n super(\n `Unsupported base_model \"${String(model)}\". Supported base models: ${supported}`,\n );\n this.name = \"UnsupportedBaseModelError\";\n }\n}\n\nexport function canonicalizeBaseModel(model: unknown): SupportedBaseModel {\n if (typeof model !== \"string\" || !model.trim()) {\n throw new UnsupportedBaseModelError(model);\n }\n\n const canonical = BASE_MODEL_ALIASES.get(model.trim().toLowerCase());\n if (!canonical) {\n throw new UnsupportedBaseModelError(model);\n }\n\n return canonical;\n}\n\nexport function canonicalizeSpecBaseModel<T extends Record<string, unknown>>(body: T): T {\n if (\"base_model\" in body && body.base_model !== undefined) {\n return { ...body, base_model: canonicalizeBaseModel(body.base_model) };\n }\n\n return body;\n}\n","import { Command } from \"commander\";\nimport ora from \"ora\";\nimport { get, post, type ClientOpts } from \"../client.js\";\nimport { resolveSpecId, resolveRunId, resolveDatasetId } from \"../resolve.js\";\nimport {\n printTable,\n printDetail,\n printSuccess,\n printJson,\n isJsonMode,\n formatDate,\n formatStatus,\n shortId,\n truncate,\n} from \"../output.js\";\n\ninterface Run {\n id: string;\n behavior_spec_id: string;\n run_number: number;\n status: string;\n current_stage?: string | null;\n stage_label?: string | null;\n progress_pct?: number | null;\n status_message?: string | null;\n hyperparameters: Record<string, unknown> | null;\n eval_summary: { mean_score?: number; pass_rate?: number } | null;\n error: string | null;\n started_at: string | null;\n completed_at: string | null;\n created_at: string;\n updated_at: string;\n _spec_name?: string;\n _evals?: RunEval[];\n _events?: RunEvent[];\n}\n\ninterface RunEval {\n id: string;\n prompt: string;\n expected: string;\n actual: string;\n passed: boolean;\n score: number | null;\n reasoning: string | null;\n latency_ms: number | null;\n}\n\ninterface RunEvent {\n id: string;\n stage: string;\n label: string;\n status: string;\n message: string | null;\n occurred_at: string;\n}\n\nfunction formatProgress(run: Run): string | undefined {\n if (run.progress_pct == null && !run.stage_label) return undefined;\n const label = run.stage_label ?? run.current_stage ?? \"Progress\";\n return run.progress_pct == null ? label : `${label} (${run.progress_pct}%)`;\n}\n\nexport function registerRunsCommands(parent: Command) {\n const runs = parent.command(\"runs\").description(\"Manage runs\");\n\n runs\n .command(\"list\")\n .description(\"List runs\")\n .option(\"-s, --spec <id>\", \"Filter by spec ID (full UUID or 8+ char prefix)\")\n .option(\"-p, --page <n>\", \"Page number\", \"1\")\n .option(\"--per-page <n>\", \"Results per page\", \"20\")\n .action(async (cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n\n let path = \"/runs\";\n const query: Record<string, string | number> = {\n page: cmdOpts.page,\n per_page: cmdOpts.perPage,\n };\n\n if (cmdOpts.spec) {\n const fullSpecId = await resolveSpecId(cmdOpts.spec, opts);\n path = `/behavior-specs/${fullSpecId}/runs`;\n }\n\n const { data, meta } = await get<Run[]>(path, query, opts);\n\n if (isJsonMode()) return printJson({ data, meta });\n\n printTable(\n [\"ID\", \"Spec\", \"#\", \"Status\", \"Score\", \"Started\", \"Completed\"],\n data.map((r) => [\n shortId(r.id),\n r._spec_name ? truncate(r._spec_name, 20) : shortId(r.behavior_spec_id),\n String(r.run_number),\n formatStatus(r.status),\n r.eval_summary?.mean_score != null\n ? (r.eval_summary.mean_score * 100).toFixed(1) + \"%\"\n : \"—\",\n formatDate(r.started_at),\n formatDate(r.completed_at),\n ]),\n meta,\n );\n });\n\n runs\n .command(\"get\")\n .description(\"Show run details and eval results\")\n .argument(\"<id>\", \"Run ID (full UUID or 8+ char prefix)\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const fullId = await resolveRunId(id, opts);\n const { data } = await get<Run>(`/runs/${fullId}`, undefined, opts);\n\n if (isJsonMode()) return printJson(data);\n\n printDetail([\n [\"ID\", data.id],\n [\"Spec\", data._spec_name ?? shortId(data.behavior_spec_id)],\n [\"Run #\", String(data.run_number)],\n [\"Status\", formatStatus(data.status)],\n [\"Stage\", formatProgress(data)],\n [\"Message\", data.status_message ?? undefined],\n [\"Score\", data.eval_summary?.mean_score != null\n ? (data.eval_summary.mean_score * 100).toFixed(1) + \"%\"\n : undefined],\n [\"Pass Rate\", data.eval_summary?.pass_rate != null\n ? (data.eval_summary.pass_rate * 100).toFixed(1) + \"%\"\n : undefined],\n [\"Error\", data.error ?? undefined],\n [\"Started\", formatDate(data.started_at)],\n [\"Completed\", formatDate(data.completed_at)],\n [\"Created\", formatDate(data.created_at)],\n ]);\n\n if (data.hyperparameters && Object.keys(data.hyperparameters).length) {\n console.log(\"\\nHyperparameters:\");\n for (const [k, v] of Object.entries(data.hyperparameters)) {\n console.log(` ${k}: ${v}`);\n }\n }\n\n if (data._events?.length) {\n console.log(\"\\nLatest Updates:\");\n for (const event of data._events.slice(-5)) {\n const time = formatDate(event.occurred_at);\n console.log(\n ` ${time} ${formatStatus(event.status)} ${event.label}${event.message ? ` — ${event.message}` : \"\"}`,\n );\n }\n }\n\n if (data._evals?.length) {\n console.log(`\\nEval Results (${data._evals.length}):`);\n printTable(\n [\"#\", \"Passed\", \"Score\", \"Prompt\", \"Latency\"],\n data._evals.map((e, i) => [\n String(i + 1),\n e.passed ? \"✓\" : \"✗\",\n e.score != null ? e.score.toFixed(2) : \"—\",\n truncate(e.prompt, 40),\n e.latency_ms != null ? `${e.latency_ms}ms` : \"—\",\n ]),\n );\n }\n });\n\n runs\n .command(\"start\")\n .description(\"Start a new run for a behaviour spec\")\n .argument(\"<spec-id>\", \"Behaviour spec ID (full UUID or 8+ char prefix)\")\n .option(\"--no-augment\", \"Disable data augmentation\")\n .option(\"--no-llm-judge\", \"Disable Bedrock LLM judging\")\n .option(\"--epochs <n>\", \"Number of training epochs\")\n .option(\"--lr <rate>\", \"Learning rate\")\n .option(\"--batch-size <n>\", \"Batch size\")\n .option(\"--dataset <id>\", \"Dataset ID to use instead of inline spec examples (full UUID or 4+ char prefix)\")\n .option(\"--train-ratio <ratio>\", \"Dataset training split ratio (default: 0.8 when any split ratio is set)\")\n .option(\"--validation-ratio <ratio>\", \"Dataset validation split ratio (default: 0.1 when any split ratio is set)\")\n .option(\"--test-ratio <ratio>\", \"Dataset test split ratio (default: 0.1 when any split ratio is set)\")\n .option(\"--lora-rank <n>\", \"LoRA rank\")\n .option(\"--lora-alpha <n>\", \"LoRA alpha\")\n .action(async (specId: string, cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n const body: Record<string, unknown> = {};\n\n if (cmdOpts.augment === false) body.augment = false;\n if (cmdOpts.dataset) body.dataset_id = await resolveDatasetId(cmdOpts.dataset, opts);\n\n const splitRatioOptions = [\n cmdOpts.trainRatio,\n cmdOpts.validationRatio,\n cmdOpts.testRatio,\n ];\n if (splitRatioOptions.some((value) => value != null)) {\n body.split_ratios = {\n train: cmdOpts.trainRatio != null ? Number(cmdOpts.trainRatio) : 0.8,\n validation:\n cmdOpts.validationRatio != null ? Number(cmdOpts.validationRatio) : 0.1,\n test: cmdOpts.testRatio != null ? Number(cmdOpts.testRatio) : 0.1,\n };\n }\n\n const hp: Record<string, unknown> = {};\n if (cmdOpts.epochs) hp.n_epochs = Number(cmdOpts.epochs);\n if (cmdOpts.lr) hp.learning_rate = Number(cmdOpts.lr);\n if (cmdOpts.batchSize) hp.batch_size = Number(cmdOpts.batchSize);\n if (cmdOpts.loraRank) hp.lora_rank = Number(cmdOpts.loraRank);\n if (cmdOpts.loraAlpha) hp.lora_alpha = Number(cmdOpts.loraAlpha);\n if (cmdOpts.llmJudge === false) body.use_llm_judge = false;\n if (Object.keys(hp).length) body.hyperparameters = hp;\n\n const fullSpecId = await resolveSpecId(specId, opts);\n const { data } = await post<Run>(\n `/behavior-specs/${fullSpecId}/runs`,\n body,\n opts,\n );\n\n if (isJsonMode()) return printJson(data);\n printSuccess(\n `Run #${data.run_number} started (${shortId(data.id)}). ${formatProgress(data) ?? `Status: ${formatStatus(data.status)}`}`,\n );\n });\n\n runs\n .command(\"cancel\")\n .description(\"Cancel a running run\")\n .argument(\"<id>\", \"Run ID (full UUID or 8+ char prefix)\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const fullId = await resolveRunId(id, opts);\n const { data } = await post<Run>(`/runs/${fullId}/cancel`, undefined, opts);\n\n if (isJsonMode()) return printJson(data);\n printSuccess(`Run ${shortId(fullId)} cancelled.`);\n });\n\n runs\n .command(\"watch\")\n .description(\"Watch a run until it completes\")\n .argument(\"<id>\", \"Run ID (full UUID or 8+ char prefix)\")\n .option(\"--interval <ms>\", \"Poll interval in milliseconds\", \"5000\")\n .action(async (id: string, cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n const interval = Number(cmdOpts.interval);\n const fullId = await resolveRunId(id, opts);\n const spinner = ora(`Watching run ${shortId(fullId)}...`).start();\n\n const terminalStates = new Set([\n \"completed\",\n \"failed\",\n \"cancelled\",\n ]);\n\n let run: Run;\n while (true) {\n const { data } = await get<Run>(`/runs/${fullId}`, undefined, opts);\n run = data;\n spinner.text = `Run ${shortId(fullId)} — ${formatProgress(run) ?? formatStatus(run.status)}`;\n\n if (terminalStates.has(run.status)) break;\n await new Promise((r) => setTimeout(r, interval));\n }\n\n spinner.stop();\n\n if (isJsonMode()) return printJson(run);\n\n printDetail([\n [\"Run\", shortId(run.id)],\n [\"Status\", formatStatus(run.status)],\n [\"Stage\", formatProgress(run)],\n [\"Message\", run.status_message ?? undefined],\n [\"Score\", run.eval_summary?.mean_score != null\n ? (run.eval_summary.mean_score * 100).toFixed(1) + \"%\"\n : undefined],\n [\"Error\", run.error ?? undefined],\n [\"Completed\", formatDate(run.completed_at)],\n ]);\n });\n}\n","import { Command } from \"commander\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { get, del, upload, type ClientOpts } from \"../client.js\";\nimport { resolveDatasetId } from \"../resolve.js\";\nimport {\n printTable,\n printDetail,\n printSuccess,\n printJson,\n printError,\n isJsonMode,\n formatDate,\n formatStatus,\n shortId,\n truncate,\n} from \"../output.js\";\n\ninterface Dataset {\n id: string;\n name: string;\n description: string | null;\n storage_path: string;\n file_size_bytes: number;\n row_count: number;\n format: string;\n status: string;\n validation_errors: string[] | null;\n created_at: string;\n updated_at: string;\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction validateDatasetFile(file: string): void {\n const lines = readFileSync(file, \"utf8\").split(/\\r?\\n/);\n const errors: string[] = [];\n let rowCount = 0;\n\n for (const [index, rawLine] of lines.entries()) {\n const line = rawLine.trim();\n if (!line) continue;\n\n rowCount += 1;\n const rowNumber = index + 1;\n let row: unknown;\n\n try {\n row = JSON.parse(line);\n } catch {\n errors.push(`Row ${rowNumber}: invalid JSON`);\n continue;\n }\n\n if (!row || typeof row !== \"object\" || Array.isArray(row)) {\n errors.push(`Row ${rowNumber}: expected an object with \"input\" and \"output\" fields`);\n continue;\n }\n\n const record = row as Record<string, unknown>;\n if (\"messages\" in record && !(\"input\" in record) && !(\"output\" in record)) {\n errors.push(\n `Row ${rowNumber}: found OpenAI SFT-style \"messages\"; Tuned Tensor datasets require flat \"input\" and \"output\" strings`,\n );\n continue;\n }\n\n if (typeof record.input !== \"string\") {\n errors.push(`Row ${rowNumber}: missing string \"input\" field`);\n }\n if (typeof record.output !== \"string\") {\n errors.push(`Row ${rowNumber}: missing string \"output\" field`);\n }\n }\n\n if (rowCount === 0) {\n errors.push(\"File contains no JSONL rows\");\n }\n\n if (errors.length > 0) {\n const preview = errors.slice(0, 5).join(\"\\n\");\n const suffix = errors.length > 5 ? `\\n...and ${errors.length - 5} more error(s)` : \"\";\n throw new Error(\n `Invalid dataset format. Each JSONL row must be {\"input\": \"...\", \"output\": \"...\"}.\\n${preview}${suffix}`,\n );\n }\n}\n\nexport function registerDatasetsCommands(parent: Command) {\n const datasets = parent\n .command(\"datasets\")\n .description(\"Manage datasets\");\n\n datasets\n .command(\"list\")\n .description(\"List datasets\")\n .option(\"-p, --page <n>\", \"Page number\", \"1\")\n .option(\"--per-page <n>\", \"Results per page\", \"20\")\n .action(async (cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n const { data, meta } = await get<Dataset[]>(\n \"/datasets\",\n { page: cmdOpts.page, per_page: cmdOpts.perPage },\n opts,\n );\n\n if (isJsonMode()) return printJson({ data, meta });\n\n printTable(\n [\"ID\", \"Name\", \"Rows\", \"Size\", \"Status\", \"Created\"],\n data.map((d) => [\n shortId(d.id),\n truncate(d.name, 30),\n String(d.row_count),\n formatBytes(d.file_size_bytes),\n formatStatus(d.status),\n formatDate(d.created_at),\n ]),\n meta,\n );\n });\n\n datasets\n .command(\"get\")\n .description(\"Show dataset details\")\n .argument(\"<id>\", \"Dataset ID (full UUID or 4+ char prefix)\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const fullId = await resolveDatasetId(id, opts);\n const { data } = await get<Dataset>(`/datasets/${fullId}`, undefined, opts);\n\n if (isJsonMode()) return printJson(data);\n\n printDetail([\n [\"ID\", data.id],\n [\"Name\", data.name],\n [\"Description\", data.description ?? undefined],\n [\"Format\", data.format],\n [\"Rows\", String(data.row_count)],\n [\"Size\", formatBytes(data.file_size_bytes)],\n [\"Status\", formatStatus(data.status)],\n [\"Created\", formatDate(data.created_at)],\n [\"Updated\", formatDate(data.updated_at)],\n ]);\n\n if (data.validation_errors?.length) {\n console.log(\"\\nValidation Errors:\");\n for (const err of data.validation_errors) {\n console.log(` - ${err}`);\n }\n }\n });\n\n datasets\n .command(\"upload\")\n .description(\"Upload a JSONL dataset file\")\n .argument(\"<file>\", \"Path to JSONL file\")\n .option(\"-n, --name <name>\", \"Dataset name (defaults to filename)\")\n .option(\"-d, --description <desc>\", \"Dataset description\")\n .action(async (file: string, cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n\n if (!existsSync(file)) {\n printError(`File not found: ${file}`);\n process.exit(1);\n }\n\n validateDatasetFile(file);\n\n const fields: Record<string, string> = {\n name: cmdOpts.name || file.split(\"/\").pop()!.replace(/\\.jsonl?$/, \"\"),\n };\n if (cmdOpts.description) fields.description = cmdOpts.description;\n\n const { data } = await upload<Dataset>(\n \"/datasets\",\n file,\n fields,\n opts,\n );\n\n if (isJsonMode()) return printJson(data);\n printSuccess(\n `Dataset uploaded: ${data.name} (${shortId(data.id)}) — ${data.row_count} rows`,\n );\n });\n\n datasets\n .command(\"delete\")\n .description(\"Delete a dataset\")\n .argument(\"<id>\", \"Dataset ID (full UUID or 4+ char prefix)\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const fullId = await resolveDatasetId(id, opts);\n await del(`/datasets/${fullId}`, opts);\n\n if (isJsonMode()) return printJson({ id: fullId, deleted: true });\n printSuccess(`Dataset deleted: ${shortId(fullId)}`);\n });\n}\n","import { Command } from \"commander\";\nimport { get, del, type ClientOpts } from \"../client.js\";\nimport {\n printTable,\n printDetail,\n printSuccess,\n printJson,\n isJsonMode,\n formatDate,\n shortId,\n truncate,\n} from \"../output.js\";\n\ninterface Model {\n id: string;\n name: string;\n provider: string;\n provider_model_id: string;\n base_model: string;\n description: string | null;\n created_at: string;\n}\n\nexport function registerModelsCommands(parent: Command) {\n const models = parent.command(\"models\").description(\"Manage fine-tuned models\");\n\n models\n .command(\"list\")\n .description(\"List fine-tuned models\")\n .option(\"-p, --page <n>\", \"Page number\", \"1\")\n .option(\"--per-page <n>\", \"Results per page\", \"20\")\n .action(async (cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n const { data, meta } = await get<Model[]>(\n \"/models\",\n { page: cmdOpts.page, per_page: cmdOpts.perPage },\n opts,\n );\n\n if (isJsonMode()) return printJson({ data, meta });\n\n printTable(\n [\"ID\", \"Name\", \"Base Model\", \"Provider\", \"Created\"],\n data.map((m) => [\n shortId(m.id),\n truncate(m.name, 30),\n m.base_model.split(\"/\").pop() || m.base_model,\n m.provider,\n formatDate(m.created_at),\n ]),\n meta,\n );\n });\n\n models\n .command(\"get\")\n .description(\"Show model details\")\n .argument(\"<id>\", \"Model ID\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const { data } = await get<Model>(`/models/${id}`, undefined, opts);\n\n if (isJsonMode()) return printJson(data);\n\n printDetail([\n [\"ID\", data.id],\n [\"Name\", data.name],\n [\"Base Model\", data.base_model],\n [\"Provider\", data.provider],\n [\"Provider Model\", data.provider_model_id],\n [\"Description\", data.description ?? undefined],\n [\"Created\", formatDate(data.created_at)],\n ]);\n });\n\n models\n .command(\"delete\")\n .description(\"Delete a model\")\n .argument(\"<id>\", \"Model ID\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n await del(`/models/${id}`, opts);\n\n if (isJsonMode()) return printJson({ id, deleted: true });\n printSuccess(`Model deleted: ${shortId(id)}`);\n });\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { get, type ClientOpts } from \"../client.js\";\nimport {\n printDetail,\n printJson,\n printTable,\n isJsonMode,\n formatDate,\n formatStatus,\n shortId,\n} from \"../output.js\";\n\ninterface BalanceResponse {\n balance_cents: number;\n reserved_cents: number;\n available_cents: number;\n lifetime_topup_cents: number;\n}\n\ntype CreditKind =\n | \"signup_bonus\"\n | \"topup\"\n | \"debit_run\"\n | \"debit_autotune\"\n | \"refund\"\n | \"adjustment\";\n\ninterface LedgerRow {\n id: string;\n kind: CreditKind;\n amount_cents: number;\n balance_after_cents: number;\n reference_id: string | null;\n created_at: string;\n}\n\nconst KIND_LABELS: Record<CreditKind, string> = {\n signup_bonus: \"Signup bonus\",\n topup: \"Top-up\",\n debit_run: \"Run\",\n debit_autotune: \"Auto-tune\",\n refund: \"Refund\",\n adjustment: \"Adjustment\",\n};\n\nfunction formatCents(cents: number): string {\n const sign = cents < 0 ? \"-\" : \"\";\n const abs = Math.abs(cents);\n return `${sign}$${(abs / 100).toFixed(2)}`;\n}\n\nfunction formatSigned(cents: number): string {\n if (cents > 0) return chalk.green(`+${formatCents(cents)}`);\n if (cents < 0) return chalk.red(formatCents(cents));\n return formatCents(cents);\n}\n\nexport function registerBalanceCommands(parent: Command) {\n parent\n .command(\"balance\")\n .description(\"Show available credits, held credits, and recent transactions\")\n .option(\"-n, --limit <n>\", \"Number of transactions to show (default 10)\", \"10\")\n .action(async (options) => {\n const opts = parent.opts() as ClientOpts;\n const limit = Number(options.limit) || 10;\n\n const [{ data: balance }, { data: transactions }] = await Promise.all([\n get<BalanceResponse>(\"/billing/balance\", undefined, opts),\n get<LedgerRow[]>(\"/billing/transactions\", { per_page: limit }, opts),\n ]);\n\n if (isJsonMode()) {\n return printJson({ balance, transactions });\n }\n\n const lowBalance = balance.available_cents < 100;\n const availableLine = lowBalance\n ? chalk.red(formatCents(balance.available_cents)) + chalk.dim(\" (low)\")\n : chalk.bold.green(formatCents(balance.available_cents));\n\n printDetail([\n [\"Available\", availableLine],\n [\"Total balance\", formatCents(balance.balance_cents)],\n [\"On hold\", formatCents(balance.reserved_cents)],\n [\"Lifetime top-ups\", formatCents(balance.lifetime_topup_cents)],\n ]);\n\n if (transactions && transactions.length > 0) {\n console.log(`\\n${chalk.bold(\"Recent transactions\")}`);\n printTable(\n [\"Date\", \"Type\", \"Amount\", \"Balance\", \"Reference\"],\n transactions.map((row) => [\n formatDate(row.created_at),\n KIND_LABELS[row.kind] ?? row.kind,\n formatSigned(row.amount_cents),\n formatCents(row.balance_after_cents),\n row.reference_id ? shortId(row.reference_id) : chalk.dim(\"—\"),\n ])\n );\n } else {\n console.log(\n `\\n${chalk.dim(\"No transactions yet — run `tt topup` to add credits.\")}`\n );\n }\n\n if (lowBalance) {\n console.log(\n `\\n${formatStatus(\"preparing\")} ${chalk.yellow(\n \"Run `tt topup` to add more available credits before starting a run.\"\n )}`\n );\n }\n });\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport open from \"open\";\nimport { post, type ClientOpts } from \"../client.js\";\nimport { printJson, isJsonMode, printSuccess } from \"../output.js\";\n\ninterface TopupResponse {\n checkout_url: string;\n session_id: string;\n}\n\nconst PRESETS_USD = [10, 25, 50, 100];\nconst MIN_USD = 5;\nconst MAX_USD = 10000;\n\nfunction parseAmount(input: string | undefined): number | null {\n if (!input) return null;\n const cleaned = input.replace(/^\\$/, \"\").trim();\n const num = Number(cleaned);\n if (!Number.isFinite(num) || num <= 0) return null;\n return num;\n}\n\nasync function readLine(prompt: string): Promise<string> {\n const readline = await import(\"node:readline/promises\");\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n try {\n return (await rl.question(prompt)).trim();\n } finally {\n rl.close();\n }\n}\n\nexport function registerTopupCommands(parent: Command) {\n parent\n .command(\"topup\")\n .description(\"Add prepaid credits via Stripe Checkout\")\n .option(\"-a, --amount <usd>\", \"Amount in USD (e.g. 25)\")\n .option(\"--no-open\", \"Print checkout URL instead of opening the browser\")\n .action(async (options) => {\n const opts = parent.opts() as ClientOpts;\n\n let amountUsd: number | null;\n\n if (options.amount !== undefined) {\n amountUsd = parseAmount(options.amount);\n if (amountUsd === null) {\n throw new Error(\"Invalid amount\");\n }\n } else {\n if (isJsonMode()) {\n throw new Error(\n \"amount is required in --json mode (use --amount <usd>)\"\n );\n }\n console.log(chalk.bold(\"Add credits via Stripe Checkout\"));\n console.log(\n chalk.dim(\n `Quick picks: ${PRESETS_USD.map((n) => `$${n}`).join(\", \")}`\n )\n );\n const input = await readLine(`Amount in USD (min $${MIN_USD}): `);\n amountUsd = parseAmount(input);\n if (amountUsd === null) {\n throw new Error(\"Invalid amount\");\n }\n }\n\n if (amountUsd < MIN_USD) {\n throw new Error(`Minimum top-up is $${MIN_USD}`);\n }\n if (amountUsd > MAX_USD) {\n throw new Error(`Maximum top-up is $${MAX_USD}`);\n }\n\n const amountCents = Math.round(amountUsd * 100);\n\n const { data } = await post<TopupResponse>(\n \"/billing/topup\",\n { amount_cents: amountCents },\n opts\n );\n\n if (isJsonMode()) {\n return printJson(data);\n }\n\n const url = data.checkout_url;\n console.log(\n `${chalk.bold(\"Checkout URL:\")} ${chalk.cyan(url)}\\n` +\n chalk.dim(\"Complete the payment to credit your account.\")\n );\n\n if (options.open !== false) {\n try {\n await open(url);\n printSuccess(\"Opened Stripe Checkout in your browser.\");\n } catch {\n console.log(\n chalk.yellow(\n \"Could not open browser automatically — copy the URL above.\"\n )\n );\n }\n }\n });\n}\n","import { Command } from \"commander\";\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { printSuccess, printError, printWarning } from \"../output.js\";\nimport type { LocalSpec } from \"../eval/types.js\";\nimport { canonicalizeBaseModel } from \"../base-models.js\";\n\nconst DEFAULT_SPEC_FILE = \"tunedtensor.json\";\n\nconst SCAFFOLD: LocalSpec = {\n name: \"My Agent\",\n description: \"\",\n base_model: \"Qwen/Qwen3.5-2B\",\n system_prompt: \"You are a helpful assistant.\",\n guidelines: [],\n constraints: [],\n examples: [\n { input: \"Hello\", output: \"Hi! How can I help you today?\" },\n ],\n eval_cases: [],\n};\n\nexport function registerInitCommand(parent: Command) {\n parent\n .command(\"init\")\n .description(\"Create a local behaviour spec file\")\n .option(\"-n, --name <name>\", \"Spec name\")\n .option(\"--model <model>\", \"Base model ID\")\n .option(\"-f, --file <path>\", \"Output file path\", DEFAULT_SPEC_FILE)\n .action(async (cmdOpts) => {\n const filePath = resolve(cmdOpts.file);\n\n if (existsSync(filePath)) {\n printWarning(`${cmdOpts.file} already exists. Use tt eval to run evals or edit it directly.`);\n return;\n }\n\n const spec: LocalSpec = { ...SCAFFOLD };\n if (cmdOpts.name) spec.name = cmdOpts.name;\n if (cmdOpts.model) spec.base_model = canonicalizeBaseModel(cmdOpts.model);\n\n writeFileSync(filePath, JSON.stringify(spec, null, 2) + \"\\n\");\n printSuccess(`Created ${cmdOpts.file}`);\n console.log(\"\\nNext steps:\");\n console.log(\" 1. Edit the spec: system_prompt, guidelines, examples\");\n console.log(\" 2. Run evals: tt eval --model <model-id>\");\n console.log(\" 3. Push to remote: tt push\");\n });\n}\n\nexport function loadSpec(filePath?: string): LocalSpec {\n const resolved = resolve(filePath || DEFAULT_SPEC_FILE);\n if (!existsSync(resolved)) {\n printError(\n `Spec file not found: ${filePath || DEFAULT_SPEC_FILE}\\nRun \\`tt init\\` to create one.`,\n );\n process.exit(1);\n }\n\n const raw = JSON.parse(readFileSync(resolved, \"utf-8\"));\n return raw as LocalSpec;\n}\n\nexport { DEFAULT_SPEC_FILE };\n","import { Command } from \"commander\";\nimport ora from \"ora\";\nimport chalk from \"chalk\";\nimport {\n printTable,\n printJson,\n isJsonMode,\n printWarning,\n truncate,\n} from \"../output.js\";\nimport type { ClientOpts } from \"../client.js\";\nimport { loadSpec, DEFAULT_SPEC_FILE } from \"./init.js\";\nimport { runEvals } from \"../eval/runner.js\";\nimport type { EvalSummary, ValidationCheck } from \"../eval/types.js\";\n\nexport function registerEvalCommand(parent: Command) {\n parent\n .command(\"eval\")\n .description(\"Evaluate a model against a behaviour spec using rule-based assertions\")\n .requiredOption(\"-m, --model <model>\", \"Model ID to evaluate (base or fine-tuned)\")\n .option(\"-f, --file <path>\", \"Spec file path\", DEFAULT_SPEC_FILE)\n .action(async (cmdOpts) => {\n const spec = loadSpec(cmdOpts.file);\n const clientOpts = parent.opts() as ClientOpts;\n\n if (!isJsonMode()) {\n console.log(chalk.dim(`\\nSpec: ${cmdOpts.file} | Model: ${cmdOpts.model}\\n`));\n }\n\n const spinner = ora(\"Running evals...\").start();\n\n const summary = await runEvals(spec, cmdOpts.model, {\n clientOpts,\n onProgress: (done, total) => { spinner.text = `Running evals... ${done}/${total}`; },\n });\n\n spinner.stop();\n\n if (isJsonMode()) return printJson(summary);\n\n printValidation(summary.spec_validation.checks);\n console.log();\n printResults(summary);\n });\n}\n\nfunction printValidation(checks: ValidationCheck[]) {\n console.log(chalk.bold(\"Spec Validation\"));\n for (const check of checks) {\n const icon = check.passed ? chalk.green(\"✓\") : chalk.red(\"✗\");\n const msg = check.message\n ? chalk.dim(` — ${check.message}`)\n : \"\";\n console.log(` ${icon} ${check.name}${msg}`);\n }\n}\n\nfunction printResults(summary: EvalSummary) {\n if (!summary.results.length) {\n printWarning(\"No eval cases to run. Add examples or eval_cases to your spec.\");\n return;\n }\n\n console.log(chalk.bold(`Eval Results (${summary.total}):`));\n\n printTable(\n [\"#\", \"Passed\", \"Input\", \"Latency\"],\n summary.results.map((r, i) => [\n String(i + 1),\n r.passed ? chalk.green(\"✓\") : chalk.red(\"✗\"),\n truncate(r.input, 40),\n r.latency_ms != null ? `${r.latency_ms}ms` : \"—\",\n ]),\n );\n\n console.log();\n\n const passStr = (summary.pass_rate * 100).toFixed(1) + \"%\";\n const color = summary.pass_rate >= 0.8\n ? chalk.green\n : summary.pass_rate >= 0.5\n ? chalk.yellow\n : chalk.red;\n\n console.log(\n ` Pass Rate: ${color(chalk.bold(passStr))} (${summary.passed}/${summary.total} passed)`,\n );\n\n const failedResults = summary.results.filter((r) => !r.passed);\n if (failedResults.length) {\n console.log(chalk.dim(`\\nFailed eval details:`));\n for (const r of failedResults) {\n console.log(chalk.dim(` • \"${truncate(r.input, 50)}\":`));\n if (r.actual) {\n console.log(chalk.dim(` Response: ${truncate(r.actual, 80)}`));\n }\n for (const a of r.assertions.filter((a) => !a.passed)) {\n console.log(chalk.red(` ✗ ${a.assertion}: ${a.message}`));\n }\n }\n }\n}\n","import type {\n AssertionResult,\n LocalSpec,\n ValidationCheck,\n ValidationResult,\n} from \"./types.js\";\n\nexport function validateSpec(spec: LocalSpec): ValidationResult {\n const checks: ValidationCheck[] = [];\n\n checks.push({\n name: \"Has name\",\n passed: Boolean(spec.name?.trim()),\n message: spec.name?.trim() ? undefined : \"Spec is missing a name\",\n });\n\n checks.push({\n name: \"Has system prompt\",\n passed: Boolean(spec.system_prompt?.trim()),\n message: spec.system_prompt?.trim()\n ? undefined\n : \"Spec is missing a system_prompt\",\n });\n\n checks.push({\n name: \"Has base model\",\n passed: Boolean(spec.base_model?.trim()),\n message: spec.base_model?.trim()\n ? undefined\n : \"Spec is missing a base_model\",\n });\n\n const exCount = spec.examples?.length ?? 0;\n checks.push({\n name: \"Has examples\",\n passed: exCount > 0,\n message: exCount > 0 ? `${exCount} example(s)` : \"Add at least one example\",\n });\n\n checks.push({\n name: \"Has guidelines\",\n passed: (spec.guidelines?.length ?? 0) > 0,\n message:\n (spec.guidelines?.length ?? 0) > 0\n ? undefined\n : \"Consider adding guidelines for better eval coverage\",\n });\n\n if (spec.constraints?.length && spec.examples?.length) {\n const violations = checkExamplesAgainstConstraints(spec);\n checks.push({\n name: \"Examples satisfy constraints\",\n passed: violations.length === 0,\n message:\n violations.length === 0\n ? undefined\n : violations.join(\"; \"),\n });\n }\n\n return {\n valid: checks.every((c) => c.passed),\n checks,\n };\n}\n\nfunction checkExamplesAgainstConstraints(spec: LocalSpec): string[] {\n const violations: string[] = [];\n for (const [i, ex] of spec.examples.entries()) {\n for (const constraint of spec.constraints) {\n const result = evaluateConstraint(ex.output, constraint);\n if (!result.passed) {\n violations.push(`Example ${i + 1} violates \"${constraint}\": ${result.message}`);\n }\n }\n }\n return violations;\n}\n\nfunction evaluateConstraint(\n text: string,\n constraint: string,\n): { passed: boolean; message?: string } {\n const lower = constraint.toLowerCase();\n\n const neverMatch = lower.match(/^never (?:share|mention|include|reveal|use|say|output|return|give|provide|show|disclose|expose)\\s+(.+)/);\n if (neverMatch) {\n const forbidden = neverMatch[1].replace(/['\"]/g, \"\").trim();\n if (text.toLowerCase().includes(forbidden.toLowerCase())) {\n return { passed: false, message: `Output contains \"${forbidden}\"` };\n }\n return { passed: true };\n }\n\n const alwaysMatch = lower.match(/^always (?:include|use|start with|end with|contain|respond in|reply in)\\s+(.+)/);\n if (alwaysMatch) {\n const required = alwaysMatch[1].replace(/['\"]/g, \"\").trim();\n if (!text.toLowerCase().includes(required.toLowerCase())) {\n return { passed: false, message: `Output missing \"${required}\"` };\n }\n return { passed: true };\n }\n\n return {\n passed: true,\n message: `Constraint not enforceable by rules: \"${constraint}\" (will be checked by LLM judge if a provider is configured)`,\n };\n}\n\nexport function runAssertions(\n text: string,\n assertions: string[],\n): AssertionResult[] {\n return assertions.map((assertion) => runSingleAssertion(text, assertion));\n}\n\nfunction runSingleAssertion(text: string, assertion: string): AssertionResult {\n const [type, ...rest] = assertion.split(\":\");\n const value = rest.join(\":\");\n\n switch (type) {\n case \"contains\":\n return {\n assertion,\n passed: text.includes(value),\n message: text.includes(value)\n ? undefined\n : `Expected output to contain \"${value}\"`,\n };\n\n case \"not-contains\":\n return {\n assertion,\n passed: !text.includes(value),\n message: !text.includes(value)\n ? undefined\n : `Expected output to not contain \"${value}\"`,\n };\n\n case \"matches\": {\n const re = new RegExp(value);\n const match = re.test(text);\n return {\n assertion,\n passed: match,\n message: match ? undefined : `Output did not match pattern /${value}/`,\n };\n }\n\n case \"max-length\": {\n const max = Number(value);\n return {\n assertion,\n passed: text.length <= max,\n message:\n text.length <= max\n ? undefined\n : `Output length ${text.length} exceeds max ${max}`,\n };\n }\n\n case \"min-length\": {\n const min = Number(value);\n return {\n assertion,\n passed: text.length >= min,\n message:\n text.length >= min\n ? undefined\n : `Output length ${text.length} below min ${min}`,\n };\n }\n\n case \"is-json\": {\n let valid = false;\n try {\n JSON.parse(text);\n valid = true;\n } catch {}\n return {\n assertion,\n passed: valid,\n message: valid ? undefined : \"Output is not valid JSON\",\n };\n }\n\n default:\n return {\n assertion,\n passed: true,\n message: `Unknown assertion type: ${type} (skipped)`,\n };\n }\n}\n\nexport function checkConstraints(\n text: string,\n constraints: string[],\n): AssertionResult[] {\n return constraints.map((constraint) => {\n const result = evaluateConstraint(text, constraint);\n return {\n assertion: `constraint: ${constraint}`,\n passed: result.passed,\n message: result.message,\n };\n });\n}\n","import type {\n EvalCase,\n EvalResult,\n EvalSummary,\n LocalSpec,\n PlaygroundResponse,\n} from \"./types.js\";\nimport type { ClientOpts } from \"../client.js\";\nimport { post } from \"../client.js\";\nimport { validateSpec } from \"./rules.js\";\nimport { runAssertions, checkConstraints } from \"./rules.js\";\n\nfunction buildEvalCases(spec: LocalSpec): EvalCase[] {\n if (spec.eval_cases?.length) return spec.eval_cases;\n\n return spec.examples.map((ex) => ({\n input: ex.input,\n expected: ex.output,\n }));\n}\n\nexport async function runEvals(\n spec: LocalSpec,\n model: string,\n opts?: {\n clientOpts?: ClientOpts;\n onProgress?: (completed: number, total: number) => void;\n },\n): Promise<EvalSummary> {\n const specValidation = validateSpec(spec);\n const cases = buildEvalCases(spec);\n const results: EvalResult[] = [];\n\n for (const [i, evalCase] of cases.entries()) {\n const result = await runSingleEval(spec, evalCase, model, opts?.clientOpts);\n results.push(result);\n opts?.onProgress?.(i + 1, cases.length);\n }\n\n return {\n total: results.length,\n passed: results.filter((r) => r.passed).length,\n failed: results.filter((r) => !r.passed).length,\n pass_rate: results.length ? results.filter((r) => r.passed).length / results.length : 0,\n model,\n results,\n spec_validation: specValidation,\n };\n}\n\nasync function runSingleEval(\n spec: LocalSpec,\n evalCase: EvalCase,\n model: string,\n clientOpts?: ClientOpts,\n): Promise<EvalResult> {\n try {\n const { data } = await post<PlaygroundResponse>(\n \"/playground/completions\",\n {\n model,\n messages: [\n { role: \"system\", content: spec.system_prompt },\n { role: \"user\", content: evalCase.input },\n ],\n temperature: 0,\n max_tokens: 2048,\n },\n clientOpts,\n );\n\n const assertions = [\n ...runAssertions(data.content, evalCase.assert ?? []),\n ...checkConstraints(data.content, spec.constraints),\n ];\n\n return {\n input: evalCase.input,\n expected: evalCase.expected ?? null,\n actual: data.content,\n passed: assertions.every((a) => a.passed),\n latency_ms: data.latency_ms,\n assertions,\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n input: evalCase.input,\n expected: evalCase.expected ?? null,\n actual: null,\n passed: false,\n latency_ms: null,\n assertions: [{ assertion: \"model-call\", passed: false, message: msg }],\n };\n }\n}\n","import { Command } from \"commander\";\nimport { readFileSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { post, put, type ClientOpts } from \"../client.js\";\nimport { printSuccess, printJson, isJsonMode, shortId } from \"../output.js\";\nimport { loadSpec, DEFAULT_SPEC_FILE } from \"./init.js\";\nimport { canonicalizeSpecBaseModel } from \"../base-models.js\";\n\ninterface RemoteSpec {\n id: string;\n name: string;\n [key: string]: unknown;\n}\n\nexport function registerPushCommand(parent: Command) {\n parent\n .command(\"push\")\n .description(\"Push local spec to the Tuned Tensor API\")\n .option(\"-f, --file <path>\", \"Spec file path\", DEFAULT_SPEC_FILE)\n .action(async (cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n const filePath = resolve(cmdOpts.file);\n const spec = loadSpec(cmdOpts.file);\n\n const { id, eval_cases, ...rawBody } = spec as unknown as Record<string, unknown>;\n const body = canonicalizeSpecBaseModel(rawBody);\n\n let data: RemoteSpec;\n\n if (id) {\n const res = await put<RemoteSpec>(`/behavior-specs/${id}`, body, opts);\n data = res.data;\n } else {\n const res = await post<RemoteSpec>(\"/behavior-specs\", body, opts);\n data = res.data;\n\n const raw = JSON.parse(readFileSync(filePath, \"utf-8\"));\n raw.id = data.id;\n writeFileSync(filePath, JSON.stringify(raw, null, 2) + \"\\n\");\n }\n\n if (isJsonMode()) return printJson(data);\n printSuccess(\n `Spec ${id ? \"updated\" : \"created\"}: ${data.name} (${shortId(data.id)})`,\n );\n });\n}\n"],"mappings":"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","names":["readFileSync","readFileSync","chalk","readFileSync","readFileSync","existsSync","readFileSync","readFileSync","existsSync","chalk","chalk","chalk","chalk","existsSync","readFileSync","writeFileSync","existsSync","writeFileSync","readFileSync","ora","chalk","chalk","ora","a","readFileSync","writeFileSync","resolve","resolve","readFileSync","writeFileSync"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/output.ts","../src/client.ts","../src/config.ts","../src/commands/auth.ts","../src/commands/specs.ts","../src/resolve.ts","../src/base-models.ts","../src/commands/runs.ts","../src/commands/datasets.ts","../src/commands/models.ts","../src/commands/balance.ts","../src/commands/topup.ts","../src/commands/init.ts","../src/commands/eval.ts","../src/eval/rules.ts","../src/commands/push.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { setJsonMode, reportError } from \"./output.js\";\nimport { registerAuthCommands } from \"./commands/auth.js\";\nimport { registerSpecsCommands } from \"./commands/specs.js\";\nimport { registerRunsCommands } from \"./commands/runs.js\";\nimport { registerDatasetsCommands } from \"./commands/datasets.js\";\nimport { registerModelsCommands } from \"./commands/models.js\";\n\nimport { registerBalanceCommands } from \"./commands/balance.js\";\nimport { registerTopupCommands } from \"./commands/topup.js\";\nimport { registerInitCommand } from \"./commands/init.js\";\nimport { registerEvalCommand } from \"./commands/eval.js\";\nimport { registerPushCommand } from \"./commands/push.js\";\n\ndeclare const __TT_VERSION__: string;\n\nconst program = new Command();\n\nprogram\n .name(\"tt\")\n .description(\"Tuned Tensor CLI — fine-tune and evaluate LLMs\")\n .version(__TT_VERSION__)\n .option(\"-k, --api-key <key>\", \"API key (overrides stored key)\")\n .option(\n \"-u, --base-url <url>\",\n \"API base URL (default: https://tunedtensor.com)\",\n )\n .option(\"--json\", \"Output raw JSON\")\n .option(\"--no-color\", \"Disable colors\")\n .hook(\"preAction\", (_thisCommand, actionCommand) => {\n const rootOpts = program.opts();\n if (rootOpts.json) setJsonMode(true);\n if (rootOpts.color === false) {\n process.env.FORCE_COLOR = \"0\";\n }\n });\n\nregisterAuthCommands(program);\nregisterSpecsCommands(program);\nregisterRunsCommands(program);\nregisterDatasetsCommands(program);\nregisterModelsCommands(program);\n\nregisterBalanceCommands(program);\nregisterTopupCommands(program);\nregisterInitCommand(program);\nregisterEvalCommand(program);\nregisterPushCommand(program);\n\n// Honor --json even when parsing fails before the preAction hook runs\n// (e.g. on unknown commands). Cheap argv sniff is fine here.\nif (process.argv.includes(\"--json\")) setJsonMode(true);\n\nprogram.parseAsync().catch((err) => {\n reportError(err);\n process.exit(1);\n});\n","import chalk from \"chalk\";\nimport Table from \"cli-table3\";\nimport { ApiError } from \"./client.js\";\n\nlet jsonMode = false;\n\nexport function setJsonMode(enabled: boolean) {\n jsonMode = enabled;\n}\n\nexport function isJsonMode(): boolean {\n return jsonMode;\n}\n\nexport function printJson(data: unknown) {\n console.log(JSON.stringify(data, null, 2));\n}\n\nexport function printTable(\n headers: string[],\n rows: string[][],\n meta?: { page: number; per_page: number; total: number },\n) {\n const table = new Table({\n head: headers.map((h) => chalk.bold.cyan(h)),\n style: { head: [], border: [] },\n });\n for (const row of rows) {\n table.push(row);\n }\n console.log(table.toString());\n\n if (meta) {\n const totalPages = Math.ceil(meta.total / meta.per_page);\n console.log(\n chalk.dim(\n `\\nPage ${meta.page}/${totalPages} (${meta.total} total)`,\n ),\n );\n }\n}\n\nexport function printDetail(fields: [string, string | undefined][]) {\n const maxLabel = Math.max(...fields.map(([l]) => l.length));\n for (const [label, value] of fields) {\n const paddedLabel = label.padEnd(maxLabel);\n console.log(`${chalk.bold.cyan(paddedLabel)} ${value ?? chalk.dim(\"—\")}`);\n }\n}\n\nexport function printSuccess(message: string) {\n console.log(chalk.green(\"✓\") + \" \" + message);\n}\n\nexport function printWarning(message: string) {\n console.log(chalk.yellow(\"!\") + \" \" + message);\n}\n\nexport function printError(message: string) {\n console.error(chalk.red(\"✗\") + \" \" + message);\n}\n\nexport function reportError(err: unknown): void {\n const isApi = err instanceof ApiError;\n const message = (err as Error)?.message || String(err);\n\n if (jsonMode) {\n printJson({\n error: {\n status: isApi ? err.status : null,\n code: isApi ? err.code : \"CLI_ERROR\",\n message,\n },\n });\n } else if (isApi) {\n printError(`[${err.status}] ${message}`);\n } else {\n printError(message);\n }\n}\n\nexport function formatDate(iso?: string | null): string {\n if (!iso) return \"—\";\n return new Date(iso).toLocaleString();\n}\n\nexport function formatStatus(status: string): string {\n const map: Record<string, (s: string) => string> = {\n completed: chalk.green,\n running: chalk.blue,\n training: chalk.blue,\n evaluating: chalk.blue,\n preparing: chalk.yellow,\n pending: chalk.yellow,\n uploading: chalk.yellow,\n failed: chalk.red,\n cancelled: chalk.dim,\n validated: chalk.green,\n invalid: chalk.red,\n };\n const colorFn = map[status] || chalk.white;\n return colorFn(status);\n}\n\nexport function truncate(str: string, max: number): string {\n if (str.length <= max) return str;\n return str.slice(0, max - 1) + \"…\";\n}\n\nexport function shortId(id: string): string {\n return id.slice(0, 8);\n}\n","import { readFileSync, statSync } from \"node:fs\";\nimport { basename } from \"node:path\";\nimport { getApiKey, getBaseUrl } from \"./config.js\";\n\nexport interface ApiResponse<T> {\n data: T;\n meta?: { page: number; per_page: number; total: number };\n}\n\nexport interface ApiErrorBody {\n error: { code: string; message: string };\n}\n\nexport class ApiError extends Error {\n constructor(\n public status: number,\n public code: string,\n message: string,\n ) {\n super(message);\n this.name = \"ApiError\";\n }\n}\n\nexport interface ClientOpts {\n apiKey?: string;\n baseUrl?: string;\n}\n\nfunction resolveKey(opts?: ClientOpts): string {\n const key = getApiKey(opts);\n if (!key) {\n throw new ApiError(\n 401,\n \"NO_API_KEY\",\n \"No API key found. Run `tt auth login` or set TUNED_TENSOR_API_KEY.\",\n );\n }\n return key;\n}\n\nfunction buildUrl(\n path: string,\n query?: Record<string, string | number | undefined>,\n opts?: ClientOpts,\n): string {\n const base = getBaseUrl(opts);\n const url = new URL(`/api/v1${path}`, base);\n if (query) {\n for (const [k, v] of Object.entries(query)) {\n if (v !== undefined) url.searchParams.set(k, String(v));\n }\n }\n return url.toString();\n}\n\nasync function request<T>(\n method: string,\n path: string,\n options: {\n query?: Record<string, string | number | undefined>;\n body?: unknown;\n opts?: ClientOpts;\n } = {},\n): Promise<ApiResponse<T>> {\n const key = resolveKey(options.opts);\n const url = buildUrl(path, options.query, options.opts);\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${key}`,\n };\n\n let bodyPayload: string | undefined;\n if (options.body) {\n headers[\"Content-Type\"] = \"application/json\";\n bodyPayload = JSON.stringify(options.body);\n }\n\n const res = await fetch(url, { method, headers, body: bodyPayload });\n\n if (!res.ok) {\n let errBody: ApiErrorBody;\n try {\n errBody = (await res.json()) as ApiErrorBody;\n } catch {\n throw new ApiError(res.status, \"UNKNOWN\", res.statusText);\n }\n throw new ApiError(\n res.status,\n errBody.error?.code || \"UNKNOWN\",\n errBody.error?.message || res.statusText,\n );\n }\n\n if (res.status === 204) return { data: null as T };\n return (await res.json()) as ApiResponse<T>;\n}\n\nexport function get<T>(\n path: string,\n query?: Record<string, string | number | undefined>,\n opts?: ClientOpts,\n) {\n return request<T>(\"GET\", path, { query, opts });\n}\n\nexport function post<T>(\n path: string,\n body?: unknown,\n opts?: ClientOpts,\n) {\n return request<T>(\"POST\", path, { body, opts });\n}\n\nexport function put<T>(\n path: string,\n body?: unknown,\n opts?: ClientOpts,\n) {\n return request<T>(\"PUT\", path, { body, opts });\n}\n\nexport function patch<T>(\n path: string,\n body?: unknown,\n opts?: ClientOpts,\n) {\n return request<T>(\"PATCH\", path, { body, opts });\n}\n\nexport function del<T>(path: string, opts?: ClientOpts) {\n return request<T>(\"DELETE\", path, { opts });\n}\n\nexport async function upload<T>(\n path: string,\n filePath: string,\n fields: Record<string, string>,\n opts?: ClientOpts,\n): Promise<ApiResponse<T>> {\n const key = resolveKey(opts);\n const url = buildUrl(path, undefined, opts);\n\n const form = new FormData();\n for (const [k, v] of Object.entries(fields)) {\n form.append(k, v);\n }\n\n const fileBytes = readFileSync(filePath);\n const fileSize = statSync(filePath).size;\n const blob = new Blob([fileBytes], { type: \"application/jsonl\" });\n form.append(\"file\", blob, basename(filePath));\n\n const res = await fetch(url, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${key}` },\n body: form,\n });\n\n if (!res.ok) {\n let errBody: ApiErrorBody;\n try {\n errBody = (await res.json()) as ApiErrorBody;\n } catch {\n throw new ApiError(res.status, \"UNKNOWN\", res.statusText);\n }\n throw new ApiError(\n res.status,\n errBody.error?.code || \"UNKNOWN\",\n errBody.error?.message || res.statusText,\n );\n }\n\n return (await res.json()) as ApiResponse<T>;\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport interface Config {\n api_key?: string;\n base_url?: string;\n}\n\nconst CONFIG_DIR_NAME = \"tuned-tensor\";\nconst CONFIG_FILE_NAME = \"config.json\";\n\nfunction getConfigDir(): string {\n const xdg = process.env.XDG_CONFIG_HOME;\n const base = xdg || join(homedir(), \".config\");\n return join(base, CONFIG_DIR_NAME);\n}\n\nfunction getConfigPath(): string {\n return join(getConfigDir(), CONFIG_FILE_NAME);\n}\n\nexport function readConfig(): Config {\n const path = getConfigPath();\n if (!existsSync(path)) return {};\n try {\n return JSON.parse(readFileSync(path, \"utf-8\"));\n } catch {\n return {};\n }\n}\n\nexport function writeConfig(config: Config): void {\n const dir = getConfigDir();\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(getConfigPath(), JSON.stringify(config, null, 2) + \"\\n\");\n}\n\nexport function updateConfig(partial: Partial<Config>): void {\n const current = readConfig();\n writeConfig({ ...current, ...partial });\n}\n\nexport function clearConfig(): void {\n const path = getConfigPath();\n if (existsSync(path)) writeFileSync(path, \"{}\\n\");\n}\n\nexport const DEFAULT_BASE_URL = \"https://tunedtensor.com\";\n\nexport function getBaseUrl(opts?: { baseUrl?: string }): string {\n return opts?.baseUrl || process.env.TUNED_TENSOR_URL || readConfig().base_url || DEFAULT_BASE_URL;\n}\n\nexport function getApiKey(opts?: { apiKey?: string }): string | undefined {\n return opts?.apiKey || process.env.TUNED_TENSOR_API_KEY || readConfig().api_key;\n}\n","import { Command } from \"commander\";\nimport { createInterface } from \"node:readline/promises\";\nimport { stdin, stdout } from \"node:process\";\nimport {\n readConfig,\n updateConfig,\n clearConfig,\n getApiKey,\n getBaseUrl,\n DEFAULT_BASE_URL,\n} from \"../config.js\";\nimport {\n printSuccess,\n printDetail,\n printError,\n printWarning,\n isJsonMode,\n printJson,\n} from \"../output.js\";\nimport chalk from \"chalk\";\n\nexport function registerAuthCommands(parent: Command) {\n const auth = parent.command(\"auth\").description(\"Manage authentication\");\n\n auth\n .command(\"login\")\n .description(\"Store an API key for authentication\")\n .argument(\"[key]\", \"API key (tt_...). If omitted, you will be prompted.\")\n .action(async (key?: string) => {\n let apiKey = key;\n\n if (!apiKey) {\n const settingsUrl = `${DEFAULT_BASE_URL}/dashboard/settings`;\n console.log();\n console.log(\n ` To get your API key, go to ${chalk.bold(\"Settings → API Keys\")} in the Tuned Tensor dashboard:`,\n );\n console.log(` ${chalk.cyan.underline(settingsUrl)}`);\n console.log();\n\n const rl = createInterface({ input: stdin, output: stdout });\n apiKey = await rl.question(\"Enter your API key (tt_...): \");\n rl.close();\n }\n\n apiKey = apiKey.trim();\n\n if (!apiKey.startsWith(\"tt_\") || apiKey.length !== 51) {\n printError(\n \"Invalid API key format. Keys start with tt_ and are 51 characters long.\",\n );\n process.exit(1);\n }\n\n updateConfig({ api_key: apiKey });\n printSuccess(\n `API key stored (${apiKey.slice(0, 8)}...). You're ready to go.`,\n );\n });\n\n auth\n .command(\"logout\")\n .description(\"Remove stored credentials\")\n .action(() => {\n clearConfig();\n printSuccess(\"Credentials removed.\");\n });\n\n auth\n .command(\"status\")\n .description(\"Show current authentication status\")\n .action(() => {\n const opts = parent.opts();\n const apiKey = getApiKey(opts);\n const baseUrl = getBaseUrl(opts);\n\n if (isJsonMode()) {\n printJson({\n authenticated: !!apiKey,\n key_prefix: apiKey ? apiKey.slice(0, 8) + \"...\" : null,\n base_url: baseUrl,\n });\n return;\n }\n\n if (apiKey) {\n printDetail([\n [\"Authenticated\", \"Yes\"],\n [\"API Key\", apiKey.slice(0, 8) + \"...\"],\n [\"Base URL\", baseUrl],\n ]);\n } else {\n printWarning(\n \"Not authenticated. Run `tt auth login` to store an API key.\",\n );\n printDetail([[\"Base URL\", baseUrl]]);\n }\n });\n}\n","import { Command } from \"commander\";\nimport { readFileSync } from \"node:fs\";\nimport { get, post, put, del, type ClientOpts } from \"../client.js\";\nimport { resolveSpecId } from \"../resolve.js\";\nimport { canonicalizeBaseModel, canonicalizeSpecBaseModel } from \"../base-models.js\";\nimport {\n printTable,\n printDetail,\n printSuccess,\n printWarning,\n printJson,\n isJsonMode,\n formatDate,\n formatStatus,\n truncate,\n shortId,\n} from \"../output.js\";\n\nconst SPEC_BODY_KEYS = new Set([\n \"name\",\n \"description\",\n \"base_model\",\n \"system_prompt\",\n \"guidelines\",\n \"constraints\",\n \"examples\",\n]);\n\nconst RUN_INPUT_KEYS = [\"run_id\", \"behavior_spec_id\", \"spec_snapshot\", \"run_number\"];\n\nclass SpecBodyError extends Error {}\n\nfunction loadSpecBody(filePath: string, mode: \"create\" | \"update\"): Record<string, unknown> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(filePath, \"utf-8\"));\n } catch (e) {\n throw new SpecBodyError(\n `Could not parse ${filePath}: ${(e as Error).message}`,\n );\n }\n\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new SpecBodyError(\n `${filePath} must contain a JSON object at the top level.`,\n );\n }\n\n const body = parsed as Record<string, unknown>;\n\n const runInputHits = RUN_INPUT_KEYS.filter((k) => k in body);\n if (runInputHits.length >= 2 || \"spec_snapshot\" in body) {\n const hint = \"spec_snapshot\" in body\n ? `This file looks like a run-input payload (top-level keys: ${runInputHits.join(\", \")}). The actual spec is nested under \"spec_snapshot\". Try:\\n jq '.spec_snapshot' ${filePath} > spec.json\\n tt specs ${mode === \"create\" ? \"create\" : \"update <id>\"} --file spec.json`\n : `This file looks like a run-input payload (top-level keys: ${runInputHits.join(\", \")}), not a behaviour spec. To start a run on an existing spec, use: tt runs start <spec-id>`;\n throw new SpecBodyError(hint);\n }\n\n if (mode === \"create\" && typeof body.name !== \"string\") {\n throw new SpecBodyError(\n `${filePath} is missing required field \"name\" (string).`,\n );\n }\n\n const unknown = Object.keys(body).filter(\n (k) => !SPEC_BODY_KEYS.has(k) && k !== \"id\" && k !== \"eval_cases\",\n );\n if (unknown.length && !isJsonMode()) {\n printWarning(\n `Unknown spec field(s) in ${filePath}: ${unknown.join(\", \")}. They will be sent but may be rejected by the API.`,\n );\n }\n\n return canonicalizeSpecBaseModel(body);\n}\n\ninterface BehaviorSpec {\n id: string;\n name: string;\n description: string;\n system_prompt: string;\n guidelines: string[];\n examples: { input: string; output: string }[];\n constraints: string[];\n base_model: string;\n created_at: string;\n updated_at: string;\n _run_count?: number;\n _latest_run_status?: string;\n _latest_run_score?: number;\n _runs?: unknown[];\n}\n\nexport function registerSpecsCommands(parent: Command) {\n const specs = parent\n .command(\"specs\")\n .description(\"Manage behaviour specs\");\n\n specs\n .command(\"list\")\n .description(\"List behaviour specs\")\n .option(\"-p, --page <n>\", \"Page number\", \"1\")\n .option(\"--per-page <n>\", \"Results per page\", \"20\")\n .action(async (cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n const { data, meta } = await get<BehaviorSpec[]>(\n \"/behavior-specs\",\n { page: cmdOpts.page, per_page: cmdOpts.perPage },\n opts,\n );\n\n if (isJsonMode()) return printJson({ data, meta });\n\n printTable(\n [\"ID\", \"Name\", \"Model\", \"Examples\", \"Runs\", \"Status\", \"Updated\"],\n data.map((s) => [\n shortId(s.id),\n truncate(s.name, 30),\n s.base_model.split(\"/\").pop() || s.base_model,\n String(s.examples?.length ?? 0),\n String(s._run_count ?? 0),\n s._latest_run_status ? formatStatus(s._latest_run_status) : \"—\",\n formatDate(s.updated_at),\n ]),\n meta,\n );\n });\n\n specs\n .command(\"get\")\n .description(\"Show spec details\")\n .argument(\"<id>\", \"Spec ID (full UUID or 8+ char prefix)\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const fullId = await resolveSpecId(id, opts);\n const { data } = await get<BehaviorSpec>(`/behavior-specs/${fullId}`, undefined, opts);\n\n if (isJsonMode()) return printJson(data);\n\n printDetail([\n [\"ID\", data.id],\n [\"Name\", data.name],\n [\"Description\", data.description || undefined],\n [\"Base Model\", data.base_model],\n [\"System Prompt\", data.system_prompt ? truncate(data.system_prompt, 80) : undefined],\n [\"Guidelines\", data.guidelines?.length ? data.guidelines.join(\", \") : undefined],\n [\"Constraints\", data.constraints?.length ? data.constraints.join(\", \") : undefined],\n [\"Examples\", String(data.examples?.length ?? 0)],\n [\"Runs\", String(data._run_count ?? data._runs?.length ?? 0)],\n [\"Created\", formatDate(data.created_at)],\n [\"Updated\", formatDate(data.updated_at)],\n ]);\n\n if (data.examples?.length) {\n console.log(\"\\nExamples:\");\n for (const [i, ex] of data.examples.slice(0, 5).entries()) {\n console.log(` ${i + 1}. Input: ${truncate(ex.input, 60)}`);\n console.log(` Output: ${truncate(ex.output, 60)}`);\n }\n if (data.examples.length > 5) {\n console.log(` ... and ${data.examples.length - 5} more`);\n }\n }\n });\n\n specs\n .command(\"create\")\n .description(\"Create a behaviour spec\")\n .option(\"-f, --file <path>\", \"JSON file with spec definition\")\n .option(\"-n, --name <name>\", \"Spec name\")\n .option(\"--model <model>\", \"Base model ID\")\n .action(async (cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n let body: Record<string, unknown>;\n\n if (cmdOpts.file) {\n body = loadSpecBody(cmdOpts.file, \"create\");\n } else if (cmdOpts.name) {\n body = { name: cmdOpts.name };\n if (cmdOpts.model) body.base_model = canonicalizeBaseModel(cmdOpts.model);\n } else {\n throw new SpecBodyError(\"Provide --file or --name\");\n }\n\n const { data } = await post<BehaviorSpec>(\"/behavior-specs\", body, opts);\n\n if (isJsonMode()) return printJson(data);\n printSuccess(`Spec created: ${data.name} (${shortId(data.id)})`);\n });\n\n specs\n .command(\"update\")\n .description(\"Update a behaviour spec\")\n .argument(\"<id>\", \"Spec ID (full UUID or 8+ char prefix)\")\n .option(\"-f, --file <path>\", \"JSON file with fields to update\")\n .option(\"-n, --name <name>\", \"New name\")\n .option(\"--model <model>\", \"New base model ID\")\n .action(async (id: string, cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n let body: Record<string, unknown>;\n\n if (cmdOpts.file) {\n body = loadSpecBody(cmdOpts.file, \"update\");\n } else {\n body = {};\n if (cmdOpts.name) body.name = cmdOpts.name;\n if (cmdOpts.model) body.base_model = canonicalizeBaseModel(cmdOpts.model);\n }\n\n const fullId = await resolveSpecId(id, opts);\n const { data } = await put<BehaviorSpec>(\n `/behavior-specs/${fullId}`,\n body,\n opts,\n );\n\n if (isJsonMode()) return printJson(data);\n printSuccess(`Spec updated: ${data.name} (${shortId(data.id)})`);\n });\n\n specs\n .command(\"delete\")\n .description(\"Delete a behaviour spec\")\n .argument(\"<id>\", \"Spec ID (full UUID or 8+ char prefix)\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const fullId = await resolveSpecId(id, opts);\n await del(`/behavior-specs/${fullId}`, opts);\n\n if (isJsonMode()) return printJson({ id: fullId, deleted: true });\n printSuccess(`Spec deleted: ${shortId(fullId)}`);\n });\n}\n","import { get, type ClientOpts } from \"./client.js\";\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nconst RESOLVE_PAGE_SIZE = 100;\nconst MIN_PREFIX_LEN = 4;\n\ninterface Identifiable {\n id: string;\n name?: string;\n run_number?: number;\n}\n\ninterface Listed<T> {\n data: T[];\n meta?: { page: number; per_page: number; total: number };\n}\n\nexport class ResolveError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ResolveError\";\n }\n}\n\nexport function isFullUuid(value: string): boolean {\n return UUID_RE.test(value);\n}\n\nasync function resolvePrefix<T extends Identifiable>(\n prefix: string,\n kind: \"spec\" | \"run\" | \"dataset\" | \"model\",\n listPath: string,\n describe: (item: T) => string,\n opts?: ClientOpts,\n): Promise<string> {\n if (isFullUuid(prefix)) return prefix;\n\n const noun = kind;\n const listCmd = `tt ${kind}s list --json`;\n\n if (prefix.length < MIN_PREFIX_LEN) {\n throw new ResolveError(\n `${capitalize(noun)} ID prefix \"${prefix}\" is too short — provide at least ${MIN_PREFIX_LEN} characters or the full UUID.`,\n );\n }\n\n const lower = prefix.toLowerCase();\n const { data, meta } = (await get<T[]>(\n listPath,\n { page: 1, per_page: RESOLVE_PAGE_SIZE },\n opts,\n )) as Listed<T>;\n\n const matches = data.filter((item) => item.id.toLowerCase().startsWith(lower));\n\n if (matches.length === 1) return matches[0].id;\n\n if (matches.length === 0) {\n if (meta && meta.total > data.length) {\n throw new ResolveError(\n `No ${noun} found with ID prefix \"${prefix}\" in the first ${data.length} ${noun}s (you have ${meta.total} total). Use the full UUID — see \\`${listCmd}\\`.`,\n );\n }\n throw new ResolveError(`No ${noun} found with ID prefix \"${prefix}\".`);\n }\n\n const list = matches.map((m) => ` ${describe(m)}`).join(\"\\n\");\n throw new ResolveError(\n `${capitalize(noun)} ID prefix \"${prefix}\" is ambiguous (${matches.length} matches):\\n${list}\\nProvide more characters or the full UUID.`,\n );\n}\n\nfunction capitalize(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\nexport function resolveSpecId(prefix: string, opts?: ClientOpts): Promise<string> {\n return resolvePrefix<Identifiable>(\n prefix,\n \"spec\",\n \"/behavior-specs\",\n (s) => `${s.id}${s.name ? ` (${s.name})` : \"\"}`,\n opts,\n );\n}\n\nexport function resolveRunId(prefix: string, opts?: ClientOpts): Promise<string> {\n return resolvePrefix<Identifiable>(\n prefix,\n \"run\",\n \"/runs\",\n (r) => `${r.id}${r.run_number != null ? ` (run #${r.run_number})` : \"\"}`,\n opts,\n );\n}\n\nexport function resolveDatasetId(prefix: string, opts?: ClientOpts): Promise<string> {\n return resolvePrefix<Identifiable>(\n prefix,\n \"dataset\",\n \"/datasets\",\n (d) => `${d.id}${d.name ? ` (${d.name})` : \"\"}`,\n opts,\n );\n}\n\nexport function resolveModelId(prefix: string, opts?: ClientOpts): Promise<string> {\n return resolvePrefix<Identifiable>(\n prefix,\n \"model\",\n \"/models\",\n (m) => `${m.id}${m.name ? ` (${m.name})` : \"\"}`,\n opts,\n );\n}\n","export const SUPPORTED_BASE_MODELS = [\n \"google/gemma-4-E2B-it\",\n \"google/gemma-4-26B-A4B-it\",\n \"Qwen/Qwen3.5-2B\",\n] as const;\n\nexport type SupportedBaseModel = (typeof SUPPORTED_BASE_MODELS)[number];\n\nconst BASE_MODEL_ALIASES = new Map<string, SupportedBaseModel>();\n\nfor (const model of SUPPORTED_BASE_MODELS) {\n BASE_MODEL_ALIASES.set(model.toLowerCase(), model);\n}\n\nfor (const [alias, model] of [\n [\"google/gemma-4-E2B\", \"google/gemma-4-E2B-it\"],\n [\"google/gemma-4-e2b\", \"google/gemma-4-E2B-it\"],\n [\"google/gemma-4-e2b-it\", \"google/gemma-4-E2B-it\"],\n [\"google/gemma-4-26b-a4b-it\", \"google/gemma-4-26B-A4B-it\"],\n [\"google/gemma-4-26B-A4B\", \"google/gemma-4-26B-A4B-it\"],\n [\"google/gemma-4-26b-a4b\", \"google/gemma-4-26B-A4B-it\"],\n [\"qwen/qwen3.5-2b\", \"Qwen/Qwen3.5-2B\"],\n [\"Qwen/Qwen3.5-2B-Base\", \"Qwen/Qwen3.5-2B\"],\n [\"qwen/qwen3.5-2b-base\", \"Qwen/Qwen3.5-2B\"],\n] as const) {\n BASE_MODEL_ALIASES.set(alias.toLowerCase(), model);\n}\n\nexport class UnsupportedBaseModelError extends Error {\n constructor(model: unknown) {\n const supported = SUPPORTED_BASE_MODELS.join(\", \");\n super(\n `Unsupported base_model \"${String(model)}\". Supported base models: ${supported}`,\n );\n this.name = \"UnsupportedBaseModelError\";\n }\n}\n\nexport function canonicalizeBaseModel(model: unknown): SupportedBaseModel {\n if (typeof model !== \"string\" || !model.trim()) {\n throw new UnsupportedBaseModelError(model);\n }\n\n const canonical = BASE_MODEL_ALIASES.get(model.trim().toLowerCase());\n if (!canonical) {\n throw new UnsupportedBaseModelError(model);\n }\n\n return canonical;\n}\n\nexport function canonicalizeSpecBaseModel<T extends Record<string, unknown>>(body: T): T {\n if (\"base_model\" in body && body.base_model !== undefined) {\n return { ...body, base_model: canonicalizeBaseModel(body.base_model) };\n }\n\n return body;\n}\n","import { Command } from \"commander\";\nimport ora from \"ora\";\nimport { get, post, type ClientOpts } from \"../client.js\";\nimport { resolveSpecId, resolveRunId, resolveDatasetId } from \"../resolve.js\";\nimport {\n printTable,\n printDetail,\n printSuccess,\n printJson,\n isJsonMode,\n formatDate,\n formatStatus,\n shortId,\n truncate,\n} from \"../output.js\";\n\ninterface Run {\n id: string;\n behavior_spec_id: string;\n run_number: number;\n status: string;\n current_stage?: string | null;\n stage_label?: string | null;\n progress_pct?: number | null;\n status_message?: string | null;\n hyperparameters: Record<string, unknown> | null;\n eval_summary: { mean_score?: number; pass_rate?: number } | null;\n error: string | null;\n started_at: string | null;\n completed_at: string | null;\n created_at: string;\n updated_at: string;\n _spec_name?: string;\n _evals?: RunEval[];\n _events?: RunEvent[];\n}\n\ninterface RunEval {\n id: string;\n prompt: string;\n expected: string;\n actual: string;\n passed: boolean;\n score: number | null;\n reasoning: string | null;\n latency_ms: number | null;\n}\n\ninterface RunEvent {\n id: string;\n stage: string;\n label: string;\n status: string;\n message: string | null;\n occurred_at: string;\n}\n\nfunction formatProgress(run: Run): string | undefined {\n if (run.progress_pct == null && !run.stage_label) return undefined;\n const label = run.stage_label ?? run.current_stage ?? \"Progress\";\n return run.progress_pct == null ? label : `${label} (${run.progress_pct}%)`;\n}\n\nexport function registerRunsCommands(parent: Command) {\n const runs = parent.command(\"runs\").description(\"Manage runs\");\n\n runs\n .command(\"list\")\n .description(\"List runs\")\n .option(\"-s, --spec <id>\", \"Filter by spec ID (full UUID or 8+ char prefix)\")\n .option(\"-p, --page <n>\", \"Page number\", \"1\")\n .option(\"--per-page <n>\", \"Results per page\", \"20\")\n .action(async (cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n\n let path = \"/runs\";\n const query: Record<string, string | number> = {\n page: cmdOpts.page,\n per_page: cmdOpts.perPage,\n };\n\n if (cmdOpts.spec) {\n const fullSpecId = await resolveSpecId(cmdOpts.spec, opts);\n path = `/behavior-specs/${fullSpecId}/runs`;\n }\n\n const { data, meta } = await get<Run[]>(path, query, opts);\n\n if (isJsonMode()) return printJson({ data, meta });\n\n printTable(\n [\"ID\", \"Spec\", \"#\", \"Status\", \"Score\", \"Started\", \"Completed\"],\n data.map((r) => [\n shortId(r.id),\n r._spec_name ? truncate(r._spec_name, 20) : shortId(r.behavior_spec_id),\n String(r.run_number),\n formatStatus(r.status),\n r.eval_summary?.mean_score != null\n ? (r.eval_summary.mean_score * 100).toFixed(1) + \"%\"\n : \"—\",\n formatDate(r.started_at),\n formatDate(r.completed_at),\n ]),\n meta,\n );\n });\n\n runs\n .command(\"get\")\n .description(\"Show run details and eval results\")\n .argument(\"<id>\", \"Run ID (full UUID or 8+ char prefix)\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const fullId = await resolveRunId(id, opts);\n const { data } = await get<Run>(`/runs/${fullId}`, undefined, opts);\n\n if (isJsonMode()) return printJson(data);\n\n printDetail([\n [\"ID\", data.id],\n [\"Spec\", data._spec_name ?? shortId(data.behavior_spec_id)],\n [\"Run #\", String(data.run_number)],\n [\"Status\", formatStatus(data.status)],\n [\"Stage\", formatProgress(data)],\n [\"Message\", data.status_message ?? undefined],\n [\"Score\", data.eval_summary?.mean_score != null\n ? (data.eval_summary.mean_score * 100).toFixed(1) + \"%\"\n : undefined],\n [\"Pass Rate\", data.eval_summary?.pass_rate != null\n ? (data.eval_summary.pass_rate * 100).toFixed(1) + \"%\"\n : undefined],\n [\"Error\", data.error ?? undefined],\n [\"Started\", formatDate(data.started_at)],\n [\"Completed\", formatDate(data.completed_at)],\n [\"Created\", formatDate(data.created_at)],\n ]);\n\n if (data.hyperparameters && Object.keys(data.hyperparameters).length) {\n console.log(\"\\nHyperparameters:\");\n for (const [k, v] of Object.entries(data.hyperparameters)) {\n console.log(` ${k}: ${v}`);\n }\n }\n\n if (data._events?.length) {\n console.log(\"\\nLatest Updates:\");\n for (const event of data._events.slice(-5)) {\n const time = formatDate(event.occurred_at);\n console.log(\n ` ${time} ${formatStatus(event.status)} ${event.label}${event.message ? ` — ${event.message}` : \"\"}`,\n );\n }\n }\n\n if (data._evals?.length) {\n console.log(`\\nEval Results (${data._evals.length}):`);\n printTable(\n [\"#\", \"Passed\", \"Score\", \"Prompt\", \"Latency\"],\n data._evals.map((e, i) => [\n String(i + 1),\n e.passed ? \"✓\" : \"✗\",\n e.score != null ? e.score.toFixed(2) : \"—\",\n truncate(e.prompt, 40),\n e.latency_ms != null ? `${e.latency_ms}ms` : \"—\",\n ]),\n );\n }\n });\n\n runs\n .command(\"start\")\n .description(\"Start a new run for a behaviour spec\")\n .argument(\"<spec-id>\", \"Behaviour spec ID (full UUID or 8+ char prefix)\")\n .option(\"--no-augment\", \"Disable data augmentation\")\n .option(\"--no-llm-judge\", \"Disable Bedrock LLM judging\")\n .option(\"--epochs <n>\", \"Number of training epochs\")\n .option(\"--lr <rate>\", \"Learning rate\")\n .option(\"--batch-size <n>\", \"Batch size\")\n .option(\"--dataset <id>\", \"Dataset ID to use instead of inline spec examples (full UUID or 4+ char prefix)\")\n .option(\"--train-ratio <ratio>\", \"Dataset training split ratio (default: 0.8 when any split ratio is set)\")\n .option(\"--validation-ratio <ratio>\", \"Dataset validation split ratio (default: 0.1 when any split ratio is set)\")\n .option(\"--test-ratio <ratio>\", \"Dataset test split ratio (default: 0.1 when any split ratio is set)\")\n .option(\"--lora-rank <n>\", \"LoRA rank\")\n .option(\"--lora-alpha <n>\", \"LoRA alpha\")\n .option(\"--max-eval-examples <n>\", \"Max examples for the primary eval pass\")\n .option(\"--max-test-eval-examples <n>\", \"Max examples for the secondary test eval pass\")\n .action(async (specId: string, cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n const body: Record<string, unknown> = {};\n\n if (cmdOpts.augment === false) body.augment = false;\n if (cmdOpts.dataset) body.dataset_id = await resolveDatasetId(cmdOpts.dataset, opts);\n\n const splitRatioOptions = [\n cmdOpts.trainRatio,\n cmdOpts.validationRatio,\n cmdOpts.testRatio,\n ];\n if (splitRatioOptions.some((value) => value != null)) {\n body.split_ratios = {\n train: cmdOpts.trainRatio != null ? Number(cmdOpts.trainRatio) : 0.8,\n validation:\n cmdOpts.validationRatio != null ? Number(cmdOpts.validationRatio) : 0.1,\n test: cmdOpts.testRatio != null ? Number(cmdOpts.testRatio) : 0.1,\n };\n }\n\n const hp: Record<string, unknown> = {};\n if (cmdOpts.epochs) hp.n_epochs = Number(cmdOpts.epochs);\n if (cmdOpts.lr) hp.learning_rate = Number(cmdOpts.lr);\n if (cmdOpts.batchSize) hp.batch_size = Number(cmdOpts.batchSize);\n if (cmdOpts.loraRank) hp.lora_rank = Number(cmdOpts.loraRank);\n if (cmdOpts.loraAlpha) hp.lora_alpha = Number(cmdOpts.loraAlpha);\n if (cmdOpts.maxEvalExamples) hp.max_eval_examples = Number(cmdOpts.maxEvalExamples);\n if (cmdOpts.maxTestEvalExamples) hp.max_test_eval_examples = Number(cmdOpts.maxTestEvalExamples);\n if (cmdOpts.llmJudge === false) body.use_llm_judge = false;\n if (Object.keys(hp).length) body.hyperparameters = hp;\n\n const fullSpecId = await resolveSpecId(specId, opts);\n const { data } = await post<Run>(\n `/behavior-specs/${fullSpecId}/runs`,\n body,\n opts,\n );\n\n if (isJsonMode()) return printJson(data);\n printSuccess(\n `Run #${data.run_number} started (${shortId(data.id)}). ${formatProgress(data) ?? `Status: ${formatStatus(data.status)}`}`,\n );\n });\n\n runs\n .command(\"cancel\")\n .description(\"Cancel a running run\")\n .argument(\"<id>\", \"Run ID (full UUID or 8+ char prefix)\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const fullId = await resolveRunId(id, opts);\n const { data } = await post<Run>(`/runs/${fullId}/cancel`, undefined, opts);\n\n if (isJsonMode()) return printJson(data);\n printSuccess(`Run ${shortId(fullId)} cancelled.`);\n });\n\n runs\n .command(\"watch\")\n .description(\"Watch a run until it completes\")\n .argument(\"<id>\", \"Run ID (full UUID or 8+ char prefix)\")\n .option(\"--interval <ms>\", \"Poll interval in milliseconds\", \"5000\")\n .action(async (id: string, cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n const interval = Number(cmdOpts.interval);\n const fullId = await resolveRunId(id, opts);\n const spinner = ora(`Watching run ${shortId(fullId)}...`).start();\n\n const terminalStates = new Set([\n \"completed\",\n \"failed\",\n \"cancelled\",\n ]);\n\n let run: Run;\n while (true) {\n const { data } = await get<Run>(`/runs/${fullId}`, undefined, opts);\n run = data;\n spinner.text = `Run ${shortId(fullId)} — ${formatProgress(run) ?? formatStatus(run.status)}`;\n\n if (terminalStates.has(run.status)) break;\n await new Promise((r) => setTimeout(r, interval));\n }\n\n spinner.stop();\n\n if (isJsonMode()) return printJson(run);\n\n printDetail([\n [\"Run\", shortId(run.id)],\n [\"Status\", formatStatus(run.status)],\n [\"Stage\", formatProgress(run)],\n [\"Message\", run.status_message ?? undefined],\n [\"Score\", run.eval_summary?.mean_score != null\n ? (run.eval_summary.mean_score * 100).toFixed(1) + \"%\"\n : undefined],\n [\"Error\", run.error ?? undefined],\n [\"Completed\", formatDate(run.completed_at)],\n ]);\n });\n}\n","import { Command } from \"commander\";\nimport { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { get, del, post, type ClientOpts } from \"../client.js\";\nimport { resolveDatasetId } from \"../resolve.js\";\nimport {\n printTable,\n printDetail,\n printSuccess,\n printJson,\n printError,\n isJsonMode,\n formatDate,\n formatStatus,\n shortId,\n truncate,\n} from \"../output.js\";\n\ninterface Dataset {\n id: string;\n name: string;\n description: string | null;\n storage_path: string;\n file_size_bytes: number;\n row_count: number;\n format: string;\n status: string;\n validation_errors: string[] | null;\n created_at: string;\n updated_at: string;\n}\n\ninterface DatasetUploadUrl {\n path: string;\n upload_url: string;\n method: \"PUT\";\n headers?: Record<string, string>;\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction validateDatasetFile(file: string): void {\n const lines = readFileSync(file, \"utf8\").split(/\\r?\\n/);\n const errors: string[] = [];\n let rowCount = 0;\n\n for (const [index, rawLine] of lines.entries()) {\n const line = rawLine.trim();\n if (!line) continue;\n\n rowCount += 1;\n const rowNumber = index + 1;\n let row: unknown;\n\n try {\n row = JSON.parse(line);\n } catch {\n errors.push(`Row ${rowNumber}: invalid JSON`);\n continue;\n }\n\n if (!row || typeof row !== \"object\" || Array.isArray(row)) {\n errors.push(`Row ${rowNumber}: expected an object with \"input\" and \"output\" fields`);\n continue;\n }\n\n const record = row as Record<string, unknown>;\n if (\"messages\" in record && !(\"input\" in record) && !(\"output\" in record)) {\n errors.push(\n `Row ${rowNumber}: found OpenAI SFT-style \"messages\"; Tuned Tensor datasets require flat \"input\" and \"output\" strings`,\n );\n continue;\n }\n\n if (typeof record.input !== \"string\") {\n errors.push(`Row ${rowNumber}: missing string \"input\" field`);\n }\n if (typeof record.output !== \"string\") {\n errors.push(`Row ${rowNumber}: missing string \"output\" field`);\n }\n }\n\n if (rowCount === 0) {\n errors.push(\"File contains no JSONL rows\");\n }\n\n if (errors.length > 0) {\n const preview = errors.slice(0, 5).join(\"\\n\");\n const suffix = errors.length > 5 ? `\\n...and ${errors.length - 5} more error(s)` : \"\";\n throw new Error(\n `Invalid dataset format. Each JSONL row must be {\"input\": \"...\", \"output\": \"...\"}.\\n${preview}${suffix}`,\n );\n }\n}\n\nexport function registerDatasetsCommands(parent: Command) {\n const datasets = parent\n .command(\"datasets\")\n .description(\"Manage datasets\");\n\n datasets\n .command(\"list\")\n .description(\"List datasets\")\n .option(\"-p, --page <n>\", \"Page number\", \"1\")\n .option(\"--per-page <n>\", \"Results per page\", \"20\")\n .action(async (cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n const { data, meta } = await get<Dataset[]>(\n \"/datasets\",\n { page: cmdOpts.page, per_page: cmdOpts.perPage },\n opts,\n );\n\n if (isJsonMode()) return printJson({ data, meta });\n\n printTable(\n [\"ID\", \"Name\", \"Rows\", \"Size\", \"Status\", \"Created\"],\n data.map((d) => [\n shortId(d.id),\n truncate(d.name, 30),\n String(d.row_count),\n formatBytes(d.file_size_bytes),\n formatStatus(d.status),\n formatDate(d.created_at),\n ]),\n meta,\n );\n });\n\n datasets\n .command(\"get\")\n .description(\"Show dataset details\")\n .argument(\"<id>\", \"Dataset ID (full UUID or 4+ char prefix)\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const fullId = await resolveDatasetId(id, opts);\n const { data } = await get<Dataset>(`/datasets/${fullId}`, undefined, opts);\n\n if (isJsonMode()) return printJson(data);\n\n printDetail([\n [\"ID\", data.id],\n [\"Name\", data.name],\n [\"Description\", data.description ?? undefined],\n [\"Format\", data.format],\n [\"Rows\", String(data.row_count)],\n [\"Size\", formatBytes(data.file_size_bytes)],\n [\"Status\", formatStatus(data.status)],\n [\"Created\", formatDate(data.created_at)],\n [\"Updated\", formatDate(data.updated_at)],\n ]);\n\n if (data.validation_errors?.length) {\n console.log(\"\\nValidation Errors:\");\n for (const err of data.validation_errors) {\n console.log(` - ${err}`);\n }\n }\n });\n\n datasets\n .command(\"upload\")\n .description(\"Upload a JSONL dataset file\")\n .argument(\"<file>\", \"Path to JSONL file\")\n .option(\"-n, --name <name>\", \"Dataset name (defaults to filename)\")\n .option(\"-d, --description <desc>\", \"Dataset description\")\n .action(async (file: string, cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n\n if (!existsSync(file)) {\n printError(`File not found: ${file}`);\n process.exit(1);\n }\n\n validateDatasetFile(file);\n\n const name = cmdOpts.name || file.split(\"/\").pop()!.replace(/\\.jsonl?$/, \"\");\n const fileBytes = readFileSync(file);\n const uploadUrl = await post<DatasetUploadUrl>(\n \"/datasets/upload-url\",\n {\n name,\n description: cmdOpts.description ?? null,\n filename: file.split(\"/\").pop()!,\n size: statSync(file).size,\n contentType: \"application/jsonl\",\n },\n opts,\n );\n\n const uploadRes = await fetch(uploadUrl.data.upload_url, {\n method: uploadUrl.data.method,\n headers: uploadUrl.data.headers ?? { \"Content-Type\": \"application/jsonl\" },\n body: new Blob([fileBytes], { type: \"application/jsonl\" }),\n });\n if (!uploadRes.ok) {\n throw new Error(`Dataset upload failed: ${uploadRes.status} ${uploadRes.statusText}`);\n }\n\n const { data } = await post<Dataset>(\n \"/datasets/finalize\",\n {\n path: uploadUrl.data.path,\n name,\n description: cmdOpts.description ?? null,\n },\n opts,\n );\n\n if (isJsonMode()) return printJson(data);\n printSuccess(\n `Dataset uploaded: ${data.name} (${shortId(data.id)}) — ${data.row_count} rows`,\n );\n });\n\n datasets\n .command(\"delete\")\n .description(\"Delete a dataset\")\n .argument(\"<id>\", \"Dataset ID (full UUID or 4+ char prefix)\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const fullId = await resolveDatasetId(id, opts);\n await del(`/datasets/${fullId}`, opts);\n\n if (isJsonMode()) return printJson({ id: fullId, deleted: true });\n printSuccess(`Dataset deleted: ${shortId(fullId)}`);\n });\n}\n","import { Command } from \"commander\";\nimport { existsSync, mkdirSync, statSync, createWriteStream, unlinkSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport { get, del, type ClientOpts } from \"../client.js\";\nimport { resolveModelId } from \"../resolve.js\";\nimport {\n printTable,\n printDetail,\n printSuccess,\n printJson,\n isJsonMode,\n formatDate,\n shortId,\n truncate,\n} from \"../output.js\";\n\ninterface Model {\n id: string;\n name: string;\n provider: string;\n provider_model_id: string;\n base_model: string;\n description: string | null;\n created_at: string;\n}\n\ninterface ModelDownload {\n url: string;\n filename: string;\n expires_at: string;\n}\n\nfunction resolveOutputPath(output: string | undefined, filename: string): string {\n if (!output) return filename;\n if (existsSync(output) && statSync(output).isDirectory()) {\n return join(output, filename);\n }\n return output;\n}\n\nasync function downloadUrlToFile(url: string, outputPath: string): Promise<number | null> {\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`Download failed: ${res.status} ${res.statusText}`);\n }\n if (!res.body) {\n throw new Error(\"Download failed: response body was empty\");\n }\n\n mkdirSync(dirname(outputPath), { recursive: true });\n const file = createWriteStream(outputPath);\n\n try {\n await pipeline(Readable.fromWeb(res.body), file);\n } catch (err) {\n try {\n unlinkSync(outputPath);\n } catch {\n // Best effort cleanup for partially written downloads.\n }\n throw err;\n }\n\n const length = res.headers.get(\"content-length\");\n return length ? Number(length) : null;\n}\n\nexport function registerModelsCommands(parent: Command) {\n const models = parent.command(\"models\").description(\"Manage fine-tuned models\");\n\n models\n .command(\"list\")\n .description(\"List fine-tuned models\")\n .option(\"-p, --page <n>\", \"Page number\", \"1\")\n .option(\"--per-page <n>\", \"Results per page\", \"20\")\n .action(async (cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n const { data, meta } = await get<Model[]>(\n \"/models\",\n { page: cmdOpts.page, per_page: cmdOpts.perPage },\n opts,\n );\n\n if (isJsonMode()) return printJson({ data, meta });\n\n printTable(\n [\"ID\", \"Name\", \"Base Model\", \"Provider\", \"Created\"],\n data.map((m) => [\n shortId(m.id),\n truncate(m.name, 30),\n m.base_model.split(\"/\").pop() || m.base_model,\n m.provider,\n formatDate(m.created_at),\n ]),\n meta,\n );\n });\n\n models\n .command(\"get\")\n .description(\"Show model details\")\n .argument(\"<id>\", \"Model ID\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const { data } = await get<Model>(`/models/${id}`, undefined, opts);\n\n if (isJsonMode()) return printJson(data);\n\n printDetail([\n [\"ID\", data.id],\n [\"Name\", data.name],\n [\"Base Model\", data.base_model],\n [\"Provider\", data.provider],\n [\"Provider Model\", data.provider_model_id],\n [\"Description\", data.description ?? undefined],\n [\"Created\", formatDate(data.created_at)],\n ]);\n });\n\n models\n .command(\"download\")\n .description(\"Download a fine-tuned model artifact\")\n .argument(\"<id>\", \"Model ID (full UUID or 4+ char prefix)\")\n .option(\"-o, --output <path>\", \"Output file or directory\")\n .option(\"-f, --force\", \"Overwrite the output file if it already exists\")\n .action(async (id: string, cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n const fullId = await resolveModelId(id, opts);\n const { data } = await get<ModelDownload>(\n `/models/${fullId}/download`,\n undefined,\n opts,\n );\n\n const outputPath = resolveOutputPath(cmdOpts.output, data.filename);\n if (existsSync(outputPath) && !cmdOpts.force) {\n throw new Error(`Output file already exists: ${outputPath}. Use --force to overwrite.`);\n }\n\n const bytes = await downloadUrlToFile(data.url, outputPath);\n\n if (isJsonMode()) {\n return printJson({\n id: fullId,\n output_path: outputPath,\n filename: data.filename,\n bytes,\n expires_at: data.expires_at,\n });\n }\n\n const size = bytes == null ? \"\" : ` (${bytes} bytes)`;\n printSuccess(`Model downloaded to ${outputPath}${size}`);\n });\n\n models\n .command(\"delete\")\n .description(\"Delete a model\")\n .argument(\"<id>\", \"Model ID\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n await del(`/models/${id}`, opts);\n\n if (isJsonMode()) return printJson({ id, deleted: true });\n printSuccess(`Model deleted: ${shortId(id)}`);\n });\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { get, type ClientOpts } from \"../client.js\";\nimport {\n printDetail,\n printJson,\n printTable,\n isJsonMode,\n formatDate,\n formatStatus,\n shortId,\n} from \"../output.js\";\n\ninterface BalanceResponse {\n balance_cents: number;\n reserved_cents: number;\n available_cents: number;\n lifetime_topup_cents: number;\n}\n\ntype CreditKind =\n | \"signup_bonus\"\n | \"topup\"\n | \"debit_run\"\n | \"debit_autotune\"\n | \"refund\"\n | \"adjustment\";\n\ninterface LedgerRow {\n id: string;\n kind: CreditKind;\n amount_cents: number;\n balance_after_cents: number;\n reference_id: string | null;\n created_at: string;\n}\n\nconst KIND_LABELS: Record<CreditKind, string> = {\n signup_bonus: \"Signup bonus\",\n topup: \"Top-up\",\n debit_run: \"Run\",\n debit_autotune: \"Auto-tune\",\n refund: \"Refund\",\n adjustment: \"Adjustment\",\n};\n\nfunction formatCents(cents: number): string {\n const sign = cents < 0 ? \"-\" : \"\";\n const abs = Math.abs(cents);\n return `${sign}$${(abs / 100).toFixed(2)}`;\n}\n\nfunction formatSigned(cents: number): string {\n if (cents > 0) return chalk.green(`+${formatCents(cents)}`);\n if (cents < 0) return chalk.red(formatCents(cents));\n return formatCents(cents);\n}\n\nexport function registerBalanceCommands(parent: Command) {\n parent\n .command(\"balance\")\n .description(\"Show available credits, held credits, and recent transactions\")\n .option(\"-n, --limit <n>\", \"Number of transactions to show (default 10)\", \"10\")\n .action(async (options) => {\n const opts = parent.opts() as ClientOpts;\n const limit = Number(options.limit) || 10;\n\n const [{ data: balance }, { data: transactions }] = await Promise.all([\n get<BalanceResponse>(\"/billing/balance\", undefined, opts),\n get<LedgerRow[]>(\"/billing/transactions\", { per_page: limit }, opts),\n ]);\n\n if (isJsonMode()) {\n return printJson({ balance, transactions });\n }\n\n const lowBalance = balance.available_cents < 100;\n const availableLine = lowBalance\n ? chalk.red(formatCents(balance.available_cents)) + chalk.dim(\" (low)\")\n : chalk.bold.green(formatCents(balance.available_cents));\n\n printDetail([\n [\"Available\", availableLine],\n [\"Total balance\", formatCents(balance.balance_cents)],\n [\"On hold\", formatCents(balance.reserved_cents)],\n [\"Lifetime top-ups\", formatCents(balance.lifetime_topup_cents)],\n ]);\n\n if (transactions && transactions.length > 0) {\n console.log(`\\n${chalk.bold(\"Recent transactions\")}`);\n printTable(\n [\"Date\", \"Type\", \"Amount\", \"Balance\", \"Reference\"],\n transactions.map((row) => [\n formatDate(row.created_at),\n KIND_LABELS[row.kind] ?? row.kind,\n formatSigned(row.amount_cents),\n formatCents(row.balance_after_cents),\n row.reference_id ? shortId(row.reference_id) : chalk.dim(\"—\"),\n ])\n );\n } else {\n console.log(\n `\\n${chalk.dim(\"No transactions yet — run `tt topup` to add credits.\")}`\n );\n }\n\n if (lowBalance) {\n console.log(\n `\\n${formatStatus(\"preparing\")} ${chalk.yellow(\n \"Run `tt topup` to add more available credits before starting a run.\"\n )}`\n );\n }\n });\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport open from \"open\";\nimport { post, type ClientOpts } from \"../client.js\";\nimport { printJson, isJsonMode, printSuccess } from \"../output.js\";\n\ninterface TopupResponse {\n checkout_url: string;\n session_id: string;\n}\n\nconst PRESETS_USD = [10, 25, 50, 100];\nconst MIN_USD = 5;\nconst MAX_USD = 10000;\n\nfunction parseAmount(input: string | undefined): number | null {\n if (!input) return null;\n const cleaned = input.replace(/^\\$/, \"\").trim();\n const num = Number(cleaned);\n if (!Number.isFinite(num) || num <= 0) return null;\n return num;\n}\n\nasync function readLine(prompt: string): Promise<string> {\n const readline = await import(\"node:readline/promises\");\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n try {\n return (await rl.question(prompt)).trim();\n } finally {\n rl.close();\n }\n}\n\nexport function registerTopupCommands(parent: Command) {\n parent\n .command(\"topup\")\n .description(\"Add prepaid credits via Stripe Checkout\")\n .option(\"-a, --amount <usd>\", \"Amount in USD (e.g. 25)\")\n .option(\"--no-open\", \"Print checkout URL instead of opening the browser\")\n .action(async (options) => {\n const opts = parent.opts() as ClientOpts;\n\n let amountUsd: number | null;\n\n if (options.amount !== undefined) {\n amountUsd = parseAmount(options.amount);\n if (amountUsd === null) {\n throw new Error(\"Invalid amount\");\n }\n } else {\n if (isJsonMode()) {\n throw new Error(\n \"amount is required in --json mode (use --amount <usd>)\"\n );\n }\n console.log(chalk.bold(\"Add credits via Stripe Checkout\"));\n console.log(\n chalk.dim(\n `Quick picks: ${PRESETS_USD.map((n) => `$${n}`).join(\", \")}`\n )\n );\n const input = await readLine(`Amount in USD (min $${MIN_USD}): `);\n amountUsd = parseAmount(input);\n if (amountUsd === null) {\n throw new Error(\"Invalid amount\");\n }\n }\n\n if (amountUsd < MIN_USD) {\n throw new Error(`Minimum top-up is $${MIN_USD}`);\n }\n if (amountUsd > MAX_USD) {\n throw new Error(`Maximum top-up is $${MAX_USD}`);\n }\n\n const amountCents = Math.round(amountUsd * 100);\n\n const { data } = await post<TopupResponse>(\n \"/billing/topup\",\n { amount_cents: amountCents },\n opts\n );\n\n if (isJsonMode()) {\n return printJson(data);\n }\n\n const url = data.checkout_url;\n console.log(\n `${chalk.bold(\"Checkout URL:\")} ${chalk.cyan(url)}\\n` +\n chalk.dim(\"Complete the payment to credit your account.\")\n );\n\n if (options.open !== false) {\n try {\n await open(url);\n printSuccess(\"Opened Stripe Checkout in your browser.\");\n } catch {\n console.log(\n chalk.yellow(\n \"Could not open browser automatically — copy the URL above.\"\n )\n );\n }\n }\n });\n}\n","import { Command } from \"commander\";\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { printSuccess, printError, printWarning } from \"../output.js\";\nimport type { LocalSpec } from \"../eval/types.js\";\nimport { canonicalizeBaseModel } from \"../base-models.js\";\n\nconst DEFAULT_SPEC_FILE = \"tunedtensor.json\";\n\nconst SCAFFOLD: LocalSpec = {\n name: \"My Agent\",\n description: \"\",\n base_model: \"Qwen/Qwen3.5-2B\",\n system_prompt: \"You are a helpful assistant.\",\n guidelines: [],\n constraints: [],\n examples: [\n { input: \"Hello\", output: \"Hi! How can I help you today?\" },\n ],\n eval_cases: [],\n};\n\nexport function registerInitCommand(parent: Command) {\n parent\n .command(\"init\")\n .description(\"Create a local behaviour spec file\")\n .option(\"-n, --name <name>\", \"Spec name\")\n .option(\"--model <model>\", \"Base model ID\")\n .option(\"-f, --file <path>\", \"Output file path\", DEFAULT_SPEC_FILE)\n .action(async (cmdOpts) => {\n const filePath = resolve(cmdOpts.file);\n\n if (existsSync(filePath)) {\n printWarning(`${cmdOpts.file} already exists. Use tt eval to validate it or edit it directly.`);\n return;\n }\n\n const spec: LocalSpec = { ...SCAFFOLD };\n if (cmdOpts.name) spec.name = cmdOpts.name;\n if (cmdOpts.model) spec.base_model = canonicalizeBaseModel(cmdOpts.model);\n\n writeFileSync(filePath, JSON.stringify(spec, null, 2) + \"\\n\");\n printSuccess(`Created ${cmdOpts.file}`);\n console.log(\"\\nNext steps:\");\n console.log(\" 1. Edit the spec: system_prompt, guidelines, examples\");\n console.log(\" 2. Validate spec: tt eval\");\n console.log(\" 3. Push to remote: tt push\");\n });\n}\n\nexport function loadSpec(filePath?: string): LocalSpec {\n const resolved = resolve(filePath || DEFAULT_SPEC_FILE);\n if (!existsSync(resolved)) {\n printError(\n `Spec file not found: ${filePath || DEFAULT_SPEC_FILE}\\nRun \\`tt init\\` to create one.`,\n );\n process.exit(1);\n }\n\n const raw = JSON.parse(readFileSync(resolved, \"utf-8\"));\n return raw as LocalSpec;\n}\n\nexport { DEFAULT_SPEC_FILE };\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport {\n printJson,\n isJsonMode,\n} from \"../output.js\";\nimport { loadSpec, DEFAULT_SPEC_FILE } from \"./init.js\";\nimport { validateSpec } from \"../eval/rules.js\";\nimport type { ValidationCheck } from \"../eval/types.js\";\n\nexport function registerEvalCommand(parent: Command) {\n parent\n .command(\"eval\")\n .description(\"Validate a local behaviour spec\")\n .option(\"-m, --model <model>\", \"Deprecated; ignored because tt eval only validates the local spec\")\n .option(\"-f, --file <path>\", \"Spec file path\", DEFAULT_SPEC_FILE)\n .action(async (cmdOpts) => {\n const spec = loadSpec(cmdOpts.file);\n const validation = validateSpec(spec);\n\n if (!isJsonMode()) {\n console.log(chalk.dim(`\\nSpec: ${cmdOpts.file}\\n`));\n }\n\n if (isJsonMode()) {\n printJson(validation);\n } else {\n printValidation(validation.checks);\n }\n\n if (!validation.valid) {\n process.exitCode = 1;\n }\n });\n}\n\nfunction printValidation(checks: ValidationCheck[]) {\n console.log(chalk.bold(\"Spec Validation\"));\n for (const check of checks) {\n const icon = check.passed ? chalk.green(\"✓\") : chalk.red(\"✗\");\n const msg = check.message\n ? chalk.dim(` — ${check.message}`)\n : \"\";\n console.log(` ${icon} ${check.name}${msg}`);\n }\n}\n","import type {\n AssertionResult,\n LocalSpec,\n ValidationCheck,\n ValidationResult,\n} from \"./types.js\";\n\nexport function validateSpec(spec: LocalSpec): ValidationResult {\n const checks: ValidationCheck[] = [];\n\n checks.push({\n name: \"Has name\",\n passed: Boolean(spec.name?.trim()),\n message: spec.name?.trim() ? undefined : \"Spec is missing a name\",\n });\n\n checks.push({\n name: \"Has system prompt\",\n passed: Boolean(spec.system_prompt?.trim()),\n message: spec.system_prompt?.trim()\n ? undefined\n : \"Spec is missing a system_prompt\",\n });\n\n checks.push({\n name: \"Has base model\",\n passed: Boolean(spec.base_model?.trim()),\n message: spec.base_model?.trim()\n ? undefined\n : \"Spec is missing a base_model\",\n });\n\n const exCount = spec.examples?.length ?? 0;\n checks.push({\n name: \"Has examples\",\n passed: exCount > 0,\n message: exCount > 0 ? `${exCount} example(s)` : \"Add at least one example\",\n });\n\n checks.push({\n name: \"Has guidelines\",\n passed: (spec.guidelines?.length ?? 0) > 0,\n message:\n (spec.guidelines?.length ?? 0) > 0\n ? undefined\n : \"Consider adding guidelines for better eval coverage\",\n });\n\n if (spec.constraints?.length && spec.examples?.length) {\n const violations = checkExamplesAgainstConstraints(spec);\n checks.push({\n name: \"Examples satisfy constraints\",\n passed: violations.length === 0,\n message:\n violations.length === 0\n ? undefined\n : violations.join(\"; \"),\n });\n }\n\n return {\n valid: checks.every((c) => c.passed),\n checks,\n };\n}\n\nfunction checkExamplesAgainstConstraints(spec: LocalSpec): string[] {\n const violations: string[] = [];\n for (const [i, ex] of spec.examples.entries()) {\n for (const constraint of spec.constraints) {\n const result = evaluateConstraint(ex.output, constraint);\n if (!result.passed) {\n violations.push(`Example ${i + 1} violates \"${constraint}\": ${result.message}`);\n }\n }\n }\n return violations;\n}\n\nfunction evaluateConstraint(\n text: string,\n constraint: string,\n): { passed: boolean; message?: string } {\n const lower = constraint.toLowerCase();\n\n const neverMatch = lower.match(/^never (?:share|mention|include|reveal|use|say|output|return|give|provide|show|disclose|expose)\\s+(.+)/);\n if (neverMatch) {\n const forbidden = neverMatch[1].replace(/['\"]/g, \"\").trim();\n if (text.toLowerCase().includes(forbidden.toLowerCase())) {\n return { passed: false, message: `Output contains \"${forbidden}\"` };\n }\n return { passed: true };\n }\n\n const alwaysMatch = lower.match(/^always (?:include|use|start with|end with|contain|respond in|reply in)\\s+(.+)/);\n if (alwaysMatch) {\n const required = alwaysMatch[1].replace(/['\"]/g, \"\").trim();\n if (!text.toLowerCase().includes(required.toLowerCase())) {\n return { passed: false, message: `Output missing \"${required}\"` };\n }\n return { passed: true };\n }\n\n return {\n passed: true,\n message: `Constraint not enforceable by rules: \"${constraint}\" (will be checked by LLM judge if a provider is configured)`,\n };\n}\n\nexport function runAssertions(\n text: string,\n assertions: string[],\n): AssertionResult[] {\n return assertions.map((assertion) => runSingleAssertion(text, assertion));\n}\n\nfunction runSingleAssertion(text: string, assertion: string): AssertionResult {\n const [type, ...rest] = assertion.split(\":\");\n const value = rest.join(\":\");\n\n switch (type) {\n case \"contains\":\n return {\n assertion,\n passed: text.includes(value),\n message: text.includes(value)\n ? undefined\n : `Expected output to contain \"${value}\"`,\n };\n\n case \"not-contains\":\n return {\n assertion,\n passed: !text.includes(value),\n message: !text.includes(value)\n ? undefined\n : `Expected output to not contain \"${value}\"`,\n };\n\n case \"matches\": {\n const re = new RegExp(value);\n const match = re.test(text);\n return {\n assertion,\n passed: match,\n message: match ? undefined : `Output did not match pattern /${value}/`,\n };\n }\n\n case \"max-length\": {\n const max = Number(value);\n return {\n assertion,\n passed: text.length <= max,\n message:\n text.length <= max\n ? undefined\n : `Output length ${text.length} exceeds max ${max}`,\n };\n }\n\n case \"min-length\": {\n const min = Number(value);\n return {\n assertion,\n passed: text.length >= min,\n message:\n text.length >= min\n ? undefined\n : `Output length ${text.length} below min ${min}`,\n };\n }\n\n case \"is-json\": {\n let valid = false;\n try {\n JSON.parse(text);\n valid = true;\n } catch {}\n return {\n assertion,\n passed: valid,\n message: valid ? undefined : \"Output is not valid JSON\",\n };\n }\n\n default:\n return {\n assertion,\n passed: true,\n message: `Unknown assertion type: ${type} (skipped)`,\n };\n }\n}\n\nexport function checkConstraints(\n text: string,\n constraints: string[],\n): AssertionResult[] {\n return constraints.map((constraint) => {\n const result = evaluateConstraint(text, constraint);\n return {\n assertion: `constraint: ${constraint}`,\n passed: result.passed,\n message: result.message,\n };\n });\n}\n","import { Command } from \"commander\";\nimport { readFileSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { post, put, type ClientOpts } from \"../client.js\";\nimport { printSuccess, printJson, isJsonMode, shortId } from \"../output.js\";\nimport { loadSpec, DEFAULT_SPEC_FILE } from \"./init.js\";\nimport { canonicalizeSpecBaseModel } from \"../base-models.js\";\n\ninterface RemoteSpec {\n id: string;\n name: string;\n [key: string]: unknown;\n}\n\nexport function registerPushCommand(parent: Command) {\n parent\n .command(\"push\")\n .description(\"Push local spec to the Tuned Tensor API\")\n .option(\"-f, --file <path>\", \"Spec file path\", DEFAULT_SPEC_FILE)\n .action(async (cmdOpts) => {\n const opts = parent.opts() as ClientOpts;\n const filePath = resolve(cmdOpts.file);\n const spec = loadSpec(cmdOpts.file);\n\n const { id, eval_cases, ...rawBody } = spec as unknown as Record<string, unknown>;\n const body = canonicalizeSpecBaseModel(rawBody);\n\n let data: RemoteSpec;\n\n if (id) {\n const res = await put<RemoteSpec>(`/behavior-specs/${id}`, body, opts);\n data = res.data;\n } else {\n const res = await post<RemoteSpec>(\"/behavior-specs\", body, opts);\n data = res.data;\n\n const raw = JSON.parse(readFileSync(filePath, \"utf-8\"));\n raw.id = data.id;\n writeFileSync(filePath, JSON.stringify(raw, null, 2) + \"\\n\");\n }\n\n if (isJsonMode()) return printJson(data);\n printSuccess(\n `Spec ${id ? \"updated\" : \"created\"}: ${data.name} (${shortId(data.id)})`,\n );\n });\n}\n"],"mappings":"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","names":["readFileSync","chalk","readFileSync","readFileSync","existsSync","readFileSync","statSync","readFileSync","existsSync","statSync","existsSync","mkdirSync","statSync","join","existsSync","statSync","join","mkdirSync","chalk","chalk","chalk","chalk","existsSync","readFileSync","writeFileSync","existsSync","writeFileSync","readFileSync","chalk","chalk","readFileSync","writeFileSync","resolve","resolve","readFileSync","writeFileSync"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tuned-tensor/cli",
3
- "version": "0.4.7",
3
+ "version": "0.4.8",
4
4
  "description": "CLI for Tuned Tensor — fine-tune and evaluate LLMs from the command line",
5
5
  "type": "module",
6
6
  "bin": {