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