@tuned-tensor/cli 0.13.0-beta.1 → 0.13.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/dist/index.js CHANGED
@@ -2,19 +2,16 @@
2
2
  import {
3
3
  TRAINING_MODELS,
4
4
  assertLocalRunInputReady,
5
- createLocalStore,
6
- defaultLocalHome,
7
5
  loadLocalRunInput,
8
6
  loadLocalRunnerConfig,
9
- runLocalPipeline,
10
- runReportSchema
11
- } from "./chunk-2VJ3VVZF.js";
7
+ runLocalPipeline
8
+ } from "./chunk-YJYCGSHJ.js";
12
9
 
13
10
  // src/cli.ts
14
11
  import { spawn as spawn2 } from "child_process";
15
12
  import { constants as osConstants2 } from "os";
16
13
  import { Command } from "commander";
17
- import chalk7 from "chalk";
14
+ import chalk6 from "chalk";
18
15
 
19
16
  // src/local-agent-client.ts
20
17
  import { randomUUID as randomUUID2 } from "crypto";
@@ -1588,10 +1585,6 @@ function updateConfig(partial) {
1588
1585
  const current = readConfig();
1589
1586
  writeConfig({ ...current, ...partial });
1590
1587
  }
1591
- var DEFAULT_BASE_URL = "https://tunedtensor.com";
1592
- function getBaseUrl(opts) {
1593
- return opts?.baseUrl || process.env.TUNED_TENSOR_URL || readConfig().base_url || DEFAULT_BASE_URL;
1594
- }
1595
1588
  function getApiKey(opts) {
1596
1589
  return opts?.apiKey || process.env.TUNED_TENSOR_API_KEY || readConfig().api_key;
1597
1590
  }
@@ -1615,7 +1608,7 @@ function getAgentSelection(env = process.env) {
1615
1608
  }
1616
1609
 
1617
1610
  // src/cli.ts
1618
- import { join as join8 } from "path";
1611
+ import { join as join7 } from "path";
1619
1612
 
1620
1613
  // src/agent.ts
1621
1614
  import chalk3 from "chalk";
