@tuned-tensor/cli 0.11.0 → 0.12.0-beta.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
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ TRAINING_MODELS,
3
4
  assertLocalRunInputReady,
4
5
  loadLocalRunInput,
5
6
  loadLocalRunnerConfig,
6
7
  runLocalPipeline
7
- } from "./chunk-DAP2Z7EZ.js";
8
+ } from "./chunk-HDGBDHOB.js";
8
9
 
9
10
  // src/cli.ts
10
11
  import { spawn as spawn4 } from "child_process";
@@ -24,76 +25,6 @@ import { join } from "path";
24
25
  import { Type } from "typebox";
25
26
  import { Value } from "typebox/value";
26
27
 
27
- // src/base-models.ts
28
- var SUPPORTED_BASE_MODELS = [
29
- "google/gemma-4-E2B-it",
30
- "google/gemma-4-E4B-it",
31
- "Qwen/Qwen3.5-2B",
32
- "Qwen/Qwen3-VL-2B-Instruct",
33
- "Qwen/Qwen3.5-4B",
34
- "meta-llama/Llama-3.2-3B-Instruct",
35
- "microsoft/Phi-4-mini-instruct",
36
- "ibm-granite/granite-3.3-2b-instruct",
37
- "bigcode/starcoder2-3b"
38
- ];
39
- var BASE_MODEL_ALIASES = /* @__PURE__ */ new Map();
40
- for (const model of SUPPORTED_BASE_MODELS) {
41
- BASE_MODEL_ALIASES.set(model.toLowerCase(), model);
42
- }
43
- for (const [alias, model] of [
44
- ["google/gemma-4-E2B", "google/gemma-4-E2B-it"],
45
- ["google/gemma-4-e2b", "google/gemma-4-E2B-it"],
46
- ["google/gemma-4-e2b-it", "google/gemma-4-E2B-it"],
47
- ["google/gemma-4-E4B", "google/gemma-4-E4B-it"],
48
- ["google/gemma-4-e4b", "google/gemma-4-E4B-it"],
49
- ["google/gemma-4-e4b-it", "google/gemma-4-E4B-it"],
50
- ["qwen/qwen3.5-2b", "Qwen/Qwen3.5-2B"],
51
- ["Qwen/Qwen3.5-2B-Base", "Qwen/Qwen3.5-2B"],
52
- ["qwen/qwen3.5-2b-base", "Qwen/Qwen3.5-2B"],
53
- ["qwen/qwen3-vl-2b-instruct", "Qwen/Qwen3-VL-2B-Instruct"],
54
- ["Qwen/Qwen3-VL-2B", "Qwen/Qwen3-VL-2B-Instruct"],
55
- ["qwen/qwen3-vl-2b", "Qwen/Qwen3-VL-2B-Instruct"],
56
- ["qwen/qwen3.5-4b", "Qwen/Qwen3.5-4B"],
57
- ["Qwen/Qwen3.5-4B-Base", "Qwen/Qwen3.5-4B"],
58
- ["qwen/qwen3.5-4b-base", "Qwen/Qwen3.5-4B"],
59
- ["meta-llama/llama-3.2-3b-instruct", "meta-llama/Llama-3.2-3B-Instruct"],
60
- ["meta-llama/Llama-3.2-3B", "meta-llama/Llama-3.2-3B-Instruct"],
61
- ["meta-llama/llama-3.2-3b", "meta-llama/Llama-3.2-3B-Instruct"],
62
- ["microsoft/phi-4-mini-instruct", "microsoft/Phi-4-mini-instruct"],
63
- ["phi-4-mini-instruct", "microsoft/Phi-4-mini-instruct"],
64
- ["ibm-granite/granite-3.3-2b-instruct", "ibm-granite/granite-3.3-2b-instruct"],
65
- ["granite-3.3-2b-instruct", "ibm-granite/granite-3.3-2b-instruct"],
66
- ["bigcode/starcoder2-3b", "bigcode/starcoder2-3b"],
67
- ["starcoder2-3b", "bigcode/starcoder2-3b"]
68
- ]) {
69
- BASE_MODEL_ALIASES.set(alias.toLowerCase(), model);
70
- }
71
- var UnsupportedBaseModelError = class extends Error {
72
- constructor(model) {
73
- const supported = SUPPORTED_BASE_MODELS.join(", ");
74
- super(
75
- `Unsupported base_model "${String(model)}". Supported base models: ${supported}`
76
- );
77
- this.name = "UnsupportedBaseModelError";
78
- }
79
- };
80
- function canonicalizeBaseModel(model) {
81
- if (typeof model !== "string" || !model.trim()) {
82
- throw new UnsupportedBaseModelError(model);
83
- }
84
- const canonical = BASE_MODEL_ALIASES.get(model.trim().toLowerCase());
85
- if (!canonical) {
86
- throw new UnsupportedBaseModelError(model);
87
- }
88
- return canonical;
89
- }
90
- function canonicalizeSpecBaseModel(body) {
91
- if ("base_model" in body && body.base_model !== void 0) {
92
- return { ...body, base_model: canonicalizeBaseModel(body.base_model) };
93
- }
94
- return body;
95
- }
96
-
97
28
  // src/eval/rules.ts
