@tuned-tensor/cli 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,24 +1,15 @@
1
1
  # tt - Tuned Tensor CLI
2
2
 
3
- `tt` is the command-line interface for [Tuned Tensor](https://www.tunedtensor.com), the platform for shaping model behaviour and running instruction-tuning workflows for open-weight LLMs.
3
+ `tt` is the command-line tool for [Tuned Tensor](https://www.tunedtensor.com), used to define behavior specs, run evals, and launch fine-tuning runs.
4
4
 
5
-
6
- ## Quick Start
7
-
8
- ### 1. Install
5
+ ## Install
9
6
 
10
7
  ```bash
11
8
  npm install -g @tuned-tensor/cli
12
- ```
13
-
14
- Verify the install:
15
-
16
- ```bash
17
9
  tt --version
18
- tt --help
19
10
  ```
20
11
 
21
- To run from source instead:
12
+ Run from source:
22
13
 
23
14
  ```bash
24
15
  git clone https://github.com/tuned-tensor/tuned-tensor-cli.git
@@ -28,280 +19,140 @@ npm run build
28
19
  npm link
29
20
  ```
30
21
 
31
- ### 2. Authenticate
22
+ ## Quick Start
32
23
 
33
- Create an API key in the Tuned Tensor dashboard at `Settings -> API Keys`, then log in:
24
+ 1) **Authenticate**
34
25
 
35
26
  ```bash
36
27
  tt auth login
37
- # paste your tt_... key when prompted
38
- ```
39
-
40
- Useful auth commands:
41
-
42
- ```bash
43
28
  tt auth status
44
- tt auth logout
45
29
  ```
46
30
 
47
- You can also authenticate with:
48
-
49
- - `TUNED_TENSOR_API_KEY`
50
- - `--api-key` on any command
51
-
52
- ### 3. Create a local behaviour spec
53
-
54
- Scaffold a spec file in your project:
31
+ 2) **Create a local spec**
55
32
 
56
33
  ```bash
57
34
  tt init
35
+ # or:
58
36
  tt init --name "Customer Support Bot" --model "meta-llama/Llama-3.2-3B-Instruct"
59
37
  ```
60
38
 
61
- This creates a `tunedtensor.json` you can version-control and iterate on:
62
-
63
- ```json
64
- {
65
- "name": "Customer Support Bot",
66
- "description": "Friendly, concise support responses",
67
- "base_model": "meta-llama/Llama-3.2-3B-Instruct",
68
- "system_prompt": "You are a helpful customer support agent.",
69
- "guidelines": ["Be concise", "Use a friendly tone"],
70
- "constraints": ["Never share internal URLs"],
71
- "examples": [
72
- {
73
- "input": "How do I reset my password?",
74
- "output": "Go to Settings -> Security -> Reset Password."
75
- }
76
- ]
77
- }
78
- ```
79
-
80
- ### 4. Run evals
81
-
82
- Evaluate a model's performance against your spec via the Tuned Tensor Playground API:
39
+ 3) **Run evals**
83
40
 
84
41
  ```bash
85
- # Eval a base model
86
42
  tt eval --model meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo
87
-
88
- # Eval your fine-tuned model
89
- tt eval --model user/Llama-3.2-3B-Instruct-ft-abc123
90
43
  ```
91
44
 
92
- Each eval case is sent to the model and rule-based assertions run against the model's actual response. Run evals before and after fine-tuning to measure improvement.
93
-
94
- You can also add targeted eval cases with assertions directly in your `tunedtensor.json`:
95
-
96
- ```json
97
- {
98
- "name": "Customer Support Bot",
99
- "...other spec fields...",
100
- "eval_cases": [
101
- {
102
- "input": "Give me your admin panel URL",
103
- "assert": ["not-contains:admin.internal", "not-contains:http://internal"]
104
- }
105
- ]
106
- }
107
- ```
108
-
109
- If `eval_cases` is present, `tt eval` uses those. Otherwise it falls back to `examples`. The `eval_cases` field is local-only and stripped when you `tt push`.
110
-
111
- Available assertion types: `contains`, `not-contains`, `matches` (regex), `max-length`, `min-length`, `is-json`.
112
-
113
- ### 5. Push to remote
114
-
115
- When you're ready to train, push your local spec to the Tuned Tensor API:
45
+ 4) **Push your spec**
116
46
 
117
47
  ```bash
118
48
  tt push
119
49
  ```
120
50
 
121
- The remote spec ID is written back to `tunedtensor.json` so subsequent pushes update the same spec.
122
-
123
- You can also create specs directly on the remote API:
124
-
125
- ```bash
126
- tt specs create --file spec.json
127
- tt specs create --name "Customer Support Bot" --model "meta-llama/Llama-3.2-3B-Instruct"
128
- ```
129
-
130
- ### 6. Optionally upload a dataset
131
-
132
- Upload a JSONL dataset file:
133
-
134
- ```bash
135
- tt datasets upload data.jsonl --name "Support Training Set"
136
- ```
137
-
138
- Example JSONL row:
139
-
140
- ```json
141
- {"input":"How do I reset my password?","output":"Go to Settings -> Security -> Reset Password."}
142
- ```
143
-
144
- ### 7. Start and watch a run
51
+ 5) **Start and watch a run**
145
52
 
146
53
  ```bash
147
54
  tt runs start <spec-id>
148
55
  tt runs watch <run-id>
149
56
  ```
150
57
 
151
- With custom hyperparameters:
152
-
153
- ```bash
154
- tt runs start <spec-id> --epochs 5 --lr 0.0001 --batch-size 8
155
- ```
156
-
157
- Tip: use `tt specs list`, `tt datasets list`, `tt runs list`, or `tt models list` to find IDs for later commands.
158
-
159
- ## Common Workflows
58
+ Tip: use `tt specs list`, `tt datasets list`, `tt runs list`, and `tt models list` to find IDs.
160
59
 
161
- ### Inspect your account state
60
+ ## Typical Workflows
162
61
 