@@ -1636,6 +1629,11 @@ var COMMAND_CATALOG = [
1636
1629
  { path: "validate", description: "Validate a local fine-tuning project.", group: "Workflow", modes: LOCAL },
1637
1630
  { path: "doctor", description: "Check the local host and run prerequisites.", group: "Workflow", modes: LOCAL },
1638
1631
  { path: "run", description: "Run the local fine-tuning and evaluation workflow.", group: "Workflow", modes: LOCAL },
1632
+ { path: "pipeline init", description: "Write a canonical v1 pipeline recipe.", group: "Workflow", modes: LOCAL },
1633
+ { path: "pipeline validate", description: "Validate a pipeline without executing it.", group: "Workflow", modes: LOCAL },
1634
+ { path: "pipeline plan", description: "Resolve pipeline steps and required artifacts.", group: "Workflow", modes: LOCAL },
1635
+ { path: "pipeline run", description: "Run or dry-run a local pipeline.", group: "Workflow", modes: LOCAL },
1636
+ { path: "shell", description: "Open the conversational terminal.", group: "Workflow", modes: LOCAL },
1639
1637
  { path: "runs list", description: "List local runs.", group: "Inspect", modes: LOCAL },
1640
1638
  { path: "runs get", description: "Show a local run.", group: "Inspect", modes: LOCAL },
1641
1639
  { path: "runs report", description: "Show a local run report.", group: "Inspect", modes: LOCAL },
@@ -1652,10 +1650,10 @@ var COMMAND_CATALOG = [
1652
1650
  { path: "models rollback", description: "Roll back the active local model.", group: "Serving", modes: LOCAL },
1653
1651
  { path: "serve", description: "Serve a local adapter, active model, or base model.", group: "Serving", modes: LOCAL },
1654
1652
  { path: "info", description: "Show local runtime package information.", group: "Inspect", modes: LOCAL },
1655
- { path: "auth login", description: "Store a Tuned Tensor API key.", group: "Account", modes: LOCAL },
1656
- { path: "auth logout", description: "Remove the stored Tuned Tensor API key.", group: "Account", modes: LOCAL },
1657
- { path: "auth status", description: "Show Tuned Tensor authentication status.", group: "Account", modes: LOCAL },
1658
- { path: "publish", description: "Publish local run evidence to the dashboard.", group: "Account", modes: LOCAL }
1653
+ { path: "status", description: "Show local project context.", group: "Inspect", modes: LOCAL },
1654
+ { path: "agent models", description: "List provider models for the laptop-local TT agent.", group: "Inspect", modes: LOCAL },
1655
+ { path: "agent configure", description: "Select the laptop-local TT agent model.", group: "Inspect", modes: LOCAL },
1656
+ { path: "agent status", description: "Show the laptop-local TT agent selection.", group: "Inspect", modes: LOCAL }
1659
1657
  ];
1660
1658
  var SLASH_COMMANDS = [
1661
1659
  { path: "/help", description: "Show commands; add a word to filter." },
@@ -2655,13 +2653,13 @@ async function startInteractiveShell(options) {
2655
2653
  }
2656
2654
  let readline;
2657
2655
  const terminalInput = input;
2658
- const foregroundRunner = (request2) => withForegroundSignalHandoff(
2656
+ const foregroundRunner = (request) => withForegroundSignalHandoff(
2659
2657
  {
2660
2658
  input: terminalInput,
2661
2659
  pauseReadline: () => readline?.pause(),
2662
2660
  resumeReadline: () => readline?.resume()
2663
2661
  },
2664
- () => options.runner(request2)
2662
+ () => options.runner(request)
2665
2663
  );
2666
2664
  const session = await createShellSession({
2667
2665
  runner: foregroundRunner,
@@ -2975,10 +2973,10 @@ ${chalk3.yellow.bold("Approval required")} ${chalk3.dim(action.id.slice(0, 8))}
2975
2973
  `);
2976
2974
  if (action.summary) this.options.io.write(`${sanitizeTerminalText2(action.summary)}
2977
2975
  `);
2978
- const request2 = [action.method, action.path].filter(Boolean).join(" ");
2976
+ const request = [action.method, action.path].filter(Boolean).join(" ");
2979
2977
  const technical = {
2980
2978
  operation: action.operation,
2981
- ...request2 ? { request: request2 } : {},
2979
+ ...request ? { request } : {},
2982
2980
  arguments: action.arguments ?? null,
2983
2981
  preview: action.preview ?? null
2984
2982
  };
@@ -3361,59 +3359,6 @@ var ApiError = class extends Error {
3361
3359
  this.name = "ApiError";
3362
3360
  }
3363
3361
  };
3364
- function resolveKey(opts) {
3365
- const key = getApiKey(opts);
3366
- if (!key) {
3367
- throw new ApiError(
3368
- 401,
3369
- "NO_API_KEY",
3370
- "No API key found. Run `tt auth login` or set TUNED_TENSOR_API_KEY."
3371
- );
3372
- }
3373
- return key;
3374
- }
3375
- function buildUrl(path, query, opts) {
3376
- const base = getBaseUrl(opts);
3377
- const url = new URL(`/api/v1${path}`, base);
3378
- if (query) {
3379
- for (const [k, v] of Object.entries(query)) {
3380
- if (v !== void 0) url.searchParams.set(k, String(v));
3381
- }
3382
- }
3383
- return url.toString();
3384
- }
3385
- async function request(method, path, options = {}) {
3386
- const key = resolveKey(options.opts);
3387
- const url = buildUrl(path, options.query, options.opts);
3388
- const headers = {
3389
- ...options.headers,
3390
- Authorization: `Bearer ${key}`
3391
- };
3392
- let bodyPayload;
3393
- if (options.body) {
3394
- headers["Content-Type"] = "application/json";
3395
- bodyPayload = JSON.stringify(options.body);
3396
- }
3397
- const res = await fetch(url, { method, headers, body: bodyPayload });
3398
- if (!res.ok) {
3399
- let errBody;
3400
- try {
3401
- errBody = await res.json();
3402
- } catch {
3403
- throw new ApiError(res.status, "UNKNOWN", res.statusText);
3404
- }
3405
- throw new ApiError(
3406
- res.status,
3407
- errBody.error?.code || "UNKNOWN",
3408
- errBody.error?.message || res.statusText
3409
- );
3410
- }
3411
- if (res.status === 204) return { data: null };
3412
- return await res.json();
3413
- }
3414
- function post(path, body, opts, headers) {
3415
- return request("POST", path, { body, opts, headers });
3416
- }
3417
3362
 
3418
3363
  // src/output.ts
3419
3364
  var labelStyle = chalk4.bold.hex("#A78BFA");
@@ -3530,7 +3475,9 @@ function rows(value) {
3530
3475
  }
3531
3476
  function displayId(value) {
3532
3477
  const id = text(value);
3533
- return id ? shortId(id) : "\u2014";
3478
+ if (!id) return "\u2014";
3479
+ if (id.startsWith("local-")) return `local-${shortId(id.slice("local-".length))}`;
3480
+ return shortId(id);
3534
3481
  }
3535
3482
  function displayNumber(value, digits = 4) {
3536
3483
  const parsed = number(value);
@@ -4160,10 +4107,10 @@ function localCommandStreamsStdout(args2) {
4160
4107
  const serves = args2[0] === "serve" || args2[0] === "models" && args2[1] === "serve";
4161
4108
  return serves && !args2.includes("--print-command") && !args2.includes("--help") && !args2.includes("-h");
4162
4109
  }
4163
- function parseJsonOutput(stdout2) {
4164
- if (!stdout2.trim()) return { hasJson: false, json: void 0 };
4110
+ function parseJsonOutput(stdout) {
4111
+ if (!stdout.trim()) return { hasJson: false, json: void 0 };
4165
4112
  try {
4166
- return { hasJson: true, json: JSON.parse(stdout2) };
4113
+ return { hasJson: true, json: JSON.parse(stdout) };
4167
4114
  } catch {
4168
4115
  return { hasJson: false, json: void 0 };
4169
4116
  }
@@ -4209,7 +4156,7 @@ async function spawnLocalCli(args2) {
4209
4156
  }
4210
4157
  );
4211
4158
  if (pipeInput && args2.stdin && child.stdin) args2.stdin.pipe(child.stdin);
4212
- let stdout2 = "";
4159
+ let stdout = "";
4213
4160
  let stderr = "";
4214
4161
  child.stdout?.setEncoding("utf8");
4215
4162
  child.stderr?.setEncoding("utf8");
@@ -4219,7 +4166,7 @@ async function spawnLocalCli(args2) {
4219
4166
  args2.pathReplacements
4220
4167
  );
4221
4168
  if (args2.streamingStdout) writeStream(output, normalized);
4222
- else stdout2 += normalized;
4169
+ else stdout += normalized;
4223
4170
  });
4224
4171
  child.stderr?.on("data", (chunk) => {
4225
4172
  const normalized = normalizeProjectedPaths(
@@ -4264,7 +4211,7 @@ async function spawnLocalCli(args2) {
4264
4211
  resolveChild({
4265
4212
  exitCode: spawnError ? 1 : code2 ?? signalExitCode(signal),
4266
4213
  signal,
4267
- stdout: stdout2,
4214
+ stdout,
4268
4215
  stderr,
4269
4216
  ...spawnError ? { errorMessage: spawnError.message } : {}
4270
4217
  });
@@ -4478,294 +4425,9 @@ function registerAgentCommands(parent, options) {
4478
4425
  });
4479
4426
  }
4480
4427
 
4481
- // src/commands/auth.ts
4482
- import { createInterface as createInterface2 } from "readline/promises";
4483
- import { stdin, stdout } from "process";
4484
- import { Writable } from "stream";
4485
- import chalk6 from "chalk";
4486
- async function promptForApiKey(input = stdin, output = stdout) {
4487
- if (input.isTTY !== true || output.isTTY !== true) {
4488
- throw new Error(
4489
- "An API key is required in non-interactive mode. Pass it to `tt auth login <key>` or set TUNED_TENSOR_API_KEY."
4490
- );
4491
- }
4492
- let muted = false;
4493
- const maskedOutput = new Writable({
4494
- write(chunk, _encoding, callback) {
4495
- if (!muted) output.write(chunk);
4496
- callback();
4497
- }
4498
- });
4499
- const rl = createInterface2({
4500
- input,
4501
- output: maskedOutput,
4502
- terminal: true
4503
- });
4504
- try {
4505
- const pending = rl.question("Enter your API key (tt_...): ");
4506
- muted = true;
4507
- return await pending;
4508
- } finally {
4509
- muted = false;
4510
- output.write("\n");
4511
- rl.close();
4512
- }
4513
- }
4514
- function registerAuthCommands(parent) {
4515
- const auth = parent.command("auth").description("Manage authentication");
4516
- auth.command("login").description("Store an API key for authentication").argument("[key]", "API key (tt_...). If omitted, you will be prompted.").action(async (key) => {
4517
- let apiKey = key;
4518
- if (!apiKey) {
4519
- if (isJsonMode()) {
4520
- throw new Error(
4521
- "An API key argument is required in JSON mode. Use `tt --json auth login <key>`."
4522
- );
4523
- }
4524
- const settingsUrl = `${DEFAULT_BASE_URL}/dashboard/settings`;
4525
- console.log();
4526
- console.log(
4527
- ` To get your API key, go to ${chalk6.bold("Settings \u2192 API Keys")} in the Tuned Tensor dashboard:`
4528
- );
4529
- console.log(` ${chalk6.hex("#A78BFA").underline(settingsUrl)}`);
4530
- console.log();
4531
- apiKey = await promptForApiKey();
4532
- }
4533
- apiKey = apiKey.trim();
4534
- if (!apiKey.startsWith("tt_") || apiKey.length !== 51) {
4535
- throw new Error(
4536
- "Invalid API key format. Keys start with tt_ and are 51 characters long."
4537
- );
4538
- }
4539
- updateConfig({ api_key: apiKey });
4540
- if (isJsonMode()) {
4541
- printJson({
4542
- authenticated: true,
4543
- key_prefix: `${apiKey.slice(0, 8)}...`,
4544
- base_url: getBaseUrl(parent.opts())
4545
- });
4546
- return;
4547
- }
4548
- printSuccess(
4549
- `API key stored (${apiKey.slice(0, 8)}...). You're ready to go.`
4550
- );
4551
- });
4552
- auth.command("logout").description("Remove stored credentials").action(() => {
4553
- const current = readConfig();
4554
- const { api_key: _removed, ...rest } = current;
4555
- writeConfig(rest);
4556
- if (isJsonMode()) {
4557
- printJson({ authenticated: false });
4558
- return;
4559
- }
4560
- printSuccess("Credentials removed.");
4561
- });
4562
- auth.command("status").description("Show current authentication status").action(() => {
4563
- const opts = parent.opts();
4564
- const apiKey = getApiKey(opts);
4565
- const baseUrl = getBaseUrl(opts);
4566
- if (isJsonMode()) {
4567
- printJson({
4568
- authenticated: !!apiKey,
4569
- key_prefix: apiKey ? apiKey.slice(0, 8) + "..." : null,
4570
- base_url: baseUrl
4571
- });
4572
- return;
4573
- }
4574
- if (apiKey) {
4575
- printDetail([
4576
- ["Authenticated", "Yes"],
4577
- ["API Key", apiKey.slice(0, 8) + "..."],
4578
- ["Base URL", baseUrl]
4579
- ]);
4580
- } else {
4581
- printWarning(
4582
- "Not authenticated. Run `tt auth login` to store an API key."
4583
- );
4584
- printDetail([["Base URL", baseUrl]]);
4585
- }
4586
- });
4587
- }
4588
-
4589
- // src/commands/publish.ts
4590
- import { createInterface as createInterface3 } from "readline/promises";
4591
- import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
4592
- import { homedir as homedir4 } from "os";
4593
- import { isAbsolute as isAbsolute4, join as join7, resolve as resolve4 } from "path";
4594
- import { stdin as defaultStdin, stdout as defaultStdout } from "process";
4595
- var MAX_PUBLISH_BYTES = 2 * 1024 * 1024;
4596
- function expandPath2(value, baseDirectory, homeDirectory) {
4597
- if (value === "~") return homeDirectory;
4598
- if (value.startsWith("~/")) return resolve4(homeDirectory, value.slice(2));
4599
- return isAbsolute4(value) ? resolve4(value) : resolve4(baseDirectory, value);
4600
- }
4601
- function resolvePublishStoreRoot(options) {
4602
- const cwd = options?.cwd ?? process.cwd();
4603
- const env = options?.env ?? process.env;
4604
- const homeDirectory = options?.homeDirectory ?? (env.HOME ? resolve4(env.HOME) : homedir4());
4605
- const localConfigPath = join7(cwd, "local-runner.json");
4606
- if (existsSync4(localConfigPath)) {
4607
- try {
4608
- const raw = JSON.parse(readFileSync4(localConfigPath, "utf-8"));
4609
- if (typeof raw.storeRoot === "string" && raw.storeRoot.trim()) {
4610
- return expandPath2(raw.storeRoot, cwd, homeDirectory);
4611
- }
4612
- } catch {
4613
- }
4614
- }
4615
- if (env.TT_LOCAL_HOME && env.TT_LOCAL_HOME.trim()) {
4616
- return expandPath2(env.TT_LOCAL_HOME, cwd, homeDirectory);
4617
- }
4618
- return defaultLocalHome();
4619
- }
4620
- async function confirmPublish(question, input = defaultStdin, output = defaultStdout) {
4621
- if (input.isTTY !== true || output.isTTY !== true) {
4622
- throw new Error(
4623
- "Publishing requires confirmation in interactive mode. Re-run with --yes."
4624
- );
4625
- }
4626
- const rl = createInterface3({ input, output, terminal: true });
4627
- try {
4628
- const answer = (await rl.question(question)).trim().toLowerCase();
4629
- return answer === "y" || answer === "yes";
4630
- } finally {
4631
- rl.close();
4632
- }
4633
- }
4634
- function pickPublishableRun(runs, runId) {
4635
- if (runId) {
4636
- const exact = runs.find((run) => run.id === runId);
4637
- const prefixMatches = exact ? [exact] : runs.filter((run) => run.id.startsWith(runId));
4638
- if (prefixMatches.length === 0) {
4639
- throw new Error(`Run not found: ${runId}`);
4640
- }
4641
- if (prefixMatches.length > 1) {
4642
- throw new Error(
4643
- `Ambiguous run id prefix ${JSON.stringify(runId)}; matches ${prefixMatches.map((run) => shortId(run.id)).join(", ")}. Pass a longer prefix or the full id.`
4644
- );
4645
- }
4646
- const match = prefixMatches[0];
4647
- if (match.status !== "completed" && match.status !== "failed") {
4648
- throw new Error(
4649
- `Run ${shortId(match.id)} is still ${match.status}; only completed or failed runs can be published.`
4650
- );
4651
- }
4652
- return match;
4653
- }
4654
- const candidates = runs.filter((run) => run.status === "completed" || run.status === "failed").sort((a, b) => b.updated_at.localeCompare(a.updated_at));
4655
- const latest = candidates[0];
4656
- if (!latest) {
4657
- throw new Error(
4658
- "No completed or failed local runs found. Run `tt run` first, then publish."
4659
- );
4660
- }
4661
- return latest;
4662
- }
4663
- function assertPublishPayloadSize(payload) {
4664
- const bytes = Buffer.byteLength(JSON.stringify(payload), "utf8");
4665
- if (bytes > MAX_PUBLISH_BYTES) {
4666
- throw new Error(
4667
- `Publish payload is ${bytes} bytes; maximum is ${MAX_PUBLISH_BYTES} bytes. Reduce eval examples or publish a smaller run.`
4668
- );
4669
- }
4670
- }
4671
- function registerPublishCommand(parent) {
4672
- parent.command("publish").description("Publish local run evidence to the Tuned Tensor dashboard").argument("[runId]", "Local run id or prefix (defaults to latest completed/failed run)").option("-k, --api-key <key>", "API key (tt_...)").option("-u, --base-url <url>", "API base URL").option("-y, --yes", "Skip confirmation prompt").option("--dry-run", "Show what would be published without uploading").action(async (runId, cmdOpts) => {
4673
- const opts = {
4674
- apiKey: cmdOpts.apiKey,
4675
- baseUrl: cmdOpts.baseUrl
4676
- };
4677
- if (!cmdOpts.dryRun && !getApiKey(opts)) {
4678
- throw new Error(
4679
- "No API key found. Run `tt auth login` or set TUNED_TENSOR_API_KEY."
4680
- );
4681
- }
4682
- const storeRoot = resolvePublishStoreRoot();
4683
- const store = createLocalStore(storeRoot);
4684
- const runs = await store.listRuns();
4685
- const run = pickPublishableRun(runs, runId);
4686
- const rawReport = await store.getRunReport(run.id);
4687
- const report = runReportSchema.parse(rawReport);
4688
- const specRecord = await store.getSpec(run.behavior_spec_id);
4689
- const exampleCount = report.candidate.results.length || report.baseline.results.length;
4690
- const payload = {
4691
- spec: {
4692
- id: specRecord.id,
4693
- ...specRecord.spec
4694
- },
4695
- report
4696
- };
4697
- assertPublishPayloadSize(payload);
4698
- if (isJsonMode() && cmdOpts.dryRun) {
4699
- printJson({
4700
- dry_run: true,
4701
- store_root: storeRoot,
4702
- run_id: run.id,
4703
- spec_id: specRecord.id,
4704
- spec_name: specRecord.spec.name,
4705
- run_number: run.run_number,
4706
- status: run.status,
4707
- example_count: exampleCount,
4708
- payload
4709
- });
4710
- return;
4711
- }
4712
- if (!isJsonMode()) {
4713
- printDetail([
4714
- ["Spec", specRecord.spec.name],
4715
- ["Run", `${shortId(run.id)} (#${run.run_number})`],
4716
- ["Status", run.status],
4717
- ["Examples", String(exampleCount)],
4718
- ["Store", storeRoot]
4719
- ]);
4720
- printWarning(
4721
- "Prompts and model outputs from the run report will be uploaded to your Tuned Tensor account."
4722
- );
4723
- }
4724
- if (cmdOpts.dryRun) {
4725
- if (isJsonMode()) {
4726
- printJson({
4727
- dry_run: true,
4728
- run_id: run.id,
4729
- spec_id: specRecord.id,
4730
- example_count: exampleCount
4731
- });
4732
- return;
4733
- }
4734
- printSuccess("Dry run only \u2014 nothing was uploaded.");
4735
- return;
4736
- }
4737
- if (!cmdOpts.yes && !isJsonMode()) {
4738
- const ok = await confirmPublish("Publish this run evidence? [y/N] ");
4739
- if (!ok) {
4740
- printWarning("Publish cancelled.");
4741
- return;
4742
- }
4743
- }
4744
- if (!cmdOpts.yes && isJsonMode()) {
4745
- throw new Error(
4746
- "JSON mode requires --yes to publish without an interactive prompt."
4747
- );
4748
- }
4749
- const { data: data3 } = await post("/publish/runs", payload, opts);
4750
- const baseUrl = getBaseUrl(opts).replace(/\/$/, "");
4751
- const dashboardUrl = `${baseUrl}/dashboard/runs/${data3.id}`;
4752
- if (isJsonMode()) {
4753
- printJson({ ...data3, dashboard_url: dashboardUrl });
4754
- return;
4755
- }
4756
- printSuccess(
4757
- `Published run #${data3.run_number} (${shortId(data3.id)}) for ${specRecord.spec.name}`
4758
- );
4759
- printDetail([
4760
- ["Dashboard", dashboardUrl],
4761
- ["Spec ID", shortId(data3.spec_id)]
4762
- ]);
4763
- });
4764
- }
4765
-
4766
4428
  // src/commands/pipeline.ts
4767
- import { existsSync as existsSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
4768
- import { resolve as resolve5 } from "path";
4429
+ import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
4430
+ import { resolve as resolve4 } from "path";
4769
4431
  var DEFAULT_PIPELINE_FILE = "tunedtensor.pipeline.json";
4770
4432
  function parseList(value) {
4771
4433
  if (!value) return void 0;
@@ -4774,10 +4436,10 @@ function parseList(value) {
4774
4436
  return ids;
4775
4437
  }
4776
4438
  function loadPipeline(path) {
4777
- const resolved = resolve5(path);
4778
- if (!existsSync5(resolved)) throw new Error(`Pipeline file not found: ${path}. Run \`tt pipeline init\` to create one.`);
4439
+ const resolved = resolve4(path);
4440
+ if (!existsSync4(resolved)) throw new Error(`Pipeline file not found: ${path}. Run \`tt pipeline init\` to create one.`);
4779
4441
  try {
4780
- return JSON.parse(readFileSync5(resolved, "utf8"));
4442
+ return JSON.parse(readFileSync4(resolved, "utf8"));
4781
4443
  } catch (error) {
4782
4444
  throw new Error(`Pipeline file must be JSON: ${error.message}`);
4783
4445
  }
@@ -4793,8 +4455,8 @@ function outputPlan(plan) {
4793
4455
  function registerPipelineCommands(parent) {
4794
4456
  const pipeline = parent.command("pipeline").description("Create, validate, inspect, and safely dry-run ordered pipeline recipes");
4795
4457
  pipeline.command("init").description("Write a canonical v1 pipeline recipe").option("-f, --file <path>", "Output file", DEFAULT_PIPELINE_FILE).action((options) => {
4796
- const path = resolve5(options.file);
4797
- if (existsSync5(path)) throw new Error(`Pipeline file already exists: ${options.file}.`);
4458
+ const path = resolve4(options.file);
4459
+ if (existsSync4(path)) throw new Error(`Pipeline file already exists: ${options.file}.`);
4798
4460
  const recipe = canonicalPipeline("local");
4799
4461
  writeFileSync3(path, `${JSON.stringify(recipe, null, 2)}
4800
4462
  `);
@@ -4823,9 +4485,9 @@ function registerPipelineCommands(parent) {
4823
4485
  if (remote) {
4824
4486
  throw new Error(`Step "${remote.id}" targets cloud execution. This CLI is local-only; rewrite that step to local or use --dry-run.`);
4825
4487
  }
4826
- const input = await loadLocalRunInput(resolve5(options.spec));
4488
+ const input = await loadLocalRunInput(resolve4(options.spec));
4827
4489
  assertLocalRunInputReady(input.request);
4828
- const config = await loadLocalRunnerConfig(options.config ? resolve5(options.config) : void 0);
4490
+ const config = await loadLocalRunnerConfig(options.config ? resolve4(options.config) : void 0);
4829
4491
  const localPipeline = {
4830
4492
  version: 1,
4831
4493
  ...plan.name ? { name: plan.name } : {},
@@ -4888,7 +4550,7 @@ async function checkForCliUpdate(currentVersion, options = {}) {
4888
4550
  const controller = new AbortController();
4889
4551
  const timeoutMs = options.timeoutMs ?? 750;
4890
4552
  let timeout;
4891
- const request2 = (async () => {
4553
+ const request = (async () => {
4892
4554
  try {
4893
4555
  const response = await (options.fetchImpl ?? fetch)(PACKAGE_LATEST_URL, {
4894
4556
  headers: { accept: "application/json" },
@@ -4907,14 +4569,14 @@ async function checkForCliUpdate(currentVersion, options = {}) {
4907
4569
  return null;
4908
4570
  }
4909
4571
  })();
4910
- const deadline = new Promise((resolve6) => {
4572
+ const deadline = new Promise((resolve5) => {
4911
4573
  timeout = setTimeout(() => {
4912
4574
  controller.abort();
4913
- resolve6(null);
4575
+ resolve5(null);
4914
4576
  }, timeoutMs);
4915
4577
  });
4916
4578
  try {
4917
- return await Promise.race([request2, deadline]);
4579
+ return await Promise.race([request, deadline]);
4918
4580
  } finally {
4919
4581
  if (timeout) clearTimeout(timeout);
4920
4582
  }
@@ -4958,7 +4620,7 @@ async function createDefaultAgentClient(runtime, env, workspaceRoot, getModelRun
4958
4620
  const secret = getApiKey({ apiKey: env.TUNED_TENSOR_API_KEY });
4959
4621
  const providerSecrets = Object.entries(env).filter(([name, value]) => value && /(?:API_KEY|TOKEN|SECRET)$/i.test(name)).map(([, value]) => value).filter((value) => value.length >= 8 && value !== secret);
4960
4622
  return createLocalAgentClient({
4961
- store: runtime.agentStore ?? new LocalAgentStore(join8(getConfigDir(), "agent"), {
4623
+ store: runtime.agentStore ?? new LocalAgentStore(join7(getConfigDir(), "agent"), {
4962
4624
  secretValues: [...secret ? [secret] : [], ...providerSecrets]
4963
4625
  }),
4964
4626
  workspaceRoot,
@@ -5007,7 +4669,7 @@ async function runSelfCommand(args2, options = {}) {
5007
4669
  if (!entrypoint) {
5008
4670
  throw new Error("Cannot locate the tt CLI entrypoint.");
5009
4671
  }
5010
- return await new Promise((resolve6, reject) => {
4672
+ return await new Promise((resolve5, reject) => {
5011
4673
  const child = spawn2(process.execPath, [entrypoint, ...args2], {
5012
4674
  cwd: options.cwd,
5013
4675
  env: options.env ?? process.env,
@@ -5043,7 +4705,7 @@ async function runSelfCommand(args2, options = {}) {
5043
4705
  child.once("close", (exitCode, signal) => {
5044
4706
  cleanup();
5045
4707
  const signalNumber = signal ? osConstants2.signals[signal] : void 0;
5046
- resolve6({
4708
+ resolve5({
5047
4709
  exitCode: exitCode ?? (typeof signalNumber === "number" ? 128 + signalNumber : 1),
5048
4710
  signal
5049
4711
  });
@@ -5064,10 +4726,10 @@ function createProgram(version, runtime = {}) {
5064
4726
  const launchShell = runtime.startShell ?? startInteractiveShell;
5065
4727
  const cwd = runtime.cwd ?? process.cwd();
5066
4728
  const getModelRuntime = createModelRuntimeGetter(runtime);
5067
- const shellRunner = async (request2) => {
4729
+ const shellRunner = async (request) => {
5068
4730
  const root = program.opts();
5069
- return await invokeSelf(request2.args, {
5070
- cwd: request2.cwd,
4731
+ return await invokeSelf(request.args, {
4732
+ cwd: request.cwd,
5071
4733
  env: childEnvironment2(root, env),
5072
4734
  entrypoint: runtime.argv?.[1]
5073
4735
  });
@@ -5104,7 +4766,7 @@ function createProgram(version, runtime = {}) {
5104
4766
  if (root.json) setJsonMode(true);
5105
4767
  if (root.color === false) {
5106
4768
  process.env.FORCE_COLOR = "0";
5107
- chalk7.level = 0;
4769
+ chalk6.level = 0;
5108
4770
  }
5109
4771
  });
5110
4772
  registerLocalCommands(program, {
@@ -5115,8 +4777,6 @@ function createProgram(version, runtime = {}) {
5115
4777
  stdout: runtime.stdout ?? process.stdout,
5116
4778
  stderr: runtime.stderr ?? process.stderr
5117
4779
  });
5118
- registerAuthCommands(program);
5119
- registerPublishCommand(program);
5120
4780
  registerPipelineCommands(program);
5121
4781
  registerAgentCommands(program, {
5122
4782
  env,
@@ -5135,12 +4795,12 @@ function createProgram(version, runtime = {}) {
5135
4795
  `);
5136
4796
  return;
5137
4797
  }
5138
- output.write(`${chalk7.bold.hex("#8B5CF6")("Tuned Tensor status")}
4798
+ output.write(`${chalk6.bold.hex("#8B5CF6")("Tuned Tensor status")}
5139
4799
  `);
5140
4800
  output.write(`${formatShellStatus(context).join("\n")}
5141
4801
 
5142
4802
  `);
5143
- output.write(`${chalk7.bold("Context")}
4803
+ output.write(`${chalk6.bold("Context")}
5144
4804
  `);
5145
4805
  output.write(`${formatShellContext(context).join("\n")}
5146
4806
  `);
@@ -5149,19 +4809,11 @@ function createProgram(version, runtime = {}) {
5149
4809
  program.addHelpText(
5150
4810
  "after",
5151
4811
  `
5152
- Commands:
5153
- tt Open the conversational terminal (TTY only)
5154
- tt status Inspect local project context
5155
- tt doctor Check the host and run prerequisites
5156
- tt run Fine-tune and evaluate on your GPU
5157
- tt auth Store a dashboard API key
5158
- tt publish Upload local run evidence to the dashboard
5159
-
5160
4812
  Examples:
4813
+ tt Open the conversational terminal (TTY only)
5161
4814
  tt doctor tunedtensor.json
5162
4815
  tt run tunedtensor.json --dry-run
5163
4816
  tt runs list
5164
- tt publish --yes
5165
4817
  `
5166
4818
  );
5167
4819
  return program;
@@ -5217,10 +4869,10 @@ async function runCli(version, runtime = {}) {
5217
4869
  error
5218
4870
  });
5219
4871
  await (runtime.startShell ?? startInteractiveShell)({
5220
- runner: async (request2) => await invokeSelf(
5221
- request2.args,
4872
+ runner: async (request) => await invokeSelf(
4873
+ request.args,
5222
4874
  {
5223
- cwd: request2.cwd,
4875
+ cwd: request.cwd,
5224
4876
  env,
5225
4877
  entrypoint: argv[1]
5226
4878
  }
@@ -5241,7 +4893,7 @@ async function runCli(version, runtime = {}) {
5241
4893
  }
5242
4894
 
5243
4895
  // src/index.ts
5244
- runCli("0.13.0-beta.1").catch((err) => {
4896
+ runCli("0.13.0").catch((err) => {
5245
4897
  reportError(err);
5246
4898
  process.exit(1);
5247
4899
  });