98
29
  function validateSpec(spec) {
99
30
  const checks = [];
@@ -258,15 +189,15 @@ var FolderName = Type.String({
258
189
  pattern: "^[A-Za-z0-9][A-Za-z0-9._-]*$",
259
190
  description: "One new folder name directly beneath the current workspace"
260
191
  });
261
- var BaseModel = Type.Unsafe({
192
+ var LocalBaseModel = Type.String({
262
193
  type: "string",
263
- enum: [...SUPPORTED_BASE_MODELS]
194
+ enum: TRAINING_MODELS.map((model) => model.id)
264
195
  });
265
196
  var NonEmptyText = Type.String({ minLength: 1, maxLength: 1e3 });
266
197
  var LocalProjectSpecSchema = Type.Object({
267
198
  name: Type.String({ minLength: 1, maxLength: 255 }),
268
199
  description: Type.Optional(Type.String({ maxLength: 5e3 })),
269
- base_model: BaseModel,
200
+ base_model: LocalBaseModel,
270
201
  system_prompt: Type.String({ minLength: 1, maxLength: 1e4 }),
271
202
  guidelines: Type.Array(NonEmptyText, { minItems: 1, maxItems: 50 }),
272
203
  constraints: Type.Optional(Type.Array(NonEmptyText, { maxItems: 50 })),
@@ -721,6 +652,83 @@ function ensureOpenRouterAppHeaders(modelsPath) {
721
652
  import { randomUUID } from "crypto";
722
653
  import { Type as Type2 } from "typebox";
723
654
 
655
+ // src/base-models.ts
656
+ var SUPPORTED_BASE_MODELS = [
657
+ "google/gemma-4-E2B-it",
658
+ "google/gemma-4-E4B-it",
659
+ "Qwen/Qwen3.5-2B",
660
+ "Qwen/Qwen3-VL-2B-Instruct",
661
+ "Qwen/Qwen3.5-4B",
662
+ "nvidia/NVIDIA-Nemotron-3.5-Lightning-30B-A3B-BF16",
663
+ "meta-models/Muse-Glimmer-30B",
664
+ "meta-llama/Llama-3.2-3B-Instruct",
665
+ "microsoft/Phi-4-mini-instruct",
666
+ "ibm-granite/granite-3.3-2b-instruct",
667
+ "bigcode/starcoder2-3b"
668
+ ];
669
+ var BASE_MODEL_ALIASES = /* @__PURE__ */ new Map();
670
+ for (const model of SUPPORTED_BASE_MODELS) {
671
+ BASE_MODEL_ALIASES.set(model.toLowerCase(), model);
672
+ }
673
+ for (const [alias, model] of [
674
+ ["google/gemma-4-E2B", "google/gemma-4-E2B-it"],
675
+ ["google/gemma-4-e2b", "google/gemma-4-E2B-it"],
676
+ ["google/gemma-4-e2b-it", "google/gemma-4-E2B-it"],
677
+ ["google/gemma-4-E4B", "google/gemma-4-E4B-it"],
678
+ ["google/gemma-4-e4b", "google/gemma-4-E4B-it"],
679
+ ["google/gemma-4-e4b-it", "google/gemma-4-E4B-it"],
680
+ ["qwen/qwen3.5-2b", "Qwen/Qwen3.5-2B"],
681
+ ["Qwen/Qwen3.5-2B-Base", "Qwen/Qwen3.5-2B"],
682
+ ["qwen/qwen3.5-2b-base", "Qwen/Qwen3.5-2B"],
683
+ ["qwen/qwen3-vl-2b-instruct", "Qwen/Qwen3-VL-2B-Instruct"],
684
+ ["Qwen/Qwen3-VL-2B", "Qwen/Qwen3-VL-2B-Instruct"],
685
+ ["qwen/qwen3-vl-2b", "Qwen/Qwen3-VL-2B-Instruct"],
686
+ ["qwen/qwen3.5-4b", "Qwen/Qwen3.5-4B"],
687
+ ["Qwen/Qwen3.5-4B-Base", "Qwen/Qwen3.5-4B"],
688
+ ["qwen/qwen3.5-4b-base", "Qwen/Qwen3.5-4B"],
689
+ [
690
+ "nvidia/nvidia-nemotron-3.5-lightning-30b-a3b-bf16",
691
+ "nvidia/NVIDIA-Nemotron-3.5-Lightning-30B-A3B-BF16"
692
+ ],
693
+ ["meta-models/muse-glimmer-30b", "meta-models/Muse-Glimmer-30B"],
694
+ ["meta-llama/llama-3.2-3b-instruct", "meta-llama/Llama-3.2-3B-Instruct"],
695
+ ["meta-llama/Llama-3.2-3B", "meta-llama/Llama-3.2-3B-Instruct"],
696
+ ["meta-llama/llama-3.2-3b", "meta-llama/Llama-3.2-3B-Instruct"],
697
+ ["microsoft/phi-4-mini-instruct", "microsoft/Phi-4-mini-instruct"],
698
+ ["phi-4-mini-instruct", "microsoft/Phi-4-mini-instruct"],
699
+ ["ibm-granite/granite-3.3-2b-instruct", "ibm-granite/granite-3.3-2b-instruct"],
700
+ ["granite-3.3-2b-instruct", "ibm-granite/granite-3.3-2b-instruct"],
701
+ ["bigcode/starcoder2-3b", "bigcode/starcoder2-3b"],
702
+ ["starcoder2-3b", "bigcode/starcoder2-3b"]
703
+ ]) {
704
+ BASE_MODEL_ALIASES.set(alias.toLowerCase(), model);
705
+ }
706
+ var UnsupportedBaseModelError = class extends Error {
707
+ constructor(model) {
708
+ const supported = SUPPORTED_BASE_MODELS.join(", ");
709
+ super(
710
+ `Unsupported base_model "${String(model)}". Supported base models: ${supported}`
711
+ );
712
+ this.name = "UnsupportedBaseModelError";
713
+ }
714
+ };
715
+ function canonicalizeBaseModel(model) {
716
+ if (typeof model !== "string" || !model.trim()) {
717
+ throw new UnsupportedBaseModelError(model);
718
+ }
719
+ const canonical = BASE_MODEL_ALIASES.get(model.trim().toLowerCase());
720
+ if (!canonical) {
721
+ throw new UnsupportedBaseModelError(model);
722
+ }
723
+ return canonical;
724
+ }
725
+ function canonicalizeSpecBaseModel(body) {
726
+ if ("base_model" in body && body.base_model !== void 0) {
727
+ return { ...body, base_model: canonicalizeBaseModel(body.base_model) };
728
+ }
729
+ return body;
730
+ }
731
+
724
732
  // src/pipeline.ts
725
733
  import {
726
734
  canonicalPipeline as canonicalPortablePipeline,
@@ -837,7 +845,7 @@ var RunBody = Type2.Object({
837
845
  }, { additionalProperties: false })),
838
846
  split_ratios: Type2.Optional(SplitRatios)
839
847
  }, { additionalProperties: false });
840
- var BaseModel2 = Type2.Union(
848
+ var BaseModel = Type2.Union(
841
849
  SUPPORTED_BASE_MODELS.map((model) => Type2.Literal(model))
842
850
  );
843
851
  var PipelineDocument = Type2.Object({
@@ -864,7 +872,7 @@ var CreateSpecBody = Type2.Object({
864
872
  guidelines: Type2.Optional(Guidelines),
865
873
  examples: Examples,
866
874
  constraints: Type2.Optional(Guidelines),
867
- base_model: Type2.Optional(BaseModel2)
875
+ base_model: Type2.Optional(BaseModel)
868
876
  }, { additionalProperties: false });
869
877
  var UpdateSpecBody = Type2.Object({
870
878
  name: Type2.Optional(Type2.String({ minLength: 1, maxLength: 255 })),
@@ -873,7 +881,7 @@ var UpdateSpecBody = Type2.Object({
873
881
  guidelines: Type2.Optional(Guidelines),
874
882
  examples: Type2.Optional(Examples),
875
883
  constraints: Type2.Optional(Guidelines),
876
- base_model: Type2.Optional(BaseModel2)
884
+ base_model: Type2.Optional(BaseModel)
877
885
  }, { additionalProperties: false });
878
886
  function record2(value) {
879
887
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
@@ -1762,8 +1770,10 @@ var SLASH_COMMANDS = [
1762
1770
  { path: "/help", description: "Show commands; add a word to filter." },
1763
1771
  { path: "/status", description: "Show lightweight workflow status." },
1764
1772
  { path: "/context", description: "Show the current project and backend context." },
1765
- { path: "/mode cloud", description: "Use the managed cloud workflow." },
1766
- { path: "/mode local", description: "Use the local GPU workflow." },
1773
+ { path: "/cloud", description: "Switch to the managed cloud workflow." },
1774
+ { path: "/local", description: "Switch to the local GPU workflow." },
1775
+ { path: "/mode cloud", description: "Alias for /cloud." },
1776
+ { path: "/mode local", description: "Alias for /local." },
1767
1777
  { path: "/model", description: "Show the active model; /model <id> activates a local model." },
1768
1778
  { path: "/cd", description: "Change the shell's working directory." },
1769
1779
  { path: "/clear", description: "Clear the terminal." },
@@ -1874,6 +1884,14 @@ function cloudConfigPath(env, homeDirectory) {
1874
1884
  const configHome = env.XDG_CONFIG_HOME ? resolve(env.XDG_CONFIG_HOME) : join5(homeDirectory, ".config");
1875
1885
  return join5(configHome, "tuned-tensor", "config.json");
1876
1886
  }
1887
+ function agentSelectionFrom(env, configAgent) {
1888
+ const stored = configAgent && typeof configAgent === "object" && !Array.isArray(configAgent) ? configAgent : {};
1889
+ const provider = env.TUNED_TENSOR_AGENT_PROVIDER?.trim() || stringField(stored, "provider");
1890
+ const model = env.TUNED_TENSOR_AGENT_MODEL?.trim() || stringField(stored, "model");
1891
+ const thinking = env.TUNED_TENSOR_AGENT_THINKING?.trim() || stringField(stored, "thinking");
1892
+ if (!provider && !model && !thinking) return void 0;
1893
+ return { provider, model, thinking };
1894
+ }
1877
1895
  function redactApiKey(key) {
1878
1896
  if (!key) return void 0;
1879
1897
  if (key.length <= 4) return "\u2026";
@@ -1971,6 +1989,7 @@ async function discoverShellContext(options = {}) {
1971
1989
  const storedApiKey = stringField(cloudConfigJson.value, "api_key");
1972
1990
  const apiKey = environmentApiKey || storedApiKey;
1973
1991
  const baseUrl = env.TUNED_TENSOR_URL?.trim() || stringField(cloudConfigJson.value, "base_url") || "https://tunedtensor.com";
1992
+ const agent = agentSelectionFrom(env, cloudConfigJson.value?.agent);
1974
1993
  const environmentTarget = targetFromEnvironment(env);
1975
1994
  if (env.TT_TARGET && !environmentTarget) {
1976
1995
  warnings.push(`Ignoring invalid TT_TARGET=${JSON.stringify(env.TT_TARGET)}; use cloud or local.`);
@@ -2001,12 +2020,19 @@ async function discoverShellContext(options = {}) {
2001
2020
  activeModelId,
2002
2021
  latestRun
2003
2022
  },
2023
+ agent,
2004
2024
  warnings
2005
2025
  };
2006
2026
  }
2007
2027
  function valueOrDash(value) {
2008
2028
  return value === void 0 || value === "" ? "\u2014" : String(value);
2009
2029
  }
2030
+ function agentLabel(context) {
2031
+ const agent = context.agent;
2032
+ if (!agent?.provider && !agent?.model) return "not configured";
2033
+ const id = [agent.provider, agent.model].filter(Boolean).join("/");
2034
+ return agent.thinking ? `${id} (thinking ${agent.thinking})` : id;
2035
+ }
2010
2036
  function targetSourceLabel(source) {
2011
2037
  switch (source) {
2012
2038
  case "environment":
@@ -2028,6 +2054,7 @@ function formatShellContext(context, selectedTarget, targetSource) {
2028
2054
  `Spec ID ${valueOrDash(context.spec?.id)}`,
2029
2055
  `Base model ${valueOrDash(context.spec?.baseModel)}`,
2030
2056
  `Examples ${valueOrDash(context.spec?.exampleCount)}`,
2057
+ `Agent model ${agentLabel(context)}`,
2031
2058
  `Cloud endpoint ${context.cloud.baseUrl}`,
2032
2059
  `Cloud auth ${context.cloud.authenticated ? `yes (${context.cloud.keyPrefix})` : "no"}`,
2033
2060
  `Local config ${context.local.configPath ?? "not found"}`,
@@ -2040,7 +2067,8 @@ function formatShellContext(context, selectedTarget, targetSource) {
2040
2067
  function formatShellStatus(context, selectedTarget) {
2041
2068
  const lines = [
2042
2069
  `Workflow ${selectedTarget}`,
2043
- `Spec ${context.spec?.name ?? (context.spec ? "unnamed" : "not found")}`
2070
+ `Spec ${context.spec?.name ?? (context.spec ? "unnamed" : "not found")}`,
2071
+ `Agent model ${agentLabel(context)}`
2044
2072
  ];
2045
2073
  if (selectedTarget === "cloud") {
2046
2074
  lines.push(
@@ -2219,6 +2247,8 @@ var SLASH_NAMES = /* @__PURE__ */ new Set([
2219
2247
  "status",
2220
2248
  "context",
2221
2249
  "mode",
2250
+ "cloud",
2251
+ "local",
2222
2252
  "model",
2223
2253
  "clear",
2224
2254
  "cd",
@@ -2382,14 +2412,22 @@ function helpText(mode, query, palette = false) {
2382
2412
  function activeModelLabel(snapshot) {
2383
2413
  return snapshot.mode === "local" ? snapshot.context.local.activeModelId ?? "base" : snapshot.context.spec?.baseModel ?? "\u2014";
2384
2414
  }
2415
+ function agentModelLabel(context) {
2416
+ const agent = context.agent;
2417
+ if (!agent?.provider && !agent?.model) return "not configured";
2418
+ return [agent.provider, agent.model].filter(Boolean).join("/") || "not configured";
2419
+ }
2385
2420
  function renderShellBanner(snapshot) {
2386
2421
  const spec = snapshot.context.spec?.name ?? snapshot.context.spec?.path ?? "no spec";
2387
2422
  const heading = snapshot.version ? `${accent.bold("tt")} ${chalk.dim(`v${snapshot.version}`)}` : accent.bold("tt");
2388
2423
  const lines = [
2389
2424
  heading,
2390
2425
  `${accent(snapshot.mode)}${chalk.dim(
2391
- ` \xB7 ${snapshot.context.projectName} \xB7 ${spec} \xB7 model ${activeModelLabel(snapshot)}`
2426
+ ` \xB7 ${snapshot.context.projectName} \xB7 ${spec}`
2392
2427
  )}`,
2428
+ chalk.dim(
2429
+ `agent ${agentModelLabel(snapshot.context)} \xB7 workflow model ${activeModelLabel(snapshot)}`
2430
+ ),
2393
2431
  chalk.dim("ctrl+c stop/clear \xB7 ctrl+d exit \xB7 /help commands \xB7 tab complete"),
2394
2432
  "",
2395
2433
  chalk.dim("Ask TT anything. Known commands run directly.")
@@ -2535,6 +2573,14 @@ var TunedTensorShellSession = class _TunedTensorShellSession {
2535
2573
  `);
2536
2574
  return "continue";
2537
2575
  }
2576
+ case "cloud":
2577
+ case "local":
2578
+ assertNoArgs(command.name, command.args);
2579
+ this.mode = command.name;
2580
+ this.modeSource = "session";
2581
+ this.io.write(`${successMark()} Workflow switched to ${this.mode}.
2582
+ `);
2583
+ return "continue";
2538
2584
  case "model": {
2539
2585
  if (command.args.length === 0) {
2540
2586
  await this.refreshContext();
@@ -8080,16 +8126,22 @@ function registerAgentCommands(parent, options) {
8080
8126
  const runtime = await options.getRuntime();
8081
8127
  const resolved = resolveAgentModelDefinition(runtime, selection);
8082
8128
  const authenticated = runtime.hasConfiguredAuth(selection.provider);
8129
+ const providerName = runtime.getProviders().find(
8130
+ (provider) => provider.id === selection.provider
8131
+ )?.name;
8083
8132
  const value = {
8084
8133
  execution: "local",
8085
8134
  provider: selection.provider,
8135
+ provider_name: providerName,
8086
8136
  model: selection.model,
8137
+ model_name: resolved.model.name,
8087
8138
  thinking: selection.thinking,
8088
8139
  authenticated,
8089
8140
  supports_thinking: resolved.model.reasoning !== false
8090
8141
  };
8142
+ const modelLabel = resolved.model.name && resolved.model.name !== selection.model ? `${resolved.model.name} (${selection.provider}/${selection.model})` : `${selection.provider}/${selection.model}`;
8091
8143
  options.output.write(isJsonMode() ? `${JSON.stringify(value, null, 2)}
8092
- ` : `Local agent: ${value.provider}/${value.model} (thinking: ${value.thinking}, auth: ${authenticated ? "configured" : "required"})
8144
+ ` : `Local agent: ${modelLabel} (thinking: ${value.thinking}, auth: ${authenticated ? "configured" : "required"})
8093
8145
  `);
8094
8146
  });
8095
8147
  agent.command("models").description("List Pi provider models available to the local agent").option("--provider <provider>", "Filter by Pi provider ID").option("--all", "Include models whose provider auth is not configured").action(async (commandOptions) => {
@@ -8677,7 +8729,7 @@ async function runCli(version, runtime = {}) {
8677
8729
  }
8678
8730
 
8679
8731
  // src/index.ts
8680
- runCli("0.11.0").catch((err) => {
8732
+ runCli("0.12.0-beta.0").catch((err) => {
8681
8733
  reportError(err);
8682
8734
  process.exit(1);
8683
8735
  });