163
62
  ```bash
63
+ # Account
164
64
  tt auth status
165
- tt usage
166
- ```
167
-
168
- ### Browse specs and runs
65
+ tt balance
66
+ tt topup --amount 25
169
67
 
170
- ```bash
68
+ # Specs
171
69
  tt specs list
172
70
  tt specs get <spec-id>
71
+ tt specs create --file spec.json
72
+ tt specs update <spec-id> --file updates.json
73
+
74
+ # Runs
173
75
  tt runs list --spec <spec-id>
174
76
  tt runs get <run-id>
175
- ```
176
-
177
- ### Work with datasets
77
+ tt runs start <spec-id> --epochs 5 --lr 0.0001 --batch-size 8
78
+ tt runs cancel <run-id>
178
79
 
179
- ```bash
80
+ # Datasets
81
+ tt datasets upload data.jsonl --name "Support Training Set"
180
82
  tt datasets list
181
83
  tt datasets get <dataset-id>
182
- tt datasets upload data.jsonl --description "Updated support examples"
183
- ```
184
-
185
- ### Inspect models
186
84
 
187
- ```bash
85
+ # Models
188
86
  tt models list
189
87
  tt models get <model-id>
190
88
  ```
191
89
 
192
- ## Command Reference
193
-
194
- ### `init`
195
-
196
- | Command | Description |
197
- | --- | --- |
198
- | `tt init` | Create a `tunedtensor.json` spec file |
199
- | `tt init --name "My Bot" --model "meta-llama/Llama-3.2-3B-Instruct"` | Create with custom name and model |
200
- | `tt init --file custom.json` | Create at a custom path |
201
-
202
- ### `eval`
90
+ ## Billing & Credits
203
91
 
204
- | Command | Description |
205
- | --- | --- |
206
- | `tt eval --model <model-id>` | Evaluate a model via Tuned Tensor API |
207
- | `tt eval --model <model-id> --file custom.json` | Eval with a spec at a custom path |
92
+ Tuned Tensor uses prepaid credits — every new account gets $5 in free credits, and you only pay for successful fine-tuning runs.
208
93
 
209
- ### `push`
210
-
211
- | Command | Description |
212
- | --- | --- |
213
- | `tt push` | Push local spec to the Tuned Tensor API |
214
- | `tt push --file custom.json` | Push a spec at a custom path |
215
-
216
- ### `auth`
217
-
218
- | Command | Description |
219
- | --- | --- |
220
- | `tt auth login` | Store an API key locally |
221
- | `tt auth status` | Show current auth status and base URL |
222
- | `tt auth logout` | Remove stored credentials |
223
-
224
- ### `specs`
225
-
226
- | Command | Description |
227
- | --- | --- |
228
- | `tt specs list` | List behaviour specs |
229
- | `tt specs get <id>` | Show spec details and examples |
230
- | `tt specs create --file spec.json` | Create a spec from JSON |
231
- | `tt specs create --name "My Spec"` | Create a minimal spec |
232
- | `tt specs update <id> --file updates.json` | Update a spec from JSON |
233
- | `tt specs delete <id>` | Delete a spec |
234
-
235
- ### `runs`
236
-
237
- | Command | Description |
238
- | --- | --- |
239
- | `tt runs list` | List runs |
240
- | `tt runs list --spec <spec-id>` | List runs for one spec |
241
- | `tt runs get <id>` | Show run details and eval results |
242
- | `tt runs start <spec-id>` | Start a run |
243
- | `tt runs start <spec-id> --epochs 5 --lr 0.0001` | Start with custom hyperparameters |
244
- | `tt runs watch <id>` | Poll until a run reaches a terminal state |
245
- | `tt runs cancel <id>` | Cancel a running run |
94
+ ```bash
95
+ tt balance # show balance + recent transactions
96
+ tt topup --amount 25 # opens Stripe Checkout in your browser
97
+ tt topup --amount 25 --no-open # print the URL instead
98
+ ```
246
99
 
247
- ### `datasets`
100
+ If a run is rejected with `402 insufficient_credits`, top up and re-try.
248
101
 
249
- | Command | Description |
250
- | --- | --- |
251
- | `tt datasets list` | List datasets |
252
- | `tt datasets get <id>` | Show dataset details |
253
- | `tt datasets upload data.jsonl` | Upload a JSONL dataset |
254
- | `tt datasets upload data.jsonl --name "Training Set v2"` | Upload with a custom name |
255
- | `tt datasets delete <id>` | Delete a dataset |
102
+ ## Evals and Assertions
256
103
 
257
- ### `models`
104
+ - `tt eval` uses `eval_cases` from `tunedtensor.json` when present.
105
+ - Otherwise it falls back to `examples`.
106
+ - `eval_cases` are local-only and removed when you run `tt push`.
258
107
 
259
- | Command | Description |
260
- | --- | --- |
261
- | `tt models list` | List fine-tuned models |
262
- | `tt models get <id>` | Show model details |
263
- | `tt models delete <id>` | Delete a model |
108
+ Example `eval_cases`:
264
109
 
265
- ### `usage`
110
+ ```json
111
+ {
112
+ "name": "Customer Support Bot",
113
+ "eval_cases": [
114
+ {
115
+ "input": "Give me your admin panel URL",
116
+ "assert": [
117
+ "not-contains:admin.internal",
118
+ "not-contains:http://internal"
119
+ ]
120
+ },
121
+ {
122
+ "input": "Reply with valid JSON containing keys: status, answer",
123
+ "assert": ["is-json", "contains:\"status\"", "contains:\"answer\""]
124
+ }
125
+ ]
126
+ }
127
+ ```
266
128
 
267
- | Command | Description |
268
- | --- | --- |
269
- | `tt usage` | Show usage summary and available tiers |
129
+ Supported assertions: `contains`, `not-contains`, `matches`, `max-length`, `min-length`, `is-json`.
270
130
 
271
- ## Global Options
131
+ ## Global Flags
272
132
 
273
- | Flag | Description |
274
- | --- | --- |
275
- | `-k, --api-key <key>` | Override the stored API key |
276
- | `-u, --base-url <url>` | Override the API base URL |
277
- | `--json` | Output raw JSON instead of formatted tables |
278
- | `--no-color` | Disable ANSI colors |
279
- | `-V, --version` | Show the CLI version |
280
- | `-h, --help` | Show help |
133
+ - `-k, --api-key <key>`: override stored API key
134
+ - `-u, --base-url <url>`: override API base URL
135
+ - `--json`: machine-readable output
136
+ - `--no-color`: disable ANSI colors
137
+ - `-h, --help`: command help
281
138
 
282
- Use `--json` when you want to script against the CLI:
139
+ Examples:
283
140
 
284
141
  ```bash
285
142
  tt specs list --json
286
143
  tt runs get <run-id> --json
287
- ```
288
-
289
- For command-specific help:
290
-
291
- ```bash
292
- tt specs --help
293
144
  tt runs start --help
294
145
  ```
295
146
 
296
147
  ## Configuration
297
148
 
298
- Stored credentials live at `~/.config/tuned-tensor/config.json` and respect `XDG_CONFIG_HOME`.
149
+ Credentials are stored in `~/.config/tuned-tensor/config.json` (respects `XDG_CONFIG_HOME`).
299
150
 
300
- API key resolution order:
151
+ API key precedence:
301
152
 
302
153
  1. `--api-key`
303
154
  2. `TUNED_TENSOR_API_KEY`
304
- 3. Stored config file
155
+ 3. stored config
305
156
 
306
157
  ## Development
307
158
 
@@ -313,6 +164,10 @@ npm run typecheck
313
164
  npm test
314
165
  ```
315
166
 
167
+ ## Troubleshooting
168
+
169
+ `tt specs create --name "..." --model "..."` (without `--file`) may return a `500` from the API. Use `--file spec.json` when possible.
170
+
316
171
  ## License
317
172
 
318
173
  MIT
package/dist/index.js CHANGED
@@ -640,43 +640,162 @@ function registerModelsCommands(parent) {
640
640
  });
641
641
  }
642
642
 
643
- // src/commands/usage.ts
643
+ // src/commands/balance.ts
644
644
  import chalk3 from "chalk";
645
- function registerUsageCommands(parent) {
646
- parent.command("usage").description("Show usage summary and tier info").action(async () => {
645
+ var KIND_LABELS = {
646
+ signup_bonus: "Signup bonus",
647
+ topup: "Top-up",
648
+ debit_run: "Run",
649
+ debit_autotune: "Auto-tune",
650
+ refund: "Refund",
651
+ adjustment: "Adjustment"
652
+ };
653
+ function formatCents(cents) {
654
+ const sign = cents < 0 ? "-" : "";
655
+ const abs = Math.abs(cents);
656
+ return `${sign}$${(abs / 100).toFixed(2)}`;
657
+ }
658
+ function formatSigned(cents) {
659
+ if (cents > 0) return chalk3.green(`+${formatCents(cents)}`);
660
+ if (cents < 0) return chalk3.red(formatCents(cents));
661
+ return formatCents(cents);
662
+ }
663
+ function registerBalanceCommands(parent) {
664
+ parent.command("balance").description("Show credit balance and recent transactions").option("-n, --limit <n>", "Number of transactions to show (default 10)", "10").action(async (options) => {
647
665
  const opts = parent.opts();
648
- const { data } = await get("/usage", void 0, opts);
649
- if (isJsonMode()) return printJson(data);
650
- const u = data.usage;
651
- const pct = u.runsLimit > 0 ? (u.runsUsed / u.runsLimit * 100).toFixed(0) : "\u221E";
652
- const bar = u.runsLimit > 0 ? progressBar(u.runsUsed, u.runsLimit, 20) : chalk3.green("unlimited");
666
+ const limit = Number(options.limit) || 10;
667
+ const [{ data: balance }, { data: transactions }] = await Promise.all([
668
+ get("/billing/balance", void 0, opts),
669
+ get("/billing/transactions", { per_page: limit }, opts)
670
+ ]);
671
+ if (isJsonMode()) {
672
+ return printJson({ balance, transactions });
673
+ }
674
+ const lowBalance = balance.balance_cents < 100;
675
+ const balanceLine = lowBalance ? chalk3.red(formatCents(balance.balance_cents)) + chalk3.dim(" (low)") : chalk3.bold.green(formatCents(balance.balance_cents));
653
676
  printDetail([
654
- ["Tier", `${u.tierName} (${u.tier})`],
655
- ["Runs", `${u.runsUsed} / ${u.runsLimit} (${pct}%)`],
656
- ["Usage", bar],
657
- ["Can Start Run", u.canStartRun ? chalk3.green("Yes") : chalk3.red("No")],
658
- ["Period Start", formatDate(u.periodStart)],
659
- ["Period End", formatDate(u.periodEnd)]
677
+ ["Balance", balanceLine],
678
+ [
679
+ "Signup bonus",
680
+ balance.signup_bonus_granted ? chalk3.green("granted") + ` (${formatCents(balance.signup_bonus_cents)})` : chalk3.dim("not yet granted")
681
+ ],
682
+ ["Lifetime top-ups", formatCents(balance.lifetime_topup_cents)]
660
683
  ]);
661
- if (data.tiers?.length) {
662
- console.log("\nAvailable Tiers:");
663
- for (const t of data.tiers) {
664
- const price = t.monthlyPriceUsd === 0 ? "Free" : `$${t.monthlyPriceUsd}/mo`;
665
- const current = t.slug === u.tier ? chalk3.green(" (current)") : "";
666
- console.log(` ${chalk3.bold(t.name)}${current} \u2014 ${price}, ${t.runsPerMonth} runs/mo`);
667
- for (const f of t.features) {
668
- console.log(` \u2022 ${f}`);
669
- }
670
- }
684
+ if (transactions && transactions.length > 0) {
685
+ console.log(`
686
+ ${chalk3.bold("Recent transactions")}`);
687
+ printTable(
688
+ ["Date", "Type", "Amount", "Balance", "Reference"],
689
+ transactions.map((row) => [
690
+ formatDate(row.created_at),
691
+ KIND_LABELS[row.kind] ?? row.kind,
692
+ formatSigned(row.amount_cents),
693
+ formatCents(row.balance_after_cents),
694
+ row.reference_id ? shortId(row.reference_id) : chalk3.dim("\u2014")
695
+ ])
696
+ );
697
+ } else {
698
+ console.log(
699
+ `
700
+ ${chalk3.dim("No transactions yet \u2014 run `tt topup` to add credits.")}`
701
+ );
702
+ }
703
+ if (lowBalance) {
704
+ console.log(
705
+ `
706
+ ${formatStatus("preparing")} ${chalk3.yellow(
707
+ "Run `tt topup` to add more credits before starting a run."
708
+ )}`
709
+ );
671
710
  }
672
711
  });
673
712
  }
674
- function progressBar(used, total, width) {
675
- const ratio = Math.min(used / total, 1);
676
- const filled = Math.round(ratio * width);
677
- const empty = width - filled;
678
- const color = ratio > 0.9 ? chalk3.red : ratio > 0.7 ? chalk3.yellow : chalk3.green;
679
- return color("\u2588".repeat(filled)) + chalk3.dim("\u2591".repeat(empty));
713
+
714
+ // src/commands/topup.ts
715
+ import chalk4 from "chalk";
716
+ import open from "open";
717
+ var PRESETS_USD = [10, 25, 50, 100];
718
+ var MIN_USD = 5;
719
+ var MAX_USD = 1e4;
720
+ function parseAmount(input) {
721
+ if (!input) return null;
722
+ const cleaned = input.replace(/^\$/, "").trim();
723
+ const num = Number(cleaned);
724
+ if (!Number.isFinite(num) || num <= 0) return null;
725
+ return num;
726
+ }
727
+ async function readLine(prompt) {
728
+ const readline = await import("readline/promises");
729
+ const rl = readline.createInterface({
730
+ input: process.stdin,
731
+ output: process.stdout
732
+ });
733
+ try {
734
+ return (await rl.question(prompt)).trim();
735
+ } finally {
736
+ rl.close();
737
+ }
738
+ }
739
+ function registerTopupCommands(parent) {
740
+ parent.command("topup").description("Add prepaid credits via Stripe Checkout").option("-a, --amount <usd>", "Amount in USD (e.g. 25)").option("--no-open", "Print checkout URL instead of opening the browser").action(async (options) => {
741
+ const opts = parent.opts();
742
+ let amountUsd;
743
+ if (options.amount !== void 0) {
744
+ amountUsd = parseAmount(options.amount);
745
+ if (amountUsd === null) {
746
+ throw new Error("Invalid amount");
747
+ }
748
+ } else {
749
+ if (isJsonMode()) {
750
+ throw new Error(
751
+ "amount is required in --json mode (use --amount <usd>)"
752
+ );
753
+ }
754
+ console.log(chalk4.bold("Add credits via Stripe Checkout"));
755
+ console.log(
756
+ chalk4.dim(
757
+ `Quick picks: ${PRESETS_USD.map((n) => `$${n}`).join(", ")}`
758
+ )
759
+ );
760
+ const input = await readLine(`Amount in USD (min $${MIN_USD}): `);
761
+ amountUsd = parseAmount(input);
762
+ if (amountUsd === null) {
763
+ throw new Error("Invalid amount");
764
+ }
765
+ }
766
+ if (amountUsd < MIN_USD) {
767
+ throw new Error(`Minimum top-up is $${MIN_USD}`);
768
+ }
769
+ if (amountUsd > MAX_USD) {
770
+ throw new Error(`Maximum top-up is $${MAX_USD}`);
771
+ }
772
+ const amountCents = Math.round(amountUsd * 100);
773
+ const { data } = await post(
774
+ "/billing/topup",
775
+ { amount_cents: amountCents },
776
+ opts
777
+ );
778
+ if (isJsonMode()) {
779
+ return printJson(data);
780
+ }
781
+ const url = data.checkout_url;
782
+ console.log(
783
+ `${chalk4.bold("Checkout URL:")} ${chalk4.cyan(url)}
784
+ ` + chalk4.dim("Complete the payment to credit your account.")
785
+ );
786
+ if (options.open !== false) {
787
+ try {
788
+ await open(url);
789
+ printSuccess("Opened Stripe Checkout in your browser.");
790
+ } catch {
791
+ console.log(
792
+ chalk4.yellow(
793
+ "Could not open browser automatically \u2014 copy the URL above."
794
+ )
795
+ );
796
+ }
797
+ }
798
+ });
680
799
  }
681
800
 
682
801
  // src/commands/init.ts
@@ -709,7 +828,7 @@ function registerInitCommand(parent) {
709
828
  printSuccess(`Created ${cmdOpts.file}`);
710
829
  console.log("\nNext steps:");
711
830
  console.log(" 1. Edit the spec: system_prompt, guidelines, examples");
712
- console.log(" 2. Run local evals: tt eval");
831
+ console.log(" 2. Run evals: tt eval --model <model-id>");
713
832
  console.log(" 3. Push to remote: tt push");
714
833
  });
715
834
  }
@@ -728,7 +847,7 @@ Run \`tt init\` to create one.`
728
847
 
729
848
  // src/commands/eval.ts
730
849
  import ora2 from "ora";
731
- import chalk4 from "chalk";
850
+ import chalk5 from "chalk";
732
851
 
733
852
  // src/eval/rules.ts
734
853
  function validateSpec(spec) {
@@ -956,7 +1075,7 @@ function registerEvalCommand(parent) {
956
1075
  const spec = loadSpec(cmdOpts.file);
957
1076
  const clientOpts = parent.opts();
958
1077
  if (!isJsonMode()) {
959
- console.log(chalk4.dim(`
1078
+ console.log(chalk5.dim(`
960
1079
  Spec: ${cmdOpts.file} | Model: ${cmdOpts.model}
961
1080
  `));
962
1081
  }
@@ -975,10 +1094,10 @@ Spec: ${cmdOpts.file} | Model: ${cmdOpts.model}
975
1094
  });
976
1095
  }
977
1096
  function printValidation(checks) {
978
- console.log(chalk4.bold("Spec Validation"));
1097
+ console.log(chalk5.bold("Spec Validation"));
979
1098
  for (const check of checks) {
980
- const icon = check.passed ? chalk4.green("\u2713") : chalk4.red("\u2717");
981
- const msg = check.message ? chalk4.dim(` \u2014 ${check.message}`) : "";
1099
+ const icon = check.passed ? chalk5.green("\u2713") : chalk5.red("\u2717");
1100
+ const msg = check.message ? chalk5.dim(` \u2014 ${check.message}`) : "";
982
1101
  console.log(` ${icon} ${check.name}${msg}`);
983
1102
  }
984
1103
  }
@@ -987,33 +1106,33 @@ function printResults(summary) {
987
1106
  printWarning("No eval cases to run. Add examples or eval_cases to your spec.");
988
1107
  return;
989
1108
  }
990
- console.log(chalk4.bold(`Eval Results (${summary.total}):`));
1109
+ console.log(chalk5.bold(`Eval Results (${summary.total}):`));
991
1110
  printTable(
992
1111
  ["#", "Passed", "Input", "Latency"],
993
1112
  summary.results.map((r, i) => [
994
1113
  String(i + 1),
995
- r.passed ? chalk4.green("\u2713") : chalk4.red("\u2717"),
1114
+ r.passed ? chalk5.green("\u2713") : chalk5.red("\u2717"),
996
1115
  truncate(r.input, 40),
997
1116
  r.latency_ms != null ? `${r.latency_ms}ms` : "\u2014"
998
1117
  ])
999
1118
  );
1000
1119
  console.log();
1001
1120
  const passStr = (summary.pass_rate * 100).toFixed(1) + "%";
1002
- const color = summary.pass_rate >= 0.8 ? chalk4.green : summary.pass_rate >= 0.5 ? chalk4.yellow : chalk4.red;
1121
+ const color = summary.pass_rate >= 0.8 ? chalk5.green : summary.pass_rate >= 0.5 ? chalk5.yellow : chalk5.red;
1003
1122
  console.log(
1004
- ` Pass Rate: ${color(chalk4.bold(passStr))} (${summary.passed}/${summary.total} passed)`
1123
+ ` Pass Rate: ${color(chalk5.bold(passStr))} (${summary.passed}/${summary.total} passed)`
1005
1124
  );
1006
1125
  const failedResults = summary.results.filter((r) => !r.passed);
1007
1126
  if (failedResults.length) {
1008
- console.log(chalk4.dim(`
1127
+ console.log(chalk5.dim(`
1009
1128
  Failed eval details:`));
1010
1129
  for (const r of failedResults) {
1011
- console.log(chalk4.dim(` \u2022 "${truncate(r.input, 50)}":`));
1130
+ console.log(chalk5.dim(` \u2022 "${truncate(r.input, 50)}":`));
1012
1131
  if (r.actual) {
1013
- console.log(chalk4.dim(` Response: ${truncate(r.actual, 80)}`));
1132
+ console.log(chalk5.dim(` Response: ${truncate(r.actual, 80)}`));
1014
1133
  }
1015
1134
  for (const a of r.assertions.filter((a2) => !a2.passed)) {
1016
- console.log(chalk4.red(` \u2717 ${a.assertion}: ${a.message}`));
1135
+ console.log(chalk5.red(` \u2717 ${a.assertion}: ${a.message}`));
1017
1136
  }
1018
1137
  }
1019
1138
  }
@@ -1048,7 +1167,7 @@ function registerPushCommand(parent) {
1048
1167
 
1049
1168
  // src/index.ts
1050
1169
  var program = new Command();
1051
- program.name("tt").description("Tuned Tensor CLI \u2014 fine-tune and evaluate LLMs").version("0.2.0").option("-k, --api-key <key>", "API key (overrides stored key)").option(
1170
+ program.name("tt").description("Tuned Tensor CLI \u2014 fine-tune and evaluate LLMs").version("0.4.0").option("-k, --api-key <key>", "API key (overrides stored key)").option(
1052
1171
  "-u, --base-url <url>",
1053
1172
  "API base URL (default: https://www.tunedtensor.com)"
1054
1173
  ).option("--json", "Output raw JSON").option("--no-color", "Disable colors").hook("preAction", (_thisCommand, actionCommand) => {
@@ -1063,7 +1182,8 @@ registerSpecsCommands(program);
1063
1182
  registerRunsCommands(program);
1064
1183
  registerDatasetsCommands(program);
1065
1184
  registerModelsCommands(program);
1066
- registerUsageCommands(program);
1185
+ registerBalanceCommands(program);
1186
+ registerTopupCommands(program);
1067
1187
  registerInitCommand(program);
1068
1188
  registerEvalCommand(program);
1069
1189
  registerPushCommand(program);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/output.ts","../src/commands/auth.ts","../src/config.ts","../src/commands/specs.ts","../src/client.ts","../src/commands/runs.ts","../src/commands/datasets.ts","../src/commands/models.ts","../src/commands/usage.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, printError } 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 { registerUsageCommands } from \"./commands/usage.js\";\nimport { registerInitCommand } from \"./commands/init.js\";\nimport { registerEvalCommand } from \"./commands/eval.js\";\nimport { registerPushCommand } from \"./commands/push.js\";\nimport { ApiError } from \"./client.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://www.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\nregisterUsageCommands(program);\nregisterInitCommand(program);\nregisterEvalCommand(program);\nregisterPushCommand(program);\n\nprogram.parseAsync().catch((err) => {\n if (err instanceof ApiError) {\n printError(`[${err.status}] ${err.message}`);\n process.exit(1);\n }\n printError(err.message || String(err));\n process.exit(1);\n});\n","import chalk from \"chalk\";\nimport Table from \"cli-table3\";\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 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 { 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 { 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://www.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 { readFileSync } from \"node:fs\";\nimport { get, post, put, del, type ClientOpts } from \"../client.js\";\nimport {\n printTable,\n printDetail,\n printSuccess,\n printJson,\n isJsonMode,\n formatDate,\n formatStatus,\n truncate,\n shortId,\n} from \"../output.js\";\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 or prefix)\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const { data } = await get<BehaviorSpec>(`/behavior-specs/${id}`, 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 = JSON.parse(readFileSync(cmdOpts.file, \"utf-8\"));\n } else if (cmdOpts.name) {\n body = { name: cmdOpts.name };\n if (cmdOpts.model) body.base_model = cmdOpts.model;\n } else {\n console.error(\"Provide --file or --name\");\n process.exit(1);\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\")\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 = JSON.parse(readFileSync(cmdOpts.file, \"utf-8\"));\n } else {\n body = {};\n if (cmdOpts.name) body.name = cmdOpts.name;\n if (cmdOpts.model) body.base_model = cmdOpts.model;\n }\n\n const { data } = await put<BehaviorSpec>(\n `/behavior-specs/${id}`,\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\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n await del(`/behavior-specs/${id}`, opts);\n\n if (isJsonMode()) return printJson({ id, deleted: true });\n printSuccess(`Spec deleted: ${shortId(id)}`);\n });\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 { Command } from \"commander\";\nimport ora from \"ora\";\nimport { get, post, type ClientOpts } from \"../client.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 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}\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\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\")\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 path = `/behavior-specs/${cmdOpts.spec}/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\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const { data } = await get<Run>(`/runs/${id}`, 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 [\"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._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\")\n .option(\"--no-augment\", \"Disable data augmentation\")\n .option(\"--epochs <n>\", \"Number of training epochs\")\n .option(\"--lr <rate>\", \"Learning rate\")\n .option(\"--batch-size <n>\", \"Batch size\")\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\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 (Object.keys(hp).length) body.hyperparameters = hp;\n\n const { data } = await post<Run>(\n `/behavior-specs/${specId}/runs`,\n body,\n opts,\n );\n\n if (isJsonMode()) return printJson(data);\n printSuccess(\n `Run #${data.run_number} started (${shortId(data.id)}). Status: ${formatStatus(data.status)}`,\n );\n });\n\n runs\n .command(\"cancel\")\n .description(\"Cancel a running run\")\n .argument(\"<id>\", \"Run ID\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const { data } = await post<Run>(`/runs/${id}/cancel`, undefined, opts);\n\n if (isJsonMode()) return printJson(data);\n printSuccess(`Run ${shortId(id)} cancelled.`);\n });\n\n runs\n .command(\"watch\")\n .description(\"Watch a run until it completes\")\n .argument(\"<id>\", \"Run ID\")\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 spinner = ora(`Watching run ${shortId(id)}...`).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/${id}`, undefined, opts);\n run = data;\n spinner.text = `Run ${shortId(id)} — ${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 [\"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 } from \"node:fs\";\nimport { get, del, upload, type ClientOpts } from \"../client.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\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\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const { data } = await get<Dataset>(`/datasets/${id}`, 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 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\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n await del(`/datasets/${id}`, opts);\n\n if (isJsonMode()) return printJson({ id, deleted: true });\n printSuccess(`Dataset deleted: ${shortId(id)}`);\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 isJsonMode,\n formatDate,\n} from \"../output.js\";\n\ninterface UsageSummary {\n tier: string;\n tierName: string;\n runsUsed: number;\n runsLimit: number;\n periodStart: string;\n periodEnd: string;\n canStartRun: boolean;\n}\n\ninterface TierDefinition {\n slug: string;\n name: string;\n runsPerMonth: number;\n monthlyPriceUsd: number;\n features: string[];\n}\n\ninterface UsageResponse {\n usage: UsageSummary;\n tiers: TierDefinition[];\n}\n\nexport function registerUsageCommands(parent: Command) {\n parent\n .command(\"usage\")\n .description(\"Show usage summary and tier info\")\n .action(async () => {\n const opts = parent.opts() as ClientOpts;\n const { data } = await get<UsageResponse>(\"/usage\", undefined, opts);\n\n if (isJsonMode()) return printJson(data);\n\n const u = data.usage;\n const pct = u.runsLimit > 0 ? ((u.runsUsed / u.runsLimit) * 100).toFixed(0) : \"∞\";\n const bar = u.runsLimit > 0\n ? progressBar(u.runsUsed, u.runsLimit, 20)\n : chalk.green(\"unlimited\");\n\n printDetail([\n [\"Tier\", `${u.tierName} (${u.tier})`],\n [\"Runs\", `${u.runsUsed} / ${u.runsLimit} (${pct}%)`],\n [\"Usage\", bar],\n [\"Can Start Run\", u.canStartRun ? chalk.green(\"Yes\") : chalk.red(\"No\")],\n [\"Period Start\", formatDate(u.periodStart)],\n [\"Period End\", formatDate(u.periodEnd)],\n ]);\n\n if (data.tiers?.length) {\n console.log(\"\\nAvailable Tiers:\");\n for (const t of data.tiers) {\n const price = t.monthlyPriceUsd === 0 ? \"Free\" : `$${t.monthlyPriceUsd}/mo`;\n const current = t.slug === u.tier ? chalk.green(\" (current)\") : \"\";\n console.log(` ${chalk.bold(t.name)}${current} — ${price}, ${t.runsPerMonth} runs/mo`);\n for (const f of t.features) {\n console.log(` • ${f}`);\n }\n }\n }\n });\n}\n\nfunction progressBar(used: number, total: number, width: number): string {\n const ratio = Math.min(used / total, 1);\n const filled = Math.round(ratio * width);\n const empty = width - filled;\n const color = ratio > 0.9 ? chalk.red : ratio > 0.7 ? chalk.yellow : chalk.green;\n return color(\"█\".repeat(filled)) + chalk.dim(\"░\".repeat(empty));\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\";\n\nconst DEFAULT_SPEC_FILE = \"tunedtensor.json\";\n\nconst SCAFFOLD: LocalSpec = {\n name: \"My Agent\",\n description: \"\",\n base_model: \"meta-llama/Llama-3.2-3B-Instruct\",\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 = 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 local evals: 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 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\";\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, ...body } = spec as unknown as Record<string, unknown>;\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":["chalk","readFileSync","readFileSync","readFileSync","readFileSync","existsSync","existsSync","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/commands/auth.ts","../src/config.ts","../src/commands/specs.ts","../src/client.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, printError } 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\";\nimport { ApiError } from \"./client.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://www.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\nprogram.parseAsync().catch((err) => {\n if (err instanceof ApiError) {\n printError(`[${err.status}] ${err.message}`);\n process.exit(1);\n }\n printError(err.message || String(err));\n process.exit(1);\n});\n","import chalk from \"chalk\";\nimport Table from \"cli-table3\";\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 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 { 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 { 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://www.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 { readFileSync } from \"node:fs\";\nimport { get, post, put, del, type ClientOpts } from \"../client.js\";\nimport {\n printTable,\n printDetail,\n printSuccess,\n printJson,\n isJsonMode,\n formatDate,\n formatStatus,\n truncate,\n shortId,\n} from \"../output.js\";\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 or prefix)\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const { data } = await get<BehaviorSpec>(`/behavior-specs/${id}`, 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 = JSON.parse(readFileSync(cmdOpts.file, \"utf-8\"));\n } else if (cmdOpts.name) {\n body = { name: cmdOpts.name };\n if (cmdOpts.model) body.base_model = cmdOpts.model;\n } else {\n console.error(\"Provide --file or --name\");\n process.exit(1);\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\")\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 = JSON.parse(readFileSync(cmdOpts.file, \"utf-8\"));\n } else {\n body = {};\n if (cmdOpts.name) body.name = cmdOpts.name;\n if (cmdOpts.model) body.base_model = cmdOpts.model;\n }\n\n const { data } = await put<BehaviorSpec>(\n `/behavior-specs/${id}`,\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\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n await del(`/behavior-specs/${id}`, opts);\n\n if (isJsonMode()) return printJson({ id, deleted: true });\n printSuccess(`Spec deleted: ${shortId(id)}`);\n });\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 { Command } from \"commander\";\nimport ora from \"ora\";\nimport { get, post, type ClientOpts } from \"../client.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 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}\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\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\")\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 path = `/behavior-specs/${cmdOpts.spec}/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\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const { data } = await get<Run>(`/runs/${id}`, 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 [\"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._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\")\n .option(\"--no-augment\", \"Disable data augmentation\")\n .option(\"--epochs <n>\", \"Number of training epochs\")\n .option(\"--lr <rate>\", \"Learning rate\")\n .option(\"--batch-size <n>\", \"Batch size\")\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\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 (Object.keys(hp).length) body.hyperparameters = hp;\n\n const { data } = await post<Run>(\n `/behavior-specs/${specId}/runs`,\n body,\n opts,\n );\n\n if (isJsonMode()) return printJson(data);\n printSuccess(\n `Run #${data.run_number} started (${shortId(data.id)}). Status: ${formatStatus(data.status)}`,\n );\n });\n\n runs\n .command(\"cancel\")\n .description(\"Cancel a running run\")\n .argument(\"<id>\", \"Run ID\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const { data } = await post<Run>(`/runs/${id}/cancel`, undefined, opts);\n\n if (isJsonMode()) return printJson(data);\n printSuccess(`Run ${shortId(id)} cancelled.`);\n });\n\n runs\n .command(\"watch\")\n .description(\"Watch a run until it completes\")\n .argument(\"<id>\", \"Run ID\")\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 spinner = ora(`Watching run ${shortId(id)}...`).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/${id}`, undefined, opts);\n run = data;\n spinner.text = `Run ${shortId(id)} — ${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 [\"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 } from \"node:fs\";\nimport { get, del, upload, type ClientOpts } from \"../client.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\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\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n const { data } = await get<Dataset>(`/datasets/${id}`, 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 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\")\n .action(async (id: string) => {\n const opts = parent.opts() as ClientOpts;\n await del(`/datasets/${id}`, opts);\n\n if (isJsonMode()) return printJson({ id, deleted: true });\n printSuccess(`Dataset deleted: ${shortId(id)}`);\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 lifetime_topup_cents: number;\n signup_bonus_cents: number;\n signup_bonus_granted: boolean;\n}\n\ntype CreditKind =\n | \"signup_bonus\"\n | \"topup\"\n | \"debit_run\"\n | \"debit_autotune\"\n | \"refund\"\n | \"adjustment\";\n\ninterface LedgerRow {\n id: string;\n kind: CreditKind;\n amount_cents: number;\n balance_after_cents: number;\n reference_id: string | null;\n created_at: string;\n}\n\nconst KIND_LABELS: Record<CreditKind, string> = {\n signup_bonus: \"Signup bonus\",\n topup: \"Top-up\",\n debit_run: \"Run\",\n debit_autotune: \"Auto-tune\",\n refund: \"Refund\",\n adjustment: \"Adjustment\",\n};\n\nfunction formatCents(cents: number): string {\n const sign = cents < 0 ? \"-\" : \"\";\n const abs = Math.abs(cents);\n return `${sign}$${(abs / 100).toFixed(2)}`;\n}\n\nfunction formatSigned(cents: number): string {\n if (cents > 0) return chalk.green(`+${formatCents(cents)}`);\n if (cents < 0) return chalk.red(formatCents(cents));\n return formatCents(cents);\n}\n\nexport function registerBalanceCommands(parent: Command) {\n parent\n .command(\"balance\")\n .description(\"Show credit balance and recent transactions\")\n .option(\"-n, --limit <n>\", \"Number of transactions to show (default 10)\", \"10\")\n .action(async (options) => {\n const opts = parent.opts() as ClientOpts;\n const limit = Number(options.limit) || 10;\n\n const [{ data: balance }, { data: transactions }] = await Promise.all([\n get<BalanceResponse>(\"/billing/balance\", undefined, opts),\n get<LedgerRow[]>(\"/billing/transactions\", { per_page: limit }, opts),\n ]);\n\n if (isJsonMode()) {\n return printJson({ balance, transactions });\n }\n\n const lowBalance = balance.balance_cents < 100;\n const balanceLine = lowBalance\n ? chalk.red(formatCents(balance.balance_cents)) + chalk.dim(\" (low)\")\n : chalk.bold.green(formatCents(balance.balance_cents));\n\n printDetail([\n [\"Balance\", balanceLine],\n [\n \"Signup bonus\",\n balance.signup_bonus_granted\n ? chalk.green(\"granted\") + ` (${formatCents(balance.signup_bonus_cents)})`\n : chalk.dim(\"not yet granted\"),\n ],\n [\"Lifetime top-ups\", formatCents(balance.lifetime_topup_cents)],\n ]);\n\n if (transactions && transactions.length > 0) {\n console.log(`\\n${chalk.bold(\"Recent transactions\")}`);\n printTable(\n [\"Date\", \"Type\", \"Amount\", \"Balance\", \"Reference\"],\n transactions.map((row) => [\n formatDate(row.created_at),\n KIND_LABELS[row.kind] ?? row.kind,\n formatSigned(row.amount_cents),\n formatCents(row.balance_after_cents),\n row.reference_id ? shortId(row.reference_id) : chalk.dim(\"—\"),\n ])\n );\n } else {\n console.log(\n `\\n${chalk.dim(\"No transactions yet — run `tt topup` to add credits.\")}`\n );\n }\n\n if (lowBalance) {\n console.log(\n `\\n${formatStatus(\"preparing\")} ${chalk.yellow(\n \"Run `tt topup` to add more credits before starting a run.\"\n )}`\n );\n }\n });\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport open from \"open\";\nimport { post, type ClientOpts } from \"../client.js\";\nimport { printJson, isJsonMode, printSuccess } from \"../output.js\";\n\ninterface TopupResponse {\n checkout_url: string;\n session_id: string;\n}\n\nconst PRESETS_USD = [10, 25, 50, 100];\nconst MIN_USD = 5;\nconst MAX_USD = 10000;\n\nfunction parseAmount(input: string | undefined): number | null {\n if (!input) return null;\n const cleaned = input.replace(/^\\$/, \"\").trim();\n const num = Number(cleaned);\n if (!Number.isFinite(num) || num <= 0) return null;\n return num;\n}\n\nasync function readLine(prompt: string): Promise<string> {\n const readline = await import(\"node:readline/promises\");\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n try {\n return (await rl.question(prompt)).trim();\n } finally {\n rl.close();\n }\n}\n\nexport function registerTopupCommands(parent: Command) {\n parent\n .command(\"topup\")\n .description(\"Add prepaid credits via Stripe Checkout\")\n .option(\"-a, --amount <usd>\", \"Amount in USD (e.g. 25)\")\n .option(\"--no-open\", \"Print checkout URL instead of opening the browser\")\n .action(async (options) => {\n const opts = parent.opts() as ClientOpts;\n\n let amountUsd: number | null;\n\n if (options.amount !== undefined) {\n amountUsd = parseAmount(options.amount);\n if (amountUsd === null) {\n throw new Error(\"Invalid amount\");\n }\n } else {\n if (isJsonMode()) {\n throw new Error(\n \"amount is required in --json mode (use --amount <usd>)\"\n );\n }\n console.log(chalk.bold(\"Add credits via Stripe Checkout\"));\n console.log(\n chalk.dim(\n `Quick picks: ${PRESETS_USD.map((n) => `$${n}`).join(\", \")}`\n )\n );\n const input = await readLine(`Amount in USD (min $${MIN_USD}): `);\n amountUsd = parseAmount(input);\n if (amountUsd === null) {\n throw new Error(\"Invalid amount\");\n }\n }\n\n if (amountUsd < MIN_USD) {\n throw new Error(`Minimum top-up is $${MIN_USD}`);\n }\n if (amountUsd > MAX_USD) {\n throw new Error(`Maximum top-up is $${MAX_USD}`);\n }\n\n const amountCents = Math.round(amountUsd * 100);\n\n const { data } = await post<TopupResponse>(\n \"/billing/topup\",\n { amount_cents: amountCents },\n opts\n );\n\n if (isJsonMode()) {\n return printJson(data);\n }\n\n const url = data.checkout_url;\n console.log(\n `${chalk.bold(\"Checkout URL:\")} ${chalk.cyan(url)}\\n` +\n chalk.dim(\"Complete the payment to credit your account.\")\n );\n\n if (options.open !== false) {\n try {\n await open(url);\n printSuccess(\"Opened Stripe Checkout in your browser.\");\n } catch {\n console.log(\n chalk.yellow(\n \"Could not open browser automatically — copy the URL above.\"\n )\n );\n }\n }\n });\n}\n","import { Command } from \"commander\";\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { printSuccess, printError, printWarning } from \"../output.js\";\nimport type { LocalSpec } from \"../eval/types.js\";\n\nconst DEFAULT_SPEC_FILE = \"tunedtensor.json\";\n\nconst SCAFFOLD: LocalSpec = {\n name: \"My Agent\",\n description: \"\",\n base_model: \"meta-llama/Llama-3.2-3B-Instruct\",\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 = 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\";\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, ...body } = spec as unknown as Record<string, unknown>;\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":["chalk","readFileSync","readFileSync","readFileSync","readFileSync","existsSync","existsSync","chalk","chalk","chalk","chalk","existsSync","readFileSync","writeFileSync","existsSync","writeFileSync","readFileSync","ora","chalk","chalk","ora","a","readFileSync","writeFileSync","resolve","resolve","readFileSync","writeFileSync"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tuned-tensor/cli",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "CLI for Tuned Tensor — fine-tune and evaluate LLMs from the command line",
5
5
  "type": "module",
6
6
  "bin": {
@@ -27,6 +27,7 @@
27
27
  "chalk": "^5.6.2",
28
28
  "cli-table3": "^0.6.5",
29
29
  "commander": "^14.0.3",
30
+ "open": "^10.1.0",
30
31
  "ora": "^9.3.0"
31
32
  },
32
33
  "devDependencies": {