@tuned-tensor/cli 0.4.8 → 0.4.10
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 +13 -8
- package/dist/index.js +117 -23
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,7 +36,14 @@ tt init
|
|
|
36
36
|
tt init --name "Customer Support Bot" --model "Qwen/Qwen3.5-2B"
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
Supported spec base models are `Qwen/Qwen3.5-2B`, `google/gemma-4-E2B-it`,
|
|
39
|
+
Supported spec base models are `Qwen/Qwen3.5-2B`, `Qwen/Qwen3.5-4B`, `google/gemma-4-E2B-it`, `google/gemma-4-E4B-it`, `meta-llama/Llama-3.2-3B-Instruct`, `microsoft/Phi-4-mini-instruct`, `ibm-granite/granite-3.3-2b-instruct`, and `bigcode/starcoder2-3b`.
|
|
40
|
+
|
|
41
|
+
You can print the same list from the CLI:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
tt models base
|
|
45
|
+
tt models base --json
|
|
46
|
+
```
|
|
40
47
|
|
|
41
48
|
3) **Validate your spec**
|
|
42
49
|
|
|
@@ -59,7 +66,7 @@ tt runs start <spec-id> --no-llm-judge
|
|
|
59
66
|
tt runs watch <run-id>
|
|
60
67
|
```
|
|
61
68
|
|
|
62
|
-
Tip: use `tt specs list`, `tt datasets list`, `tt runs list`, and `tt models list` to find IDs. Spec, run, and
|
|
69
|
+
Tip: use `tt specs list`, `tt datasets list`, `tt runs list`, and `tt models list` to find IDs. Spec, run, dataset, and model commands accept full UUIDs or unambiguous ID prefixes.
|
|
63
70
|
|
|
64
71
|
## Typical Workflows
|
|
65
72
|
|
|
@@ -89,6 +96,7 @@ tt datasets list
|
|
|
89
96
|
tt datasets get <dataset-id>
|
|
90
97
|
|
|
91
98
|
# Models
|
|
99
|
+
tt models base
|
|
92
100
|
tt models list
|
|
93
101
|
tt models get <model-id>
|
|
94
102
|
tt models download <model-id> --output model.tar.gz
|
|
@@ -107,16 +115,13 @@ Use `--no-llm-judge` with `tt runs start` to opt out of Bedrock LLM judging for
|
|
|
107
115
|
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.
|
|
108
116
|
|
|
109
117
|
```bash
|
|
110
|
-
tt balance # show
|
|
118
|
+
tt balance # show credit balance and recent transactions
|
|
111
119
|
tt topup --amount 25 # opens Stripe Checkout in your browser
|
|
112
120
|
tt topup --amount 25 --no-open # print the URL instead
|
|
113
121
|
```
|
|
114
122
|
|
|
115
|
-
`tt balance`
|
|
116
|
-
|
|
117
|
-
total balance while `Available` is too low to start another run. If a run is
|
|
118
|
-
rejected with `402 insufficient_credits`, top up or wait for active holds to
|
|
119
|
-
settle/release, then retry.
|
|
123
|
+
`tt balance` shows your current credit balance. If a run is rejected with
|
|
124
|
+
`402 insufficient_credits`, top up and retry.
|
|
120
125
|
|
|
121
126
|
## Spec Validation
|
|
122
127
|
|
package/dist/index.js
CHANGED
|
@@ -372,8 +372,13 @@ function resolveModelId(prefix, opts) {
|
|
|
372
372
|
// src/base-models.ts
|
|
373
373
|
var SUPPORTED_BASE_MODELS = [
|
|
374
374
|
"google/gemma-4-E2B-it",
|
|
375
|
-
"google/gemma-4-
|
|
376
|
-
"Qwen/Qwen3.5-2B"
|
|
375
|
+
"google/gemma-4-E4B-it",
|
|
376
|
+
"Qwen/Qwen3.5-2B",
|
|
377
|
+
"Qwen/Qwen3.5-4B",
|
|
378
|
+
"meta-llama/Llama-3.2-3B-Instruct",
|
|
379
|
+
"microsoft/Phi-4-mini-instruct",
|
|
380
|
+
"ibm-granite/granite-3.3-2b-instruct",
|
|
381
|
+
"bigcode/starcoder2-3b"
|
|
377
382
|
];
|
|
378
383
|
var BASE_MODEL_ALIASES = /* @__PURE__ */ new Map();
|
|
379
384
|
for (const model of SUPPORTED_BASE_MODELS) {
|
|
@@ -383,12 +388,24 @@ for (const [alias, model] of [
|
|
|
383
388
|
["google/gemma-4-E2B", "google/gemma-4-E2B-it"],
|
|
384
389
|
["google/gemma-4-e2b", "google/gemma-4-E2B-it"],
|
|
385
390
|
["google/gemma-4-e2b-it", "google/gemma-4-E2B-it"],
|
|
386
|
-
["google/gemma-4-
|
|
387
|
-
["google/gemma-4-
|
|
388
|
-
["google/gemma-4-
|
|
391
|
+
["google/gemma-4-E4B", "google/gemma-4-E4B-it"],
|
|
392
|
+
["google/gemma-4-e4b", "google/gemma-4-E4B-it"],
|
|
393
|
+
["google/gemma-4-e4b-it", "google/gemma-4-E4B-it"],
|
|
389
394
|
["qwen/qwen3.5-2b", "Qwen/Qwen3.5-2B"],
|
|
390
395
|
["Qwen/Qwen3.5-2B-Base", "Qwen/Qwen3.5-2B"],
|
|
391
|
-
["qwen/qwen3.5-2b-base", "Qwen/Qwen3.5-2B"]
|
|
396
|
+
["qwen/qwen3.5-2b-base", "Qwen/Qwen3.5-2B"],
|
|
397
|
+
["qwen/qwen3.5-4b", "Qwen/Qwen3.5-4B"],
|
|
398
|
+
["Qwen/Qwen3.5-4B-Base", "Qwen/Qwen3.5-4B"],
|
|
399
|
+
["qwen/qwen3.5-4b-base", "Qwen/Qwen3.5-4B"],
|
|
400
|
+
["meta-llama/llama-3.2-3b-instruct", "meta-llama/Llama-3.2-3B-Instruct"],
|
|
401
|
+
["meta-llama/Llama-3.2-3B", "meta-llama/Llama-3.2-3B-Instruct"],
|
|
402
|
+
["meta-llama/llama-3.2-3b", "meta-llama/Llama-3.2-3B-Instruct"],
|
|
403
|
+
["microsoft/phi-4-mini-instruct", "microsoft/Phi-4-mini-instruct"],
|
|
404
|
+
["phi-4-mini-instruct", "microsoft/Phi-4-mini-instruct"],
|
|
405
|
+
["ibm-granite/granite-3.3-2b-instruct", "ibm-granite/granite-3.3-2b-instruct"],
|
|
406
|
+
["granite-3.3-2b-instruct", "ibm-granite/granite-3.3-2b-instruct"],
|
|
407
|
+
["bigcode/starcoder2-3b", "bigcode/starcoder2-3b"],
|
|
408
|
+
["starcoder2-3b", "bigcode/starcoder2-3b"]
|
|
392
409
|
]) {
|
|
393
410
|
BASE_MODEL_ALIASES.set(alias.toLowerCase(), model);
|
|
394
411
|
}
|
|
@@ -571,6 +588,13 @@ function formatProgress(run) {
|
|
|
571
588
|
const label = run.stage_label ?? run.current_stage ?? "Progress";
|
|
572
589
|
return run.progress_pct == null ? label : `${label} (${run.progress_pct}%)`;
|
|
573
590
|
}
|
|
591
|
+
function getEvalScore(run) {
|
|
592
|
+
return run.eval_summary?.avg_score ?? run.eval_summary?.mean_score;
|
|
593
|
+
}
|
|
594
|
+
function formatEvalScore(run) {
|
|
595
|
+
const score = getEvalScore(run);
|
|
596
|
+
return score == null ? void 0 : (score * 100).toFixed(1) + "%";
|
|
597
|
+
}
|
|
574
598
|
function registerRunsCommands(parent) {
|
|
575
599
|
const runs = parent.command("runs").description("Manage runs");
|
|
576
600
|
runs.command("list").description("List runs").option("-s, --spec <id>", "Filter by spec ID (full UUID or 8+ char prefix)").option("-p, --page <n>", "Page number", "1").option("--per-page <n>", "Results per page", "20").action(async (cmdOpts) => {
|
|
@@ -593,7 +617,7 @@ function registerRunsCommands(parent) {
|
|
|
593
617
|
r._spec_name ? truncate(r._spec_name, 20) : shortId(r.behavior_spec_id),
|
|
594
618
|
String(r.run_number),
|
|
595
619
|
formatStatus(r.status),
|
|
596
|
-
|
|
620
|
+
formatEvalScore(r) ?? "\u2014",
|
|
597
621
|
formatDate(r.started_at),
|
|
598
622
|
formatDate(r.completed_at)
|
|
599
623
|
]),
|
|
@@ -612,7 +636,7 @@ function registerRunsCommands(parent) {
|
|
|
612
636
|
["Status", formatStatus(data.status)],
|
|
613
637
|
["Stage", formatProgress(data)],
|
|
614
638
|
["Message", data.status_message ?? void 0],
|
|
615
|
-
["Score",
|
|
639
|
+
["Score", formatEvalScore(data)],
|
|
616
640
|
["Pass Rate", data.eval_summary?.pass_rate != null ? (data.eval_summary.pass_rate * 100).toFixed(1) + "%" : void 0],
|
|
617
641
|
["Error", data.error ?? void 0],
|
|
618
642
|
["Started", formatDate(data.started_at)],
|
|
@@ -719,7 +743,7 @@ Eval Results (${data._evals.length}):`);
|
|
|
719
743
|
["Status", formatStatus(run.status)],
|
|
720
744
|
["Stage", formatProgress(run)],
|
|
721
745
|
["Message", run.status_message ?? void 0],
|
|
722
|
-
["Score",
|
|
746
|
+
["Score", formatEvalScore(run)],
|
|
723
747
|
["Error", run.error ?? void 0],
|
|
724
748
|
["Completed", formatDate(run.completed_at)]
|
|
725
749
|
]);
|
|
@@ -733,6 +757,54 @@ function formatBytes(bytes) {
|
|
|
733
757
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
734
758
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
735
759
|
}
|
|
760
|
+
var FORBIDDEN_CONTROL_CODEPOINTS = [
|
|
761
|
+
// C0 control chars except whitespace we explicitly allow inside string values.
|
|
762
|
+
// U+0009 TAB, U+000A LF, U+000D CR are kept since they appear in normal text.
|
|
763
|
+
{ code: 0, name: "NULL" },
|
|
764
|
+
{ code: 1, name: "START OF HEADING" },
|
|
765
|
+
{ code: 2, name: "START OF TEXT" },
|
|
766
|
+
{ code: 3, name: "END OF TEXT" },
|
|
767
|
+
{ code: 4, name: "END OF TRANSMISSION" },
|
|
768
|
+
{ code: 5, name: "ENQUIRY" },
|
|
769
|
+
{ code: 6, name: "ACKNOWLEDGE" },
|
|
770
|
+
{ code: 7, name: "BELL" },
|
|
771
|
+
{ code: 8, name: "BACKSPACE" },
|
|
772
|
+
{ code: 11, name: "VERTICAL TAB" },
|
|
773
|
+
{ code: 12, name: "FORM FEED" },
|
|
774
|
+
{ code: 14, name: "SHIFT OUT" },
|
|
775
|
+
{ code: 15, name: "SHIFT IN" },
|
|
776
|
+
// 0x10..0x1F all rejected; named lookup falls back to "CONTROL CHARACTER".
|
|
777
|
+
{ code: 28, name: "FILE SEPARATOR" },
|
|
778
|
+
{ code: 29, name: "GROUP SEPARATOR" },
|
|
779
|
+
{ code: 30, name: "RECORD SEPARATOR" },
|
|
780
|
+
// C1 control range U+0080..U+009F (all invisible, often mojibake from
|
|
781
|
+
// Windows-1252 smart quotes mis-tagged as Unicode codepoints).
|
|
782
|
+
{ code: 133, name: "NEXT LINE" },
|
|
783
|
+
// Unicode line/paragraph separators - cut lines too.
|
|
784
|
+
{ code: 8232, name: "LINE SEPARATOR" },
|
|
785
|
+
{ code: 8233, name: "PARAGRAPH SEPARATOR" }
|
|
786
|
+
];
|
|
787
|
+
function findControlChar(value) {
|
|
788
|
+
for (let i = 0; i < value.length; i++) {
|
|
789
|
+
const code = value.charCodeAt(i);
|
|
790
|
+
if (code < 32 && code !== 9 && code !== 10 && code !== 13) {
|
|
791
|
+
const named = FORBIDDEN_CONTROL_CODEPOINTS.find((entry) => entry.code === code);
|
|
792
|
+
return { codepoint: code, offset: i, name: named?.name ?? "CONTROL CHARACTER" };
|
|
793
|
+
}
|
|
794
|
+
if (code >= 128 && code <= 159) {
|
|
795
|
+
const named = FORBIDDEN_CONTROL_CODEPOINTS.find((entry) => entry.code === code);
|
|
796
|
+
return { codepoint: code, offset: i, name: named?.name ?? "C1 CONTROL CHARACTER" };
|
|
797
|
+
}
|
|
798
|
+
if (code === 8232 || code === 8233) {
|
|
799
|
+
const named = FORBIDDEN_CONTROL_CODEPOINTS.find((entry) => entry.code === code);
|
|
800
|
+
return { codepoint: code, offset: i, name: named?.name ?? "LINE BREAK" };
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
return null;
|
|
804
|
+
}
|
|
805
|
+
function formatCodepoint(code) {
|
|
806
|
+
return `U+${code.toString(16).toUpperCase().padStart(4, "0")}`;
|
|
807
|
+
}
|
|
736
808
|
function validateDatasetFile(file) {
|
|
737
809
|
const lines = readFileSync4(file, "utf8").split(/\r?\n/);
|
|
738
810
|
const errors = [];
|
|
@@ -766,6 +838,16 @@ function validateDatasetFile(file) {
|
|
|
766
838
|
if (typeof record.output !== "string") {
|
|
767
839
|
errors.push(`Row ${rowNumber}: missing string "output" field`);
|
|
768
840
|
}
|
|
841
|
+
for (const field of ["input", "output"]) {
|
|
842
|
+
const value = record[field];
|
|
843
|
+
if (typeof value !== "string") continue;
|
|
844
|
+
const hit = findControlChar(value);
|
|
845
|
+
if (hit) {
|
|
846
|
+
errors.push(
|
|
847
|
+
`Row ${rowNumber}: field "${field}" contains invisible control character ${formatCodepoint(hit.codepoint)} (${hit.name}) at offset ${hit.offset} \u2014 strip or escape before uploading; some training paths split on it`
|
|
848
|
+
);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
769
851
|
}
|
|
770
852
|
if (rowCount === 0) {
|
|
771
853
|
errors.push("File contains no JSONL rows");
|
|
@@ -913,6 +995,18 @@ async function downloadUrlToFile(url, outputPath) {
|
|
|
913
995
|
}
|
|
914
996
|
function registerModelsCommands(parent) {
|
|
915
997
|
const models = parent.command("models").description("Manage fine-tuned models");
|
|
998
|
+
models.command("base").description("List supported base models").action(async () => {
|
|
999
|
+
const data = SUPPORTED_BASE_MODELS.map((model) => ({
|
|
1000
|
+
id: model,
|
|
1001
|
+
name: model.split("/").pop() || model,
|
|
1002
|
+
type: "base"
|
|
1003
|
+
}));
|
|
1004
|
+
if (isJsonMode()) return printJson({ data });
|
|
1005
|
+
printTable(
|
|
1006
|
+
["ID", "Name", "Type"],
|
|
1007
|
+
data.map((m) => [m.id, m.name, m.type])
|
|
1008
|
+
);
|
|
1009
|
+
});
|
|
916
1010
|
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) => {
|
|
917
1011
|
const opts = parent.opts();
|
|
918
1012
|
const { data, meta } = await get(
|
|
@@ -933,9 +1027,10 @@ function registerModelsCommands(parent) {
|
|
|
933
1027
|
meta
|
|
934
1028
|
);
|
|
935
1029
|
});
|
|
936
|
-
models.command("get").description("Show model details").argument("<id>", "Model ID").action(async (id) => {
|
|
1030
|
+
models.command("get").description("Show model details").argument("<id>", "Model ID (full UUID or 4+ char prefix)").action(async (id) => {
|
|
937
1031
|
const opts = parent.opts();
|
|
938
|
-
const
|
|
1032
|
+
const fullId = await resolveModelId(id, opts);
|
|
1033
|
+
const { data } = await get(`/models/${fullId}`, void 0, opts);
|
|
939
1034
|
if (isJsonMode()) return printJson(data);
|
|
940
1035
|
printDetail([
|
|
941
1036
|
["ID", data.id],
|
|
@@ -972,11 +1067,12 @@ function registerModelsCommands(parent) {
|
|
|
972
1067
|
const size = bytes == null ? "" : ` (${bytes} bytes)`;
|
|
973
1068
|
printSuccess(`Model downloaded to ${outputPath}${size}`);
|
|
974
1069
|
});
|
|
975
|
-
models.command("delete").description("Delete a model").argument("<id>", "Model ID").action(async (id) => {
|
|
1070
|
+
models.command("delete").description("Delete a model").argument("<id>", "Model ID (full UUID or 4+ char prefix)").action(async (id) => {
|
|
976
1071
|
const opts = parent.opts();
|
|
977
|
-
await
|
|
978
|
-
|
|
979
|
-
|
|
1072
|
+
const fullId = await resolveModelId(id, opts);
|
|
1073
|
+
await del(`/models/${fullId}`, opts);
|
|
1074
|
+
if (isJsonMode()) return printJson({ id: fullId, deleted: true });
|
|
1075
|
+
printSuccess(`Model deleted: ${shortId(fullId)}`);
|
|
980
1076
|
});
|
|
981
1077
|
}
|
|
982
1078
|
|
|
@@ -1001,7 +1097,7 @@ function formatSigned(cents) {
|
|
|
1001
1097
|
return formatCents(cents);
|
|
1002
1098
|
}
|
|
1003
1099
|
function registerBalanceCommands(parent) {
|
|
1004
|
-
parent.command("balance").description("Show
|
|
1100
|
+
parent.command("balance").description("Show credit balance and recent transactions").option("-n, --limit <n>", "Number of transactions to show (default 10)", "10").action(async (options) => {
|
|
1005
1101
|
const opts = parent.opts();
|
|
1006
1102
|
const limit = Number(options.limit) || 10;
|
|
1007
1103
|
const [{ data: balance }, { data: transactions }] = await Promise.all([
|
|
@@ -1011,12 +1107,10 @@ function registerBalanceCommands(parent) {
|
|
|
1011
1107
|
if (isJsonMode()) {
|
|
1012
1108
|
return printJson({ balance, transactions });
|
|
1013
1109
|
}
|
|
1014
|
-
const lowBalance = balance.
|
|
1015
|
-
const
|
|
1110
|
+
const lowBalance = balance.balance_cents < 100;
|
|
1111
|
+
const balanceLine = lowBalance ? chalk3.red(formatCents(balance.balance_cents)) + chalk3.dim(" (low)") : chalk3.bold.green(formatCents(balance.balance_cents));
|
|
1016
1112
|
printDetail([
|
|
1017
|
-
["
|
|
1018
|
-
["Total balance", formatCents(balance.balance_cents)],
|
|
1019
|
-
["On hold", formatCents(balance.reserved_cents)],
|
|
1113
|
+
["Credits", balanceLine],
|
|
1020
1114
|
["Lifetime top-ups", formatCents(balance.lifetime_topup_cents)]
|
|
1021
1115
|
]);
|
|
1022
1116
|
if (transactions && transactions.length > 0) {
|
|
@@ -1042,7 +1136,7 @@ ${chalk3.dim("No transactions yet \u2014 run `tt topup` to add credits.")}`
|
|
|
1042
1136
|
console.log(
|
|
1043
1137
|
`
|
|
1044
1138
|
${formatStatus("preparing")} ${chalk3.yellow(
|
|
1045
|
-
"Run `tt topup` to add more
|
|
1139
|
+
"Run `tt topup` to add more credits before starting a run."
|
|
1046
1140
|
)}`
|
|
1047
1141
|
);
|
|
1048
1142
|
}
|
|
@@ -1323,7 +1417,7 @@ function registerPushCommand(parent) {
|
|
|
1323
1417
|
|
|
1324
1418
|
// src/index.ts
|
|
1325
1419
|
var program = new Command();
|
|
1326
|
-
program.name("tt").description("Tuned Tensor CLI \u2014 fine-tune and evaluate LLMs").version("0.4.
|
|
1420
|
+
program.name("tt").description("Tuned Tensor CLI \u2014 fine-tune and evaluate LLMs").version("0.4.10").option("-k, --api-key <key>", "API key (overrides stored key)").option(
|
|
1327
1421
|
"-u, --base-url <url>",
|
|
1328
1422
|
"API base URL (default: https://tunedtensor.com)"
|
|
1329
1423
|
).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/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"]}
|
|
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-E4B-it\",\n \"Qwen/Qwen3.5-2B\",\n \"Qwen/Qwen3.5-4B\",\n \"meta-llama/Llama-3.2-3B-Instruct\",\n \"microsoft/Phi-4-mini-instruct\",\n \"ibm-granite/granite-3.3-2b-instruct\",\n \"bigcode/starcoder2-3b\",\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-E4B\", \"google/gemma-4-E4B-it\"],\n [\"google/gemma-4-e4b\", \"google/gemma-4-E4B-it\"],\n [\"google/gemma-4-e4b-it\", \"google/gemma-4-E4B-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 [\"qwen/qwen3.5-4b\", \"Qwen/Qwen3.5-4B\"],\n [\"Qwen/Qwen3.5-4B-Base\", \"Qwen/Qwen3.5-4B\"],\n [\"qwen/qwen3.5-4b-base\", \"Qwen/Qwen3.5-4B\"],\n [\"meta-llama/llama-3.2-3b-instruct\", \"meta-llama/Llama-3.2-3B-Instruct\"],\n [\"meta-llama/Llama-3.2-3B\", \"meta-llama/Llama-3.2-3B-Instruct\"],\n [\"meta-llama/llama-3.2-3b\", \"meta-llama/Llama-3.2-3B-Instruct\"],\n [\"microsoft/phi-4-mini-instruct\", \"microsoft/Phi-4-mini-instruct\"],\n [\"phi-4-mini-instruct\", \"microsoft/Phi-4-mini-instruct\"],\n [\"ibm-granite/granite-3.3-2b-instruct\", \"ibm-granite/granite-3.3-2b-instruct\"],\n [\"granite-3.3-2b-instruct\", \"ibm-granite/granite-3.3-2b-instruct\"],\n [\"bigcode/starcoder2-3b\", \"bigcode/starcoder2-3b\"],\n [\"starcoder2-3b\", \"bigcode/starcoder2-3b\"],\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: { avg_score?: number; 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\nfunction getEvalScore(run: Run): number | undefined {\n return run.eval_summary?.avg_score ?? run.eval_summary?.mean_score;\n}\n\nfunction formatEvalScore(run: Run): string | undefined {\n const score = getEvalScore(run);\n return score == null ? undefined : (score * 100).toFixed(1) + \"%\";\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 formatEvalScore(r) ?? \"—\",\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\", formatEvalScore(data)],\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\", formatEvalScore(run)],\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\n// Invisible characters that JSON parsers accept but downstream JSONL consumers\n// often mishandle. Concretely: Python's str.splitlines() treats every char in\n// this set as a line break, so a row containing one of them gets cut in half\n// before json.loads sees it. We strip these at validate-time so the failure\n// mode is \"row 1099 has U+0085 at offset 4078\" (seconds, locally) instead of\n// \"AlgorithmError: exit code 1\" after a training launch (minutes, remote).\nconst FORBIDDEN_CONTROL_CODEPOINTS: ReadonlyArray<{ code: number; name: string }> = [\n // C0 control chars except whitespace we explicitly allow inside string values.\n // U+0009 TAB, U+000A LF, U+000D CR are kept since they appear in normal text.\n { code: 0x00, name: \"NULL\" },\n { code: 0x01, name: \"START OF HEADING\" },\n { code: 0x02, name: \"START OF TEXT\" },\n { code: 0x03, name: \"END OF TEXT\" },\n { code: 0x04, name: \"END OF TRANSMISSION\" },\n { code: 0x05, name: \"ENQUIRY\" },\n { code: 0x06, name: \"ACKNOWLEDGE\" },\n { code: 0x07, name: \"BELL\" },\n { code: 0x08, name: \"BACKSPACE\" },\n { code: 0x0b, name: \"VERTICAL TAB\" },\n { code: 0x0c, name: \"FORM FEED\" },\n { code: 0x0e, name: \"SHIFT OUT\" },\n { code: 0x0f, name: \"SHIFT IN\" },\n // 0x10..0x1F all rejected; named lookup falls back to \"CONTROL CHARACTER\".\n { code: 0x1c, name: \"FILE SEPARATOR\" },\n { code: 0x1d, name: \"GROUP SEPARATOR\" },\n { code: 0x1e, name: \"RECORD SEPARATOR\" },\n // C1 control range U+0080..U+009F (all invisible, often mojibake from\n // Windows-1252 smart quotes mis-tagged as Unicode codepoints).\n { code: 0x0085, name: \"NEXT LINE\" },\n // Unicode line/paragraph separators - cut lines too.\n { code: 0x2028, name: \"LINE SEPARATOR\" },\n { code: 0x2029, name: \"PARAGRAPH SEPARATOR\" },\n];\n\nfunction findControlChar(value: string): { codepoint: number; offset: number; name: string } | null {\n for (let i = 0; i < value.length; i++) {\n const code = value.charCodeAt(i);\n // Whitelist real whitespace; everything in C0 below 0x20 (besides tab/LF/CR) is hazardous.\n if (code < 0x20 && code !== 0x09 && code !== 0x0a && code !== 0x0d) {\n const named = FORBIDDEN_CONTROL_CODEPOINTS.find((entry) => entry.code === code);\n return { codepoint: code, offset: i, name: named?.name ?? \"CONTROL CHARACTER\" };\n }\n // C1 control range - all hazardous (NEL, etc.); JSON parsers accept these\n // but Python's splitlines() splits on several of them.\n if (code >= 0x80 && code <= 0x9f) {\n const named = FORBIDDEN_CONTROL_CODEPOINTS.find((entry) => entry.code === code);\n return { codepoint: code, offset: i, name: named?.name ?? \"C1 CONTROL CHARACTER\" };\n }\n if (code === 0x2028 || code === 0x2029) {\n const named = FORBIDDEN_CONTROL_CODEPOINTS.find((entry) => entry.code === code);\n return { codepoint: code, offset: i, name: named?.name ?? \"LINE BREAK\" };\n }\n }\n return null;\n}\n\nfunction formatCodepoint(code: number): string {\n return `U+${code.toString(16).toUpperCase().padStart(4, \"0\")}`;\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 for (const field of [\"input\", \"output\"] as const) {\n const value = record[field];\n if (typeof value !== \"string\") continue;\n const hit = findControlChar(value);\n if (hit) {\n errors.push(\n `Row ${rowNumber}: field \"${field}\" contains invisible control character ${formatCodepoint(hit.codepoint)} (${hit.name}) at offset ${hit.offset} — strip or escape before uploading; some training paths split on it`,\n );\n }\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 { SUPPORTED_BASE_MODELS } from \"../base-models.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(\"base\")\n .description(\"List supported base models\")\n .action(async () => {\n const data = SUPPORTED_BASE_MODELS.map((model) => ({\n id: model,\n name: model.split(\"/\").pop() || model,\n type: \"base\" as const,\n }));\n\n if (isJsonMode()) return printJson({ data });\n\n printTable(\n [\"ID\", \"Name\", \"Type\"],\n data.map((m) => [m.id, m.name, m.type]),\n );\n });\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 (full UUID or 4+ char prefix)\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const fullId = await resolveModelId(id, opts);\n const { data } = await get<Model>(`/models/${fullId}`, 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 (full UUID or 4+ char prefix)\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const fullId = await resolveModelId(id, opts);\n await del(`/models/${fullId}`, opts);\n\n if (isJsonMode()) return printJson({ id: fullId, deleted: true });\n printSuccess(`Model deleted: ${shortId(fullId)}`);\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 credit balance 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.balance_cents < 100;\n const balanceLine = lowBalance\n ? chalk.red(formatCents(balance.balance_cents)) + chalk.dim(\" (low)\")\n : chalk.bold.green(formatCents(balance.balance_cents));\n\n printDetail([\n [\"Credits\", balanceLine],\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 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"]}
|