@tuned-tensor/cli 0.21.0 → 0.22.1
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 +97 -5
- package/dist/{chunk-PVLX7LJI.js → chunk-RPWOCVIL.js} +1320 -229
- package/dist/chunk-RPWOCVIL.js.map +1 -0
- package/dist/index.js +527 -55
- package/dist/index.js.map +1 -1
- package/dist/local-runtime.js +107 -44
- package/dist/local-runtime.js.map +1 -1
- package/docs/local-runtime/architecture.md +38 -0
- package/docs/local-runtime/aws-gpu.md +2 -0
- package/docs/spec-workflow.md +7 -0
- package/package.json +1 -1
- package/training/adapter/src/hub_download.py +384 -0
- package/training/adapter/src/prefetch.py +20 -31
- package/training/adapter/src/prefetch_dataset.py +116 -0
- package/training/adapter/src/serve.py +5 -1
- package/dist/chunk-PVLX7LJI.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
TRAINING_MODELS,
|
|
9
9
|
assertFoundationSettingsMatch,
|
|
10
10
|
assessHardware,
|
|
11
|
+
auditRun,
|
|
11
12
|
buildDecisionPythonCommand,
|
|
12
13
|
buildFoundationPythonCommand,
|
|
13
14
|
buildSystemMessage,
|
|
@@ -18,10 +19,12 @@ import {
|
|
|
18
19
|
configForSpec,
|
|
19
20
|
createExecutionPlan,
|
|
20
21
|
createLocalStore,
|
|
22
|
+
createRunConsoleReporter,
|
|
21
23
|
decisionLabels,
|
|
22
24
|
defaultLocalHome,
|
|
23
25
|
defaultStoreRoot,
|
|
24
26
|
deriveSampleSeed,
|
|
27
|
+
ensureDatasetCached,
|
|
25
28
|
evalReportSchema,
|
|
26
29
|
evaluateCapabilities,
|
|
27
30
|
expandUserPath,
|
|
@@ -30,6 +33,7 @@ import {
|
|
|
30
33
|
formatHostStatusLine,
|
|
31
34
|
getAgentConfigDir,
|
|
32
35
|
getConfigDir,
|
|
36
|
+
getTunedTensorHome,
|
|
33
37
|
hardenExistingLocalStore,
|
|
34
38
|
isFoundationPipeline,
|
|
35
39
|
loadLocalRunInput,
|
|
@@ -55,13 +59,13 @@ import {
|
|
|
55
59
|
warningsFromSnapshot,
|
|
56
60
|
withDecisionPythonEnvironment,
|
|
57
61
|
withFoundationPythonEnvironment
|
|
58
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-RPWOCVIL.js";
|
|
59
63
|
|
|
60
64
|
// src/cli.ts
|
|
61
|
-
import { spawn as
|
|
65
|
+
import { spawn as spawn6 } from "child_process";
|
|
62
66
|
import { constants as osConstants2 } from "os";
|
|
63
67
|
import { Command } from "commander";
|
|
64
|
-
import
|
|
68
|
+
import chalk15 from "chalk";
|
|
65
69
|
|
|
66
70
|
// src/local-agent-client.ts
|
|
67
71
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
@@ -2163,7 +2167,9 @@ function createTunedTensorTools(api, options = {}) {
|
|
|
2163
2167
|
runtime: Type2.Optional(Type2.Union([Type2.Record(Type2.String(), Type2.Unknown()), Type2.Null()])),
|
|
2164
2168
|
evaluation: Type2.Optional(Type2.Union([Type2.Record(Type2.String(), Type2.Unknown()), Type2.Null()])),
|
|
2165
2169
|
pipeline: Type2.Optional(Type2.Union([Type2.Record(Type2.String(), Type2.Unknown()), Type2.Null()])),
|
|
2166
|
-
dataset_prebuilt: Type2.Optional(Type2.Record(Type2.String(), Type2.Unknown()
|
|
2170
|
+
dataset_prebuilt: Type2.Optional(Type2.Record(Type2.String(), Type2.Unknown(), {
|
|
2171
|
+
description: "Local chat JSONL files ({training, validation|test}), or a Hugging Face dataset: {huggingface: {repo, revision?: 40-char commit, columns?: {input, output}}, training: 'repo/path.jsonl', test|validation: ...}. The user downloads it with `tt datasets prefetch tunedtensor.json`."
|
|
2172
|
+
}))
|
|
2167
2173
|
}, { additionalProperties: false })
|
|
2168
2174
|
}, { additionalProperties: false }),
|
|
2169
2175
|
async (p) => {
|
|
@@ -3752,6 +3758,8 @@ function gpuDetail(gpu) {
|
|
|
3752
3758
|
} else if (gpu.memory_total_bytes !== void 0) {
|
|
3753
3759
|
const used = gpu.memory_used_bytes;
|
|
3754
3760
|
parts.push(used === void 0 ? `${formatGiB(gpu.memory_total_bytes)} GiB VRAM` : `VRAM ${formatGiB(used)}/${formatGiB(gpu.memory_total_bytes)} GiB`);
|
|
3761
|
+
} else if (gpu.unified_memory) {
|
|
3762
|
+
parts.push("unified with system RAM");
|
|
3755
3763
|
}
|
|
3756
3764
|
if (gpu.temperature_c !== void 0) parts.push(`${Math.round(gpu.temperature_c)}\xB0C`);
|
|
3757
3765
|
return parts.join(" ");
|
|
@@ -3903,6 +3911,7 @@ function renderBanner(input) {
|
|
|
3903
3911
|
|
|
3904
3912
|
// src/local-runtime/live-usage.ts
|
|
3905
3913
|
import { execFile } from "child_process";
|
|
3914
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
3906
3915
|
import { statfs } from "fs/promises";
|
|
3907
3916
|
import { cpus, freemem, homedir, loadavg, totalmem } from "os";
|
|
3908
3917
|
import { dirname as dirname3, join as join7, resolve as resolve2 } from "path";
|
|
@@ -3974,6 +3983,50 @@ function queryNvidia(env, timeoutMs) {
|
|
|
3974
3983
|
function tidyCpuModel(model) {
|
|
3975
3984
|
return model.replace(/\((?:R|TM|tm|r)\)/g, "").replace(/\s+(?:CPU|Processor)\b/gi, "").replace(/\s*@\s*[\d.]+\s*[GM]Hz/i, "").replace(/\s+\d+-Core$/i, "").replace(/\s+/g, " ").trim() || "CPU";
|
|
3976
3985
|
}
|
|
3986
|
+
var ARM_CORES = {
|
|
3987
|
+
"0xd03": "Cortex-A53",
|
|
3988
|
+
"0xd05": "Cortex-A55",
|
|
3989
|
+
"0xd08": "Cortex-A72",
|
|
3990
|
+
"0xd0b": "Cortex-A76",
|
|
3991
|
+
"0xd0c": "Neoverse-N1",
|
|
3992
|
+
"0xd40": "Neoverse-V1",
|
|
3993
|
+
"0xd41": "Cortex-A78",
|
|
3994
|
+
"0xd44": "Cortex-X1",
|
|
3995
|
+
"0xd47": "Cortex-A710",
|
|
3996
|
+
"0xd48": "Cortex-X2",
|
|
3997
|
+
"0xd49": "Neoverse-N2",
|
|
3998
|
+
"0xd4d": "Cortex-A715",
|
|
3999
|
+
"0xd4e": "Cortex-X3",
|
|
4000
|
+
"0xd4f": "Neoverse-V2",
|
|
4001
|
+
"0xd80": "Cortex-A520",
|
|
4002
|
+
"0xd81": "Cortex-A720",
|
|
4003
|
+
"0xd82": "Cortex-X4",
|
|
4004
|
+
"0xd84": "Neoverse-V3",
|
|
4005
|
+
"0xd85": "Cortex-X925",
|
|
4006
|
+
"0xd87": "Cortex-A725",
|
|
4007
|
+
"0xd8e": "Neoverse-N3"
|
|
4008
|
+
};
|
|
4009
|
+
function armCpuModel(cpuinfo) {
|
|
4010
|
+
const names = [];
|
|
4011
|
+
let implementer;
|
|
4012
|
+
for (const line of cpuinfo.split(/\r?\n/)) {
|
|
4013
|
+
const [key, value] = line.split(":").map((item) => item.trim().toLowerCase());
|
|
4014
|
+
if (key === "cpu implementer") implementer = value;
|
|
4015
|
+
if (key !== "cpu part" || !value) continue;
|
|
4016
|
+
const name = implementer === "0x41" ? ARM_CORES[value] : void 0;
|
|
4017
|
+
if (name && !names.includes(name)) names.push(name);
|
|
4018
|
+
}
|
|
4019
|
+
return names.length > 0 ? names.join(" + ") : void 0;
|
|
4020
|
+
}
|
|
4021
|
+
function cpuModel(reported, platform, arch) {
|
|
4022
|
+
const model = tidyCpuModel(reported ?? "");
|
|
4023
|
+
if (platform !== "linux" || !/^(?:unknown|CPU)$/i.test(model)) return model;
|
|
4024
|
+
try {
|
|
4025
|
+
return armCpuModel(readFileSync5("/proc/cpuinfo", "utf8")) ?? (arch === "arm64" ? "Arm CPU" : model);
|
|
4026
|
+
} catch {
|
|
4027
|
+
return arch === "arm64" ? "Arm CPU" : model;
|
|
4028
|
+
}
|
|
4029
|
+
}
|
|
3977
4030
|
async function modelCacheDisk(env) {
|
|
3978
4031
|
const path = resolve2(env.HF_HOME?.trim() || join7(homedir(), ".cache", "huggingface"));
|
|
3979
4032
|
for (let probe = path, depth = 0; depth < 8; depth += 1) {
|
|
@@ -3992,9 +4045,9 @@ async function modelCacheDisk(env) {
|
|
|
3992
4045
|
}
|
|
3993
4046
|
return void 0;
|
|
3994
4047
|
}
|
|
3995
|
-
function appleGpu(
|
|
4048
|
+
function appleGpu(cpuModel2, platform, arch) {
|
|
3996
4049
|
if (platform !== "darwin" || arch !== "arm64") return void 0;
|
|
3997
|
-
const chip = /apple/i.test(
|
|
4050
|
+
const chip = /apple/i.test(cpuModel2) ? cpuModel2.trim() : "Apple Silicon";
|
|
3998
4051
|
return {
|
|
3999
4052
|
index: 0,
|
|
4000
4053
|
name: `${chip} GPU`,
|
|
@@ -4015,7 +4068,7 @@ async function sampleLiveUsage(options = {}) {
|
|
|
4015
4068
|
]);
|
|
4016
4069
|
const after = cpuTimes();
|
|
4017
4070
|
const list = cpus();
|
|
4018
|
-
const model =
|
|
4071
|
+
const model = cpuModel(list[0]?.model, platform, arch);
|
|
4019
4072
|
const total = totalmem();
|
|
4020
4073
|
const apple = nvidia.gpus.length === 0 ? appleGpu(model, platform, arch) : void 0;
|
|
4021
4074
|
const [one, five, fifteen] = loadavg();
|
|
@@ -4061,17 +4114,21 @@ var COMMAND_CATALOG = [
|
|
|
4061
4114
|
{ path: "runs report", description: "Show a local run report.", group: "Inspect", modes: LOCAL },
|
|
4062
4115
|
{ path: "runs compare", description: "Compare two local run reports.", group: "Inspect", modes: LOCAL },
|
|
4063
4116
|
{ path: "runs events", description: "Show local run progress events.", group: "Inspect", modes: LOCAL },
|
|
4117
|
+
{ path: "runs audit", description: "Verify a run's event log and report, with timeline and provenance.", group: "Inspect", modes: LOCAL },
|
|
4064
4118
|
{ path: "models list", description: "List local models.", group: "Inspect", modes: LOCAL },
|
|
4065
4119
|
{ path: "models get", description: "Show a local model.", group: "Inspect", modes: LOCAL },
|
|
4066
4120
|
{ path: "models serve", description: "Serve a model through an OpenAI-compatible API.", group: "Serving", modes: LOCAL },
|
|
4067
4121
|
{ path: "models verify", description: "Verify a local model artifact.", group: "Serving", modes: LOCAL },
|
|
4068
4122
|
{ path: "models prefetch", description: "Download the local base-model snapshot.", group: "Serving", modes: LOCAL },
|
|
4069
4123
|
{ path: "models verify-base", description: "Verify the local base-model snapshot.", group: "Serving", modes: LOCAL },
|
|
4124
|
+
{ path: "datasets prefetch", description: "Download the spec's Hugging Face dataset files.", group: "Workflow", modes: LOCAL },
|
|
4125
|
+
{ path: "datasets verify", description: "Verify the cached Hugging Face dataset files.", group: "Workflow", modes: LOCAL },
|
|
4070
4126
|
{ path: "models active", description: "Show the active local model.", group: "Serving", modes: LOCAL },
|
|
4071
4127
|
{ path: "models activate", description: "Activate a verified local model.", group: "Serving", modes: LOCAL },
|
|
4072
4128
|
{ path: "models rollback", description: "Roll back the active local model.", group: "Serving", modes: LOCAL },
|
|
4073
4129
|
{ path: "serve", description: "Serve a local adapter, active model, or base model.", group: "Serving", modes: LOCAL },
|
|
4074
4130
|
{ path: "info", description: "Show local runtime package information.", group: "Inspect", modes: LOCAL },
|
|
4131
|
+
{ path: "upgrade", description: "Upgrade tt to the latest release.", group: "Inspect", modes: LOCAL },
|
|
4075
4132
|
{ path: "status", description: "Show local project context.", group: "Inspect", modes: LOCAL },
|
|
4076
4133
|
{ path: "agent models", description: "List provider models for the laptop-local TT agent.", group: "Inspect", modes: LOCAL },
|
|
4077
4134
|
{ path: "agent configure", description: "Select the laptop-local TT agent model.", group: "Inspect", modes: LOCAL },
|
|
@@ -6385,10 +6442,22 @@ function renderValidate(value) {
|
|
|
6385
6442
|
["Spec", text(value.behavior_spec_id)],
|
|
6386
6443
|
["Base model", text(value.base_model)],
|
|
6387
6444
|
["Dataset", text(value.dataset_format)],
|
|
6445
|
+
["Hugging Face", huggingFaceDatasetLabel(value)],
|
|
6388
6446
|
["Artifacts", text(value.artifact_root)],
|
|
6389
6447
|
["Store", text(value.store_root)],
|
|
6390
6448
|
["Dry run", text(value.dry_run)]
|
|
6391
6449
|
]);
|
|
6450
|
+
if (value.dataset_status === "not_downloaded") {
|
|
6451
|
+
printWarning(`Dataset files are not downloaded yet; dataset contents were not checked. Run \`${text(value.next_step) ?? "tt datasets prefetch"}\`.`);
|
|
6452
|
+
}
|
|
6453
|
+
}
|
|
6454
|
+
function huggingFaceDatasetLabel(value) {
|
|
6455
|
+
const source = record3(value.dataset_source) ?? record3(value.dataset_huggingface);
|
|
6456
|
+
const repo = text(source?.repo);
|
|
6457
|
+
if (!repo) return void 0;
|
|
6458
|
+
const revision = text(source?.revision) ?? "main";
|
|
6459
|
+
const status2 = value.dataset_status === "not_downloaded" ? "not downloaded" : "cached";
|
|
6460
|
+
return `${repo}@${revision} (${status2}${source?.pinned === false || !text(source?.revision) ? ", unpinned" : ""})`;
|
|
6392
6461
|
}
|
|
6393
6462
|
function renderRun(value) {
|
|
6394
6463
|
const runStatus = text(value.status) ?? "unknown";
|
|
@@ -6443,6 +6512,68 @@ function renderRunEvents(value) {
|
|
|
6443
6512
|
])
|
|
6444
6513
|
);
|
|
6445
6514
|
}
|
|
6515
|
+
function formatSeconds(value) {
|
|
6516
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return "running";
|
|
6517
|
+
const seconds = Math.round(value);
|
|
6518
|
+
const hours = Math.floor(seconds / 3600);
|
|
6519
|
+
const minutes = Math.floor(seconds % 3600 / 60);
|
|
6520
|
+
const rest = seconds % 60;
|
|
6521
|
+
if (hours) return `${hours}h ${String(minutes).padStart(2, "0")}m`;
|
|
6522
|
+
if (minutes) return `${minutes}m ${String(rest).padStart(2, "0")}s`;
|
|
6523
|
+
return `${rest}s`;
|
|
6524
|
+
}
|
|
6525
|
+
function shortHash(value) {
|
|
6526
|
+
const hash = text(value);
|
|
6527
|
+
return hash ? hash.slice(0, 12) : void 0;
|
|
6528
|
+
}
|
|
6529
|
+
function renderRunAudit(value) {
|
|
6530
|
+
const verdict = text(value.verdict);
|
|
6531
|
+
const chain = record3(value.chain);
|
|
6532
|
+
const reportInfo = record3(value.report);
|
|
6533
|
+
const findings = Array.isArray(value.findings) ? value.findings.map(String) : [];
|
|
6534
|
+
if (verdict === "verified") printSuccess("Run evidence verified: event log intact and report unchanged since completion");
|
|
6535
|
+
else if (verdict === "tampered") printError("Run evidence does not verify");
|
|
6536
|
+
else printWarning("Run evidence is incomplete");
|
|
6537
|
+
for (const finding of findings) console.log(` - ${finding}`);
|
|
6538
|
+
printDetail([
|
|
6539
|
+
["Run", text(value.run_id)],
|
|
6540
|
+
["Status", status(value.status)],
|
|
6541
|
+
["Event chain", `${text(chain?.status) ?? "\u2014"} (${text(chain?.chained_events) ?? 0}/${text(chain?.events) ?? 0} chained, head ${shortHash(chain?.head_hash) ?? "\u2014"})`],
|
|
6542
|
+
["Report sha256", shortHash(reportInfo?.recorded_sha256) ?? "not recorded"]
|
|
6543
|
+
]);
|
|
6544
|
+
const timeline = rows(value.timeline);
|
|
6545
|
+
if (timeline.length > 0) {
|
|
6546
|
+
console.log("");
|
|
6547
|
+
printTable(
|
|
6548
|
+
["Started", "Stage", "Duration", "Status"],
|
|
6549
|
+
timeline.map((entry) => [
|
|
6550
|
+
formatDate(text(entry.started_at)),
|
|
6551
|
+
text(entry.stage) ?? "\u2014",
|
|
6552
|
+
formatSeconds(entry.duration_seconds),
|
|
6553
|
+
status(entry.status)
|
|
6554
|
+
])
|
|
6555
|
+
);
|
|
6556
|
+
}
|
|
6557
|
+
const provenance = record3(value.provenance);
|
|
6558
|
+
if (provenance) {
|
|
6559
|
+
const software = record3(provenance.software);
|
|
6560
|
+
const execution = record3(provenance.execution);
|
|
6561
|
+
const spec = record3(provenance.spec);
|
|
6562
|
+
const baseModel = record3(provenance.base_model);
|
|
6563
|
+
const data3 = record3(provenance.data);
|
|
6564
|
+
const files = record3(data3?.file_sha256) ?? {};
|
|
6565
|
+
console.log("");
|
|
6566
|
+
printDetail([
|
|
6567
|
+
["TT", `${text(software?.tt_version) ?? "\u2014"} (node ${text(software?.node_version) ?? "\u2014"}, ${text(software?.platform) ?? "\u2014"}/${text(software?.arch) ?? "\u2014"})`],
|
|
6568
|
+
["Execution", `${text(execution?.target) ?? "\u2014"}${text(execution?.instance_id) ? ` ${text(execution?.instance_id)}` : ""} via ${text(execution?.training_backend) ?? "\u2014"}`],
|
|
6569
|
+
["Spec", `${text(spec?.file_path) ?? text(spec?.behavior_spec_id) ?? "\u2014"} (sha256 ${shortHash(spec?.file_sha256) ?? shortHash(spec?.snapshot_sha256) ?? "\u2014"})`],
|
|
6570
|
+
["Base model", `${text(baseModel?.id) ?? "\u2014"}@${shortHash(baseModel?.revision) ?? "unpinned"}`],
|
|
6571
|
+
...Object.entries(files).map(([split, hash]) => [`Data ${split}`, `sha256 ${shortHash(hash)}`]),
|
|
6572
|
+
["Training data", `sha256 ${shortHash(data3?.compiled_training_sha256) ?? "\u2014"} (${text(data3?.training_examples) ?? "\u2014"} examples)`],
|
|
6573
|
+
["Evaluation", `${text(data3?.eval_examples_used) ?? "\u2014"}/${text(data3?.eval_examples_total) ?? "\u2014"} ${text(data3?.eval_split) ?? ""} (seed ${text(data3?.eval_sample_seed) ?? "\u2014"})`]
|
|
6574
|
+
]);
|
|
6575
|
+
}
|
|
6576
|
+
}
|
|
6446
6577
|
function renderRunRecord(value) {
|
|
6447
6578
|
printDetail([
|
|
6448
6579
|
["Run", text(value.id) ?? text(value.run_id)],
|
|
@@ -6548,6 +6679,22 @@ function renderModelPrefetch(value) {
|
|
|
6548
6679
|
["Cache", text(value.model_cache) ?? text(value.hf_home)]
|
|
6549
6680
|
]);
|
|
6550
6681
|
}
|
|
6682
|
+
function renderDatasetPrefetch(value) {
|
|
6683
|
+
printSuccess(
|
|
6684
|
+
value.local_files_only === true ? "Verified the cached Hugging Face dataset" : "Dataset is ready locally"
|
|
6685
|
+
);
|
|
6686
|
+
const files = record3(value.files) ?? {};
|
|
6687
|
+
printDetail([
|
|
6688
|
+
["Dataset", text(value.repo)],
|
|
6689
|
+
["Revision", `${text(value.revision) ?? "\u2014"}${value.pinned === false ? " (unpinned: set dataset_prebuilt.huggingface.revision to pin it)" : ""}`],
|
|
6690
|
+
...Object.entries(files).map(([split, file]) => {
|
|
6691
|
+
const entry = record3(file);
|
|
6692
|
+
return [split[0].toUpperCase() + split.slice(1), `${text(entry?.path) ?? "\u2014"} (${displayBytes(entry?.size_bytes) ?? "\u2014"}, sha256 ${String(text(entry?.sha256) ?? "").slice(0, 12)})`];
|
|
6693
|
+
}),
|
|
6694
|
+
["Snapshot", text(value.snapshot_path)],
|
|
6695
|
+
["Cache", text(value.hub_cache)]
|
|
6696
|
+
]);
|
|
6697
|
+
}
|
|
6551
6698
|
function renderActiveModel(value) {
|
|
6552
6699
|
const active = text(value.active) ?? "base";
|
|
6553
6700
|
const pointer = record3(value.pointer);
|
|
@@ -6649,6 +6796,10 @@ function renderKnownJson(args2, value) {
|
|
|
6649
6796
|
renderRunEvents(value);
|
|
6650
6797
|
return true;
|
|
6651
6798
|
}
|
|
6799
|
+
if (subcommand === "audit" && isRecord4(value)) {
|
|
6800
|
+
renderRunAudit(value);
|
|
6801
|
+
return true;
|
|
6802
|
+
}
|
|
6652
6803
|
if (subcommand === "get" && isRecord4(value)) {
|
|
6653
6804
|
renderRunRecord(value);
|
|
6654
6805
|
return true;
|
|
@@ -6685,6 +6836,10 @@ function renderKnownJson(args2, value) {
|
|
|
6685
6836
|
return true;
|
|
6686
6837
|
}
|
|
6687
6838
|
}
|
|
6839
|
+
if (command === "datasets" && isRecord4(value)) {
|
|
6840
|
+
renderDatasetPrefetch(value);
|
|
6841
|
+
return true;
|
|
6842
|
+
}
|
|
6688
6843
|
if (command === "serve" && isRecord4(value)) {
|
|
6689
6844
|
renderServePlan(value);
|
|
6690
6845
|
return true;
|
|
@@ -6862,6 +7017,14 @@ function selectedSpecArgument(args2, cwd) {
|
|
|
6862
7017
|
if (command === "models" && ["prefetch", "verify-base"].includes(args2[1] ?? "")) {
|
|
6863
7018
|
return positionalSpecArgument(args2, 2, join9(cwd, DEFAULT_SPEC_NAME));
|
|
6864
7019
|
}
|
|
7020
|
+
if (command === "datasets") {
|
|
7021
|
+
if (args2[1] === void 0 || args2[1].startsWith("-") || args2[1].endsWith(".json")) {
|
|
7022
|
+
args2.splice(1, 0, "prefetch");
|
|
7023
|
+
}
|
|
7024
|
+
if (["prefetch", "verify"].includes(args2[1] ?? "")) {
|
|
7025
|
+
return positionalSpecArgument(args2, 2, join9(cwd, DEFAULT_SPEC_NAME));
|
|
7026
|
+
}
|
|
7027
|
+
}
|
|
6865
7028
|
const serves = command === "serve" || command === "models" && args2[1] === "serve";
|
|
6866
7029
|
if (!serves) return null;
|
|
6867
7030
|
const explicit = optionValueArgument(args2, "--spec");
|
|
@@ -7002,6 +7165,8 @@ function normalizeProjectedPaths(value, replacements) {
|
|
|
7002
7165
|
async function spawnLocalCli(args2) {
|
|
7003
7166
|
const output = args2.stdout ?? process.stdout;
|
|
7004
7167
|
const errors = args2.stderr ?? process.stderr;
|
|
7168
|
+
const errorTerminal = errors;
|
|
7169
|
+
const childEnv = errorTerminal.isTTY && !args2.jsonMode && args2.env.TT_PROGRESS_TTY === void 0 ? { ...args2.env, TT_PROGRESS_TTY: "1", TT_PROGRESS_COLUMNS: String(errorTerminal.columns ?? 100) } : args2.env;
|
|
7005
7170
|
const pipeInput = Boolean(args2.stdin && args2.stdin !== process.stdin);
|
|
7006
7171
|
const pipeStreamingOutput = args2.streamingStdout && Boolean(args2.stdout && args2.stdout !== process.stdout);
|
|
7007
7172
|
const child = spawn(
|
|
@@ -7009,7 +7174,7 @@ async function spawnLocalCli(args2) {
|
|
|
7009
7174
|
[args2.entrypoint, ...args2.commandArgs],
|
|
7010
7175
|
{
|
|
7011
7176
|
cwd: args2.cwd,
|
|
7012
|
-
env:
|
|
7177
|
+
env: childEnv,
|
|
7013
7178
|
stdio: [
|
|
7014
7179
|
pipeInput ? "pipe" : "inherit",
|
|
7015
7180
|
args2.streamingStdout && !pipeStreamingOutput ? "inherit" : "pipe",
|
|
@@ -7173,7 +7338,8 @@ var LOCAL_COMMANDS = [
|
|
|
7173
7338
|
"validate",
|
|
7174
7339
|
"serve",
|
|
7175
7340
|
"runs",
|
|
7176
|
-
"models"
|
|
7341
|
+
"models",
|
|
7342
|
+
"datasets"
|
|
7177
7343
|
];
|
|
7178
7344
|
var LOCAL_COMMAND_DESCRIPTIONS = {
|
|
7179
7345
|
info: "Show the installed local runtime version and runner status",
|
|
@@ -7183,7 +7349,8 @@ var LOCAL_COMMAND_DESCRIPTIONS = {
|
|
|
7183
7349
|
validate: "Validate a local behavior spec without executing it",
|
|
7184
7350
|
serve: "Serve a verified adapter, the active model, or the protected base",
|
|
7185
7351
|
runs: "Inspect locally stored runs",
|
|
7186
|
-
models: "Inspect, verify, prefetch, or serve local models"
|
|
7352
|
+
models: "Inspect, verify, prefetch, or serve local models",
|
|
7353
|
+
datasets: "Download or verify the Hugging Face dataset a spec trains on"
|
|
7187
7354
|
};
|
|
7188
7355
|
function applyExitCode(result2) {
|
|
7189
7356
|
if (result2?.exitCode !== null && result2?.exitCode !== void 0) {
|
|
@@ -7298,7 +7465,7 @@ function registerAgentCommands(parent, options) {
|
|
|
7298
7465
|
}
|
|
7299
7466
|
|
|
7300
7467
|
// src/commands/pipeline.ts
|
|
7301
|
-
import { existsSync as existsSync4, readFileSync as
|
|
7468
|
+
import { existsSync as existsSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync3 } from "fs";
|
|
7302
7469
|
import { dirname as dirname9, join as join13, resolve as resolve8 } from "path";
|
|
7303
7470
|
|
|
7304
7471
|
// src/local-runtime/project-migration.ts
|
|
@@ -8186,7 +8353,7 @@ function loadPipelineFile(path) {
|
|
|
8186
8353
|
const resolved = resolve8(path);
|
|
8187
8354
|
if (!existsSync4(resolved)) throw new Error(`Pipeline file not found: ${path}. Run \`tt pipeline init\` to create one.`);
|
|
8188
8355
|
try {
|
|
8189
|
-
return JSON.parse(
|
|
8356
|
+
return JSON.parse(readFileSync6(resolved, "utf8"));
|
|
8190
8357
|
} catch (error) {
|
|
8191
8358
|
throw new Error(`Pipeline file must be JSON: ${error.message}`);
|
|
8192
8359
|
}
|
|
@@ -8202,7 +8369,7 @@ function resolvePipelineDocument(options, specRequired) {
|
|
|
8202
8369
|
if (requested !== void 0) return { document: parsePipeline(requested) };
|
|
8203
8370
|
throw new Error(`Behavior spec not found: ${options.spec}. Create tunedtensor.json or pass an explicit --file for a recipe-only preview.`);
|
|
8204
8371
|
}
|
|
8205
|
-
const source =
|
|
8372
|
+
const source = readFileSync6(specPath, "utf8");
|
|
8206
8373
|
const input = parseLocalRunInput(JSON.parse(source), specPath);
|
|
8207
8374
|
const document = pipelineForRunInput(input, requested);
|
|
8208
8375
|
const spec = {
|
|
@@ -8260,7 +8427,7 @@ function registerPipelineCommands(parent) {
|
|
|
8260
8427
|
pipeline2.command("init").description("Write a canonical v1 pipeline recipe").option("-f, --file <path>", "Legacy standalone recipe output (default: embed in tunedtensor.json)").option("--engine <engine>", "adapter (default) or foundation").option("--spec <path>", "Foundation spec whose hyperparameters stamp the DAG").action(async (options) => {
|
|
8261
8428
|
if (!options.file) {
|
|
8262
8429
|
const path2 = resolve8(options.spec ?? DEFAULT_SPEC_FILE);
|
|
8263
|
-
const raw = JSON.parse(
|
|
8430
|
+
const raw = JSON.parse(readFileSync6(path2, "utf8"));
|
|
8264
8431
|
const input = parseLocalRunInput(raw, path2);
|
|
8265
8432
|
if (input.kind === "request") throw new Error("Pipeline init requires a behavior spec.");
|
|
8266
8433
|
if (options.engine && options.engine !== (input.spec.engine ?? "adapter")) throw new Error("--engine must match the spec.");
|
|
@@ -8324,7 +8491,7 @@ function registerPipelineCommands(parent) {
|
|
|
8324
8491
|
const plan = createExecutionPlan(document, { only: parseList(options.only), skip: parseList(options.skip) });
|
|
8325
8492
|
outputPlan({ ...plan, ...spec ? { spec } : {} }, await hostWarningsForPipeline(document, input));
|
|
8326
8493
|
});
|
|
8327
|
-
pipeline2.command("run").description("Run an ordered local pipeline, or safely preview any pipeline").option("--dry-run", "Resolve and display only; never execute, transfer, or reserve credits").option("-f, --file <path>", "Explicit pipeline recipe (default: derive from behavior spec)").option("--spec <path>", "Local behavior spec", DEFAULT_SPEC_FILE).option("--config <path>", "Local runtime config").option("--output <path>", "Foundation or decision run directory (must not already exist)").option("--resume <path>", "Resume a foundation run directory").option("--only <ids>", "Comma-separated step IDs to include").option("--skip <ids>", "Comma-separated step IDs to omit").action(async (options, command) => {
|
|
8494
|
+
pipeline2.command("run").description("Run an ordered local pipeline, or safely preview any pipeline").option("--dry-run", "Resolve and display only; never execute, transfer, or reserve credits").option("-f, --file <path>", "Explicit pipeline recipe (default: derive from behavior spec)").option("--spec <path>", "Local behavior spec", DEFAULT_SPEC_FILE).option("--config <path>", "Local runtime config").option("--output <path>", "Foundation or decision run directory (must not already exist)").option("--resume <path>", "Resume a foundation run directory").option("--only <ids>", "Comma-separated step IDs to include").option("--skip <ids>", "Comma-separated step IDs to omit").option("--verbose", "Also stream training and evaluation process logs").option("--quiet", "Do not print live stage progress").action(async (options, command) => {
|
|
8328
8495
|
if (options.output && options.resume) {
|
|
8329
8496
|
throw new Error("--output and --resume are mutually exclusive.");
|
|
8330
8497
|
}
|
|
@@ -8387,7 +8554,19 @@ function registerPipelineCommands(parent) {
|
|
|
8387
8554
|
...plan.name ? { name: plan.name } : {},
|
|
8388
8555
|
steps: plan.steps.map(({ transfers: _transfers, ...step }) => step)
|
|
8389
8556
|
};
|
|
8390
|
-
const
|
|
8557
|
+
const reporter = options.quiet ? void 0 : createRunConsoleReporter({ verbose: options.verbose });
|
|
8558
|
+
const { request: request2 } = await ensureDatasetCached({ request: input.request, config, reporter });
|
|
8559
|
+
const result2 = await runLocalPipeline({
|
|
8560
|
+
request: request2,
|
|
8561
|
+
config,
|
|
8562
|
+
pipeline: localPipeline,
|
|
8563
|
+
...input.kind === "spec" ? { projectSpec: input.spec } : {},
|
|
8564
|
+
...spec ? { specFile: { path: spec.path, sha256: spec.sha256 } } : {},
|
|
8565
|
+
...reporter ? { reporter } : {}
|
|
8566
|
+
});
|
|
8567
|
+
if (!isJsonMode()) {
|
|
8568
|
+
console.error(`Run ${result2.request.run_id}: \`tt runs audit ${result2.request.run_id}\` verifies its record and shows timing and provenance.`);
|
|
8569
|
+
}
|
|
8391
8570
|
if (isJsonMode()) return printJson({ ...result2, spec });
|
|
8392
8571
|
printSuccess(`Pipeline completed with status ${result2.status}.`);
|
|
8393
8572
|
});
|
|
@@ -8660,7 +8839,7 @@ function registerTopupCommands(parent) {
|
|
|
8660
8839
|
|
|
8661
8840
|
// src/commands/publish.ts
|
|
8662
8841
|
import { createInterface as createInterface4 } from "readline/promises";
|
|
8663
|
-
import { existsSync as existsSync5, readFileSync as
|
|
8842
|
+
import { existsSync as existsSync5, readFileSync as readFileSync7 } from "fs";
|
|
8664
8843
|
import { homedir as homedir3 } from "os";
|
|
8665
8844
|
import { isAbsolute as isAbsolute5, join as join14, resolve as resolve9 } from "path";
|
|
8666
8845
|
import { stdin as defaultStdin, stdout as defaultStdout } from "process";
|
|
@@ -8677,13 +8856,13 @@ function resolvePublishStoreRoot(options) {
|
|
|
8677
8856
|
const localConfigPath = join14(cwd, "local-runner.json");
|
|
8678
8857
|
const projectPath = join14(cwd, "tunedtensor.json");
|
|
8679
8858
|
if (existsSync5(projectPath)) {
|
|
8680
|
-
const spec = localBehaviorSpecFileSchema.parse(JSON.parse(
|
|
8859
|
+
const spec = localBehaviorSpecFileSchema.parse(JSON.parse(readFileSync7(projectPath, "utf8")));
|
|
8681
8860
|
if (existsSync5(localConfigPath) && (spec.runtime || spec.evaluation)) throw new Error("Conflicting configuration sources; migrate local-runner.json first.");
|
|
8682
8861
|
if (!existsSync5(localConfigPath)) return expandPath2(spec.runtime?.storeRoot ?? (env.TT_LOCAL_HOME?.trim() || DEFAULT_PROJECT_STORE_ROOT), cwd, homeDirectory);
|
|
8683
8862
|
}
|
|
8684
8863
|
if (existsSync5(localConfigPath)) {
|
|
8685
8864
|
try {
|
|
8686
|
-
const raw = JSON.parse(
|
|
8865
|
+
const raw = JSON.parse(readFileSync7(localConfigPath, "utf-8"));
|
|
8687
8866
|
if (typeof raw.storeRoot === "string" && raw.storeRoot.trim()) {
|
|
8688
8867
|
return expandPath2(raw.storeRoot, cwd, homeDirectory);
|
|
8689
8868
|
}
|
|
@@ -8747,7 +8926,7 @@ function assertPublishPayloadSize(payload) {
|
|
|
8747
8926
|
}
|
|
8748
8927
|
}
|
|
8749
8928
|
function registerPublishCommand(parent) {
|
|
8750
|
-
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) => {
|
|
8929
|
+
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").option("--allow-unverified", "Publish evidence that cannot be fully verified (older TT versions, unreadable events)").action(async (runId, cmdOpts) => {
|
|
8751
8930
|
const inherited = parent.optsWithGlobals();
|
|
8752
8931
|
const opts = {
|
|
8753
8932
|
apiKey: cmdOpts.apiKey ?? inherited.apiKey,
|
|
@@ -8766,12 +8945,27 @@ function registerPublishCommand(parent) {
|
|
|
8766
8945
|
const report = runReportSchema.parse(rawReport);
|
|
8767
8946
|
const specRecord = await store.getSpec(run.behavior_spec_id);
|
|
8768
8947
|
const exampleCount = report.candidate.results.length || report.baseline.results.length;
|
|
8948
|
+
const audit = await auditRun(store, run.id);
|
|
8949
|
+
if (audit.verdict === "tampered") {
|
|
8950
|
+
throw new Error(
|
|
8951
|
+
`Run ${run.id} evidence does not verify: ${audit.findings.join(" ")} Inspect it with \`tt runs audit ${run.id}\`; tampered runs are not published.`
|
|
8952
|
+
);
|
|
8953
|
+
}
|
|
8769
8954
|
const payload = {
|
|
8770
8955
|
spec: {
|
|
8771
8956
|
id: specRecord.id,
|
|
8772
8957
|
...specRecord.spec
|
|
8773
8958
|
},
|
|
8774
|
-
report
|
|
8959
|
+
report: {
|
|
8960
|
+
...report,
|
|
8961
|
+
audit: {
|
|
8962
|
+
verdict: audit.verdict,
|
|
8963
|
+
findings: audit.findings,
|
|
8964
|
+
event_chain: { status: audit.chain.status, events: audit.chain.events, head_hash: audit.chain.head_hash },
|
|
8965
|
+
report_sha256: audit.report.recorded_sha256,
|
|
8966
|
+
timeline: audit.timeline
|
|
8967
|
+
}
|
|
8968
|
+
}
|
|
8775
8969
|
};
|
|
8776
8970
|
assertPublishPayloadSize(payload);
|
|
8777
8971
|
if (isJsonMode() && cmdOpts.dryRun) {
|
|
@@ -8799,6 +8993,14 @@ function registerPublishCommand(parent) {
|
|
|
8799
8993
|
printWarning(
|
|
8800
8994
|
"Prompts and model outputs from the run report will be uploaded to your Tuned Tensor account."
|
|
8801
8995
|
);
|
|
8996
|
+
if (audit.verdict !== "verified") {
|
|
8997
|
+
printWarning(`Run evidence is unverified: ${audit.findings.join(" ")}`);
|
|
8998
|
+
}
|
|
8999
|
+
}
|
|
9000
|
+
if (audit.verdict !== "verified" && !cmdOpts.allowUnverified && !cmdOpts.dryRun) {
|
|
9001
|
+
throw new Error(
|
|
9002
|
+
`Run ${run.id} evidence cannot be fully verified: ${audit.findings.join(" ")} Review it with \`tt runs audit\`, then pass --allow-unverified to publish it anyway; the dashboard will show it as unverified.`
|
|
9003
|
+
);
|
|
8802
9004
|
}
|
|
8803
9005
|
if (cmdOpts.dryRun) {
|
|
8804
9006
|
if (isJsonMode()) {
|
|
@@ -8843,7 +9045,7 @@ function registerPublishCommand(parent) {
|
|
|
8843
9045
|
}
|
|
8844
9046
|
|
|
8845
9047
|
// src/commands/specs.ts
|
|
8846
|
-
import { readFileSync as
|
|
9048
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
8847
9049
|
|
|
8848
9050
|
// src/resolve.ts
|
|
8849
9051
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -8947,7 +9149,7 @@ var SpecBodyError = class extends Error {
|
|
|
8947
9149
|
function loadSpecBody(filePath, mode) {
|
|
8948
9150
|
let parsed;
|
|
8949
9151
|
try {
|
|
8950
|
-
parsed = JSON.parse(
|
|
9152
|
+
parsed = JSON.parse(readFileSync8(filePath, "utf-8"));
|
|
8951
9153
|
} catch (e) {
|
|
8952
9154
|
throw new SpecBodyError(
|
|
8953
9155
|
`Could not parse ${filePath}: ${e.message}`
|
|
@@ -9076,7 +9278,7 @@ function registerSpecsCommands(parent) {
|
|
|
9076
9278
|
}
|
|
9077
9279
|
|
|
9078
9280
|
// src/commands/datasets.ts
|
|
9079
|
-
import { existsSync as existsSync6, readFileSync as
|
|
9281
|
+
import { existsSync as existsSync6, readFileSync as readFileSync9, statSync as statSync2 } from "fs";
|
|
9080
9282
|
var DOCUMENT_OCR_MIME_TYPES = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/webp"]);
|
|
9081
9283
|
function formatBytes(bytes) {
|
|
9082
9284
|
if (bytes < 1024) return `${bytes} B`;
|
|
@@ -9206,7 +9408,7 @@ function parseDatasetFormat(value) {
|
|
|
9206
9408
|
throw new Error("--format must be one of: jsonl, document_ocr_jsonl");
|
|
9207
9409
|
}
|
|
9208
9410
|
function validateDatasetFile(file, requestedFormat) {
|
|
9209
|
-
const lines =
|
|
9411
|
+
const lines = readFileSync9(file, "utf8").split(/\r?\n/);
|
|
9210
9412
|
const errors = [];
|
|
9211
9413
|
let rowCount = 0;
|
|
9212
9414
|
let detectedFormat = null;
|
|
@@ -9338,7 +9540,7 @@ function registerDatasetsCommands(parent) {
|
|
|
9338
9540
|
}
|
|
9339
9541
|
const format = validateDatasetFile(file, parseDatasetFormat(cmdOpts.format));
|
|
9340
9542
|
const name = cmdOpts.name || file.split("/").pop().replace(/\.jsonl?$/, "");
|
|
9341
|
-
const fileBytes =
|
|
9543
|
+
const fileBytes = readFileSync9(file);
|
|
9342
9544
|
const uploadUrl = await post(
|
|
9343
9545
|
"/datasets/upload-url",
|
|
9344
9546
|
{
|
|
@@ -9383,7 +9585,7 @@ function registerDatasetsCommands(parent) {
|
|
|
9383
9585
|
}
|
|
9384
9586
|
|
|
9385
9587
|
// src/commands/label.ts
|
|
9386
|
-
import { existsSync as existsSync7, readFileSync as
|
|
9588
|
+
import { existsSync as existsSync7, readFileSync as readFileSync10, statSync as statSync3 } from "fs";
|
|
9387
9589
|
function formatCents2(cents) {
|
|
9388
9590
|
return `$${(cents / 100).toFixed(2)}`;
|
|
9389
9591
|
}
|
|
@@ -9427,7 +9629,7 @@ function validateUnlabeledFile(file, inputColumn) {
|
|
|
9427
9629
|
"CSV uploads need --input-column <name> to say which column holds the input text."
|
|
9428
9630
|
);
|
|
9429
9631
|
}
|
|
9430
|
-
const firstLine =
|
|
9632
|
+
const firstLine = readFileSync10(file, "utf8").split(/\r?\n/, 1)[0] ?? "";
|
|
9431
9633
|
const columns = parseCsvHeader(firstLine);
|
|
9432
9634
|
if (!columns.includes(inputColumn)) {
|
|
9433
9635
|
throw new Error(
|
|
@@ -9439,7 +9641,7 @@ function validateUnlabeledFile(file, inputColumn) {
|
|
|
9439
9641
|
if (!lower.endsWith(".jsonl") && !lower.endsWith(".json")) {
|
|
9440
9642
|
throw new Error("Labeling source file must be .jsonl or .csv");
|
|
9441
9643
|
}
|
|
9442
|
-
const lines =
|
|
9644
|
+
const lines = readFileSync10(file, "utf8").split(/\r?\n/);
|
|
9443
9645
|
const errors = [];
|
|
9444
9646
|
let rowCount = 0;
|
|
9445
9647
|
for (const [index, rawLine] of lines.entries()) {
|
|
@@ -9562,7 +9764,7 @@ function registerLabelCommands(parent) {
|
|
|
9562
9764
|
const { format } = validateUnlabeledFile(file, cmdOpts.inputColumn);
|
|
9563
9765
|
const specId = await resolveSpecId(cmdOpts.spec, opts);
|
|
9564
9766
|
const name = cmdOpts.name || file.split("/").pop().replace(/\.(jsonl|json|csv)$/, "");
|
|
9565
|
-
const fileBytes =
|
|
9767
|
+
const fileBytes = readFileSync10(file);
|
|
9566
9768
|
const contentType = format === "csv" ? "text/csv" : "application/jsonl";
|
|
9567
9769
|
const { data: uploadUrl } = await post(
|
|
9568
9770
|
"/labeling-jobs/upload-url",
|
|
@@ -9735,7 +9937,7 @@ function registerLabelCommands(parent) {
|
|
|
9735
9937
|
printError("Provide --output <text> or --file <path>.");
|
|
9736
9938
|
process.exit(1);
|
|
9737
9939
|
}
|
|
9738
|
-
const output = cmdOpts.output ??
|
|
9940
|
+
const output = cmdOpts.output ?? readFileSync10(cmdOpts.file, "utf8");
|
|
9739
9941
|
const jobId = await resolveLabelingJobId(id, opts);
|
|
9740
9942
|
const indexes = parseIndexList(cmdOpts.row);
|
|
9741
9943
|
const rowIds = await resolveRowIds(jobId, indexes, opts);
|
|
@@ -10225,7 +10427,7 @@ import {
|
|
|
10225
10427
|
statSync as statSync4,
|
|
10226
10428
|
createWriteStream,
|
|
10227
10429
|
unlinkSync,
|
|
10228
|
-
readFileSync as
|
|
10430
|
+
readFileSync as readFileSync12,
|
|
10229
10431
|
writeFileSync as writeFileSync5,
|
|
10230
10432
|
readdirSync,
|
|
10231
10433
|
rmSync
|
|
@@ -10236,7 +10438,7 @@ import { Readable, Transform } from "stream";
|
|
|
10236
10438
|
import { pipeline } from "stream/promises";
|
|
10237
10439
|
|
|
10238
10440
|
// src/commands/init.ts
|
|
10239
|
-
import { existsSync as existsSync8, readFileSync as
|
|
10441
|
+
import { existsSync as existsSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync4 } from "fs";
|
|
10240
10442
|
import { resolve as resolve10 } from "path";
|
|
10241
10443
|
var DEFAULT_SPEC_FILE2 = "tunedtensor.json";
|
|
10242
10444
|
function loadSpec(filePath) {
|
|
@@ -10248,7 +10450,7 @@ Run \`tt init\` to create one.`
|
|
|
10248
10450
|
);
|
|
10249
10451
|
process.exit(1);
|
|
10250
10452
|
}
|
|
10251
|
-
const raw = JSON.parse(
|
|
10453
|
+
const raw = JSON.parse(readFileSync11(resolved, "utf-8"));
|
|
10252
10454
|
return raw;
|
|
10253
10455
|
}
|
|
10254
10456
|
|
|
@@ -11462,7 +11664,7 @@ function findSpecPath(explicitPath, modelPath) {
|
|
|
11462
11664
|
return null;
|
|
11463
11665
|
}
|
|
11464
11666
|
function loadSystemPromptFromSpec(specPath) {
|
|
11465
|
-
const spec = JSON.parse(
|
|
11667
|
+
const spec = JSON.parse(readFileSync12(specPath, "utf8"));
|
|
11466
11668
|
return buildSystemPrompt(spec);
|
|
11467
11669
|
}
|
|
11468
11670
|
function loadJsonSchemaForServe(schemaPath) {
|
|
@@ -11471,7 +11673,7 @@ function loadJsonSchemaForServe(schemaPath) {
|
|
|
11471
11673
|
throw new Error(`JSON schema file not found: ${schemaPath}`);
|
|
11472
11674
|
}
|
|
11473
11675
|
try {
|
|
11474
|
-
const schema = JSON.parse(
|
|
11676
|
+
const schema = JSON.parse(readFileSync12(resolved, "utf8"));
|
|
11475
11677
|
return JSON.stringify(schema);
|
|
11476
11678
|
} catch (err) {
|
|
11477
11679
|
throw new Error(`JSON schema file is not valid JSON: ${schemaPath}`);
|
|
@@ -12099,10 +12301,10 @@ function registerModelsCommands(parent) {
|
|
|
12099
12301
|
}
|
|
12100
12302
|
|
|
12101
12303
|
// src/commands/push.ts
|
|
12102
|
-
import { readFileSync as
|
|
12304
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync6 } from "fs";
|
|
12103
12305
|
import { resolve as resolve12 } from "path";
|
|
12104
12306
|
function persistRemoteId(filePath, id) {
|
|
12105
|
-
const raw = JSON.parse(
|
|
12307
|
+
const raw = JSON.parse(readFileSync13(filePath, "utf-8"));
|
|
12106
12308
|
raw.id = id;
|
|
12107
12309
|
writeFileSync6(filePath, JSON.stringify(raw, null, 2) + "\n");
|
|
12108
12310
|
}
|
|
@@ -12185,8 +12387,20 @@ function registerUsageCommand(parent) {
|
|
|
12185
12387
|
});
|
|
12186
12388
|
}
|
|
12187
12389
|
|
|
12390
|
+
// src/commands/upgrade.ts
|
|
12391
|
+
import { spawn as spawn5 } from "child_process";
|
|
12392
|
+
import { accessSync, constants as constants3, existsSync as existsSync10, readFileSync as readFileSync15, realpathSync } from "fs";
|
|
12393
|
+
import { dirname as dirname13, join as join17 } from "path";
|
|
12394
|
+
import chalk14 from "chalk";
|
|
12395
|
+
|
|
12188
12396
|
// src/update-check.ts
|
|
12397
|
+
import { spawn as spawn4 } from "child_process";
|
|
12398
|
+
import { mkdirSync as mkdirSync5, readFileSync as readFileSync14, writeFileSync as writeFileSync7 } from "fs";
|
|
12399
|
+
import { dirname as dirname12, join as join16 } from "path";
|
|
12400
|
+
import chalk13 from "chalk";
|
|
12401
|
+
var CLI_PACKAGE_NAME = "@tuned-tensor/cli";
|
|
12189
12402
|
var PACKAGE_LATEST_URL = "https://registry.npmjs.org/@tuned-tensor%2fcli/latest";
|
|
12403
|
+
var DEFAULT_CACHE_MAX_AGE_MS = 12 * 60 * 60 * 1e3;
|
|
12190
12404
|
function parseVersion(version) {
|
|
12191
12405
|
const match = version.trim().match(
|
|
12192
12406
|
/^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/
|
|
@@ -12230,11 +12444,50 @@ function compareVersions(left, right) {
|
|
|
12230
12444
|
}
|
|
12231
12445
|
return comparePrerelease(left.prerelease, right.prerelease);
|
|
12232
12446
|
}
|
|
12233
|
-
|
|
12447
|
+
function getCliUpdateCacheFile(env = process.env) {
|
|
12448
|
+
return join16(getTunedTensorHome(env), "update-check.json");
|
|
12449
|
+
}
|
|
12450
|
+
function cliUpdateChecksDisabled(env = process.env) {
|
|
12451
|
+
return [env.TT_NO_UPDATE_CHECK, env.NO_UPDATE_NOTIFIER, env.CI].some((value) => value !== void 0 && value !== "" && value !== "0" && value !== "false");
|
|
12452
|
+
}
|
|
12453
|
+
function readUpdateCache(file) {
|
|
12454
|
+
try {
|
|
12455
|
+
const payload = JSON.parse(readFileSync14(file, "utf8"));
|
|
12456
|
+
if (typeof payload.checkedAt !== "number" || typeof payload.latestVersion !== "string" || !parseVersion(payload.latestVersion)) return null;
|
|
12457
|
+
return { checkedAt: payload.checkedAt, latestVersion: payload.latestVersion };
|
|
12458
|
+
} catch {
|
|
12459
|
+
return null;
|
|
12460
|
+
}
|
|
12461
|
+
}
|
|
12462
|
+
function writeUpdateCache(file, cache) {
|
|
12463
|
+
try {
|
|
12464
|
+
mkdirSync5(dirname12(file), { recursive: true });
|
|
12465
|
+
writeFileSync7(file, `${JSON.stringify(cache)}
|
|
12466
|
+
`);
|
|
12467
|
+
} catch {
|
|
12468
|
+
}
|
|
12469
|
+
}
|
|
12470
|
+
function recordLatestCliVersion(cacheFile, latestVersion, now = Date.now()) {
|
|
12471
|
+
writeUpdateCache(cacheFile, { checkedAt: now, latestVersion });
|
|
12472
|
+
}
|
|
12473
|
+
function compareCliVersions(left, right) {
|
|
12474
|
+
const parsedLeft = parseVersion(left);
|
|
12475
|
+
const parsedRight = parseVersion(right);
|
|
12476
|
+
if (!parsedLeft || !parsedRight) return null;
|
|
12477
|
+
return compareVersions(parsedLeft, parsedRight);
|
|
12478
|
+
}
|
|
12479
|
+
function newerStableRelease(currentVersion, latestVersion) {
|
|
12480
|
+
if (!latestVersion) return null;
|
|
12234
12481
|
const current = parseVersion(currentVersion);
|
|
12235
|
-
|
|
12482
|
+
const latest = parseVersion(latestVersion);
|
|
12483
|
+
if (!current || !latest || latest.prerelease.length > 0 || compareVersions(latest, current) <= 0) return null;
|
|
12484
|
+
return { currentVersion, latestVersion };
|
|
12485
|
+
}
|
|
12486
|
+
async function fetchLatestCliVersion(options = {}) {
|
|
12236
12487
|
const controller = new AbortController();
|
|
12237
|
-
const
|
|
12488
|
+
const abort = () => controller.abort();
|
|
12489
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
12490
|
+
const timeoutMs = options.timeoutMs ?? 1500;
|
|
12238
12491
|
let timeout;
|
|
12239
12492
|
const request2 = (async () => {
|
|
12240
12493
|
try {
|
|
@@ -12246,11 +12499,7 @@ async function checkForCliUpdate(currentVersion, options = {}) {
|
|
|
12246
12499
|
const payload = await response.json();
|
|
12247
12500
|
if (typeof payload.version !== "string") return null;
|
|
12248
12501
|
const latest = parseVersion(payload.version);
|
|
12249
|
-
|
|
12250
|
-
return {
|
|
12251
|
-
currentVersion,
|
|
12252
|
-
latestVersion: payload.version
|
|
12253
|
-
};
|
|
12502
|
+
return latest && latest.prerelease.length === 0 ? payload.version : null;
|
|
12254
12503
|
} catch {
|
|
12255
12504
|
return null;
|
|
12256
12505
|
}
|
|
@@ -12265,15 +12514,211 @@ async function checkForCliUpdate(currentVersion, options = {}) {
|
|
|
12265
12514
|
return await Promise.race([request2, deadline]);
|
|
12266
12515
|
} finally {
|
|
12267
12516
|
if (timeout) clearTimeout(timeout);
|
|
12517
|
+
options.signal?.removeEventListener("abort", abort);
|
|
12518
|
+
}
|
|
12519
|
+
}
|
|
12520
|
+
function cachedCliUpdate(currentVersion, cacheFile) {
|
|
12521
|
+
return newerStableRelease(currentVersion, readUpdateCache(cacheFile)?.latestVersion);
|
|
12522
|
+
}
|
|
12523
|
+
function cliUpdateCacheIsStale(cacheFile, options = {}) {
|
|
12524
|
+
const cache = readUpdateCache(cacheFile);
|
|
12525
|
+
const now = (options.now ?? Date.now)();
|
|
12526
|
+
return !cache || now - cache.checkedAt >= (options.cacheMaxAgeMs ?? DEFAULT_CACHE_MAX_AGE_MS);
|
|
12527
|
+
}
|
|
12528
|
+
async function refreshCliUpdateCache(cacheFile, options = {}) {
|
|
12529
|
+
const latest = await fetchLatestCliVersion(options);
|
|
12530
|
+
if (latest) recordLatestCliVersion(cacheFile, latest, (options.now ?? Date.now)());
|
|
12531
|
+
return latest;
|
|
12532
|
+
}
|
|
12533
|
+
var REFRESH_SCRIPT = `
|
|
12534
|
+
const [url, file] = process.argv.slice(1);
|
|
12535
|
+
const fs = require("node:fs");
|
|
12536
|
+
const path = require("node:path");
|
|
12537
|
+
fetch(url, { headers: { accept: "application/json" }, signal: AbortSignal.timeout(10000) })
|
|
12538
|
+
.then((response) => response.ok ? response.json() : null)
|
|
12539
|
+
.then((payload) => {
|
|
12540
|
+
if (!payload || typeof payload.version !== "string") return;
|
|
12541
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
12542
|
+
fs.writeFileSync(file, JSON.stringify({ checkedAt: Date.now(), latestVersion: payload.version }) + "\\n");
|
|
12543
|
+
})
|
|
12544
|
+
.catch(() => {});
|
|
12545
|
+
`;
|
|
12546
|
+
function spawnCliUpdateRefresh(cacheFile) {
|
|
12547
|
+
const cached = readUpdateCache(cacheFile);
|
|
12548
|
+
if (cached) recordLatestCliVersion(cacheFile, cached.latestVersion);
|
|
12549
|
+
try {
|
|
12550
|
+
const child = spawn4(
|
|
12551
|
+
process.execPath,
|
|
12552
|
+
["-e", REFRESH_SCRIPT, PACKAGE_LATEST_URL, cacheFile],
|
|
12553
|
+
{ detached: true, stdio: "ignore", windowsHide: true }
|
|
12554
|
+
);
|
|
12555
|
+
child.on("error", () => {
|
|
12556
|
+
});
|
|
12557
|
+
child.unref();
|
|
12558
|
+
} catch {
|
|
12268
12559
|
}
|
|
12269
12560
|
}
|
|
12561
|
+
async function checkForCliUpdate(currentVersion, options = {}) {
|
|
12562
|
+
if (!parseVersion(currentVersion)) return null;
|
|
12563
|
+
const { cacheFile } = options;
|
|
12564
|
+
if (cacheFile && !cliUpdateCacheIsStale(cacheFile, options)) {
|
|
12565
|
+
return cachedCliUpdate(currentVersion, cacheFile);
|
|
12566
|
+
}
|
|
12567
|
+
const latest = cacheFile ? await refreshCliUpdateCache(cacheFile, options) : await fetchLatestCliVersion(options);
|
|
12568
|
+
return newerStableRelease(
|
|
12569
|
+
currentVersion,
|
|
12570
|
+
latest ?? (cacheFile ? readUpdateCache(cacheFile)?.latestVersion : void 0)
|
|
12571
|
+
);
|
|
12572
|
+
}
|
|
12270
12573
|
function formatCliUpdateNotice(update) {
|
|
12271
12574
|
return [
|
|
12272
|
-
`Update available: tt ${update.currentVersion} \u2192 ${update.latestVersion}
|
|
12273
|
-
"
|
|
12575
|
+
chalk13.yellow(`Update available: tt ${update.currentVersion} \u2192 ${chalk13.bold(update.latestVersion)}`),
|
|
12576
|
+
`Run ${chalk13.bold("tt upgrade")} to install it.`
|
|
12274
12577
|
].join("\n");
|
|
12275
12578
|
}
|
|
12276
12579
|
|
|
12580
|
+
// src/commands/upgrade.ts
|
|
12581
|
+
function resolveGlobalInstall(entrypoint, platform = process.platform) {
|
|
12582
|
+
if (!entrypoint) return null;
|
|
12583
|
+
let script;
|
|
12584
|
+
try {
|
|
12585
|
+
script = realpathSync(entrypoint);
|
|
12586
|
+
} catch {
|
|
12587
|
+
return null;
|
|
12588
|
+
}
|
|
12589
|
+
if (/[\\/]_npx[\\/]/.test(script)) return null;
|
|
12590
|
+
const match = platform === "win32" ? script.match(/^(.*)\\node_modules\\@tuned-tensor\\cli\\dist\\index\.js$/i) : script.match(/^(.*)\/lib\/node_modules\/@tuned-tensor\/cli\/dist\/index\.js$/);
|
|
12591
|
+
if (!match?.[1]) return null;
|
|
12592
|
+
return { prefix: match[1], packageDir: dirname13(dirname13(script)) };
|
|
12593
|
+
}
|
|
12594
|
+
function prefixIsWritable(prefix, platform) {
|
|
12595
|
+
const modules = platform === "win32" ? join17(prefix, "node_modules") : join17(prefix, "lib", "node_modules");
|
|
12596
|
+
try {
|
|
12597
|
+
accessSync(existsSync10(modules) ? modules : prefix, constants3.W_OK);
|
|
12598
|
+
return true;
|
|
12599
|
+
} catch {
|
|
12600
|
+
return false;
|
|
12601
|
+
}
|
|
12602
|
+
}
|
|
12603
|
+
function installedVersion(packageDir) {
|
|
12604
|
+
try {
|
|
12605
|
+
const manifest = JSON.parse(readFileSync15(join17(packageDir, "package.json"), "utf8"));
|
|
12606
|
+
return typeof manifest.version === "string" ? manifest.version : void 0;
|
|
12607
|
+
} catch {
|
|
12608
|
+
return void 0;
|
|
12609
|
+
}
|
|
12610
|
+
}
|
|
12611
|
+
function quoteForCmd(arg) {
|
|
12612
|
+
return /[\s"&|<>^]/.test(arg) ? `"${arg.replace(/"/g, '""')}"` : arg;
|
|
12613
|
+
}
|
|
12614
|
+
function defaultNpmRunner(platform) {
|
|
12615
|
+
return async (args2) => await new Promise((resolve13, reject) => {
|
|
12616
|
+
const windows = platform === "win32";
|
|
12617
|
+
const child = spawn5(
|
|
12618
|
+
windows ? "npm.cmd" : "npm",
|
|
12619
|
+
windows ? args2.map(quoteForCmd) : args2,
|
|
12620
|
+
{
|
|
12621
|
+
shell: windows,
|
|
12622
|
+
// Keep stdout clean for --json; npm progress goes to stderr.
|
|
12623
|
+
stdio: ["ignore", isJsonMode() ? 2 : "inherit", "inherit"]
|
|
12624
|
+
}
|
|
12625
|
+
);
|
|
12626
|
+
child.once("error", reject);
|
|
12627
|
+
child.once("close", (code2) => resolve13(code2 ?? 1));
|
|
12628
|
+
});
|
|
12629
|
+
}
|
|
12630
|
+
function formatCommand(args2) {
|
|
12631
|
+
return ["npm", ...args2].map((arg) => /\s/.test(arg) ? JSON.stringify(arg) : arg).join(" ");
|
|
12632
|
+
}
|
|
12633
|
+
function registerUpgradeCommand(program, deps) {
|
|
12634
|
+
program.command("upgrade").alias("update").description("Upgrade tt to the latest release").argument("[version]", "Version or npm dist-tag to install (default: latest)").option("--check", "Only report whether an update is available").addHelpText(
|
|
12635
|
+
"after",
|
|
12636
|
+
`
|
|
12637
|
+
Examples:
|
|
12638
|
+
tt upgrade Install the latest stable release
|
|
12639
|
+
tt upgrade --check Report whether a newer release exists
|
|
12640
|
+
tt upgrade beta Opt in to the beta channel
|
|
12641
|
+
tt upgrade 0.21.0 Install a specific version
|
|
12642
|
+
|
|
12643
|
+
Set TT_NO_UPDATE_CHECK=1 to silence update notices.
|
|
12644
|
+
`
|
|
12645
|
+
).action(async (requested, options) => {
|
|
12646
|
+
const platform = deps.platform ?? process.platform;
|
|
12647
|
+
const cacheFile = getCliUpdateCacheFile(deps.env);
|
|
12648
|
+
const current = deps.version;
|
|
12649
|
+
const target = requested?.trim() || "latest";
|
|
12650
|
+
let latest;
|
|
12651
|
+
if (target === "latest") {
|
|
12652
|
+
latest = await fetchLatestCliVersion({ fetchImpl: deps.fetchImpl, timeoutMs: 1e4 }) ?? void 0;
|
|
12653
|
+
if (!latest) {
|
|
12654
|
+
throw new Error(
|
|
12655
|
+
"Could not reach the npm registry to look up the latest tt release. Check your connection and try again."
|
|
12656
|
+
);
|
|
12657
|
+
}
|
|
12658
|
+
recordLatestCliVersion(cacheFile, latest);
|
|
12659
|
+
const comparison = compareCliVersions(latest, current);
|
|
12660
|
+
if (comparison !== null && comparison <= 0) {
|
|
12661
|
+
if (isJsonMode()) {
|
|
12662
|
+
printJson({ current_version: current, latest_version: latest, update_available: false });
|
|
12663
|
+
} else {
|
|
12664
|
+
printSuccess(`tt ${current} is the latest version.`);
|
|
12665
|
+
}
|
|
12666
|
+
return;
|
|
12667
|
+
}
|
|
12668
|
+
}
|
|
12669
|
+
if (options.check) {
|
|
12670
|
+
if (isJsonMode()) {
|
|
12671
|
+
printJson({ current_version: current, latest_version: latest ?? null, update_available: Boolean(latest) });
|
|
12672
|
+
} else if (latest) {
|
|
12673
|
+
console.log(`Update available: tt ${current} \u2192 ${chalk14.bold(latest)}`);
|
|
12674
|
+
console.log(`Run ${chalk14.bold("tt upgrade")} to install it.`);
|
|
12675
|
+
} else {
|
|
12676
|
+
console.log(`tt ${current} is installed. Run ${chalk14.bold(`tt upgrade ${target}`)} to install ${target}.`);
|
|
12677
|
+
}
|
|
12678
|
+
return;
|
|
12679
|
+
}
|
|
12680
|
+
const install = resolveGlobalInstall(deps.entrypoint, platform);
|
|
12681
|
+
const packageSpec = `${CLI_PACKAGE_NAME}@${target}`;
|
|
12682
|
+
if (!install) {
|
|
12683
|
+
throw new Error(
|
|
12684
|
+
`This tt (${deps.entrypoint ?? "unknown path"}) was not installed with npm -g, so it can't upgrade itself.
|
|
12685
|
+
Upgrade it the way you installed it, for example:
|
|
12686
|
+
npm install -g --ignore-scripts ${packageSpec}`
|
|
12687
|
+
);
|
|
12688
|
+
}
|
|
12689
|
+
const npmArgs = ["install", "-g", "--ignore-scripts", "--prefix", install.prefix, packageSpec];
|
|
12690
|
+
if (!prefixIsWritable(install.prefix, platform)) {
|
|
12691
|
+
throw new Error(
|
|
12692
|
+
`tt is installed in ${install.prefix}, which this user can't write to. Run:
|
|
12693
|
+
sudo ${formatCommand(npmArgs)}`
|
|
12694
|
+
);
|
|
12695
|
+
}
|
|
12696
|
+
if (!isJsonMode()) {
|
|
12697
|
+
console.log(`Upgrading tt ${current} \u2192 ${chalk14.bold(latest ?? target)}`);
|
|
12698
|
+
console.log(chalk14.dim(`$ ${formatCommand(npmArgs)}`));
|
|
12699
|
+
}
|
|
12700
|
+
let code2;
|
|
12701
|
+
try {
|
|
12702
|
+
code2 = await (deps.runNpm ?? defaultNpmRunner(platform))(npmArgs);
|
|
12703
|
+
} catch (error) {
|
|
12704
|
+
throw new Error(
|
|
12705
|
+
`Could not run npm (${error instanceof Error ? error.message : String(error)}). Run it yourself:
|
|
12706
|
+
${formatCommand(npmArgs)}`
|
|
12707
|
+
);
|
|
12708
|
+
}
|
|
12709
|
+
if (code2 !== 0) {
|
|
12710
|
+
throw new Error(`npm exited with code ${code2}. Run it yourself to see details:
|
|
12711
|
+
${formatCommand(npmArgs)}`);
|
|
12712
|
+
}
|
|
12713
|
+
const installed = installedVersion(install.packageDir) ?? latest ?? target;
|
|
12714
|
+
if (isJsonMode()) {
|
|
12715
|
+
printJson({ previous_version: current, version: installed, prefix: install.prefix });
|
|
12716
|
+
} else {
|
|
12717
|
+
printSuccess(`Upgraded tt ${current} \u2192 ${installed}. Restart any open tt sessions to use it.`);
|
|
12718
|
+
}
|
|
12719
|
+
});
|
|
12720
|
+
}
|
|
12721
|
+
|
|
12277
12722
|
// src/cli.ts
|
|
12278
12723
|
function createAccountToolApi(opts) {
|
|
12279
12724
|
return {
|
|
@@ -12384,7 +12829,7 @@ async function runSelfCommand(args2, options = {}) {
|
|
|
12384
12829
|
throw new Error("Cannot locate the tt CLI entrypoint.");
|
|
12385
12830
|
}
|
|
12386
12831
|
return await new Promise((resolve13, reject) => {
|
|
12387
|
-
const child =
|
|
12832
|
+
const child = spawn6(process.execPath, [entrypoint, ...args2], {
|
|
12388
12833
|
cwd: options.cwd,
|
|
12389
12834
|
env: options.env ?? process.env,
|
|
12390
12835
|
stdio: "inherit",
|
|
@@ -12486,7 +12931,7 @@ function createProgram(version, runtime = {}) {
|
|
|
12486
12931
|
if (root.json) setJsonMode(true);
|
|
12487
12932
|
if (root.color === false) {
|
|
12488
12933
|
process.env.FORCE_COLOR = "0";
|
|
12489
|
-
|
|
12934
|
+
chalk15.level = 0;
|
|
12490
12935
|
}
|
|
12491
12936
|
});
|
|
12492
12937
|
registerLocalCommands(program, {
|
|
@@ -12505,6 +12950,11 @@ function createProgram(version, runtime = {}) {
|
|
|
12505
12950
|
registerUsageCommand(program);
|
|
12506
12951
|
registerPublishCommand(program);
|
|
12507
12952
|
registerCloudCommands(program);
|
|
12953
|
+
registerUpgradeCommand(program, {
|
|
12954
|
+
version,
|
|
12955
|
+
entrypoint: runtime.argv?.[1] ?? process.argv[1],
|
|
12956
|
+
env
|
|
12957
|
+
});
|
|
12508
12958
|
registerAgentCommands(program, {
|
|
12509
12959
|
get env() {
|
|
12510
12960
|
return childEnvironment2(program.opts(), env);
|
|
@@ -12524,12 +12974,12 @@ function createProgram(version, runtime = {}) {
|
|
|
12524
12974
|
`);
|
|
12525
12975
|
return;
|
|
12526
12976
|
}
|
|
12527
|
-
output.write(`${
|
|
12977
|
+
output.write(`${chalk15.bold.hex("#8B5CF6")("Tuned Tensor status")}
|
|
12528
12978
|
`);
|
|
12529
12979
|
output.write(`${formatShellStatus(context).join("\n")}
|
|
12530
12980
|
|
|
12531
12981
|
`);
|
|
12532
|
-
output.write(`${
|
|
12982
|
+
output.write(`${chalk15.bold("Context")}
|
|
12533
12983
|
`);
|
|
12534
12984
|
output.write(`${formatShellContext(context).join("\n")}
|
|
12535
12985
|
`);
|
|
@@ -12585,7 +13035,11 @@ async function runCli(version, runtime = {}) {
|
|
|
12585
13035
|
const error = runtime.stderr ?? process.stderr;
|
|
12586
13036
|
let update = null;
|
|
12587
13037
|
try {
|
|
12588
|
-
|
|
13038
|
+
if (runtime.checkForUpdate) {
|
|
13039
|
+
update = await runtime.checkForUpdate(version);
|
|
13040
|
+
} else if (!cliUpdateChecksDisabled(env)) {
|
|
13041
|
+
update = await checkForCliUpdate(version, { cacheFile: getCliUpdateCacheFile(env) });
|
|
13042
|
+
}
|
|
12589
13043
|
} catch {
|
|
12590
13044
|
}
|
|
12591
13045
|
if (update) {
|
|
@@ -12626,11 +13080,29 @@ async function runCli(version, runtime = {}) {
|
|
|
12626
13080
|
return;
|
|
12627
13081
|
}
|
|
12628
13082
|
if (argv.includes("--json")) setJsonMode(true);
|
|
12629
|
-
|
|
13083
|
+
const notifier = startCommandUpdateNotifier(version, args2, runtime, env);
|
|
13084
|
+
try {
|
|
13085
|
+
await createProgram(version, { ...runtime, argv }).parseAsync(argv);
|
|
13086
|
+
} finally {
|
|
13087
|
+
notifier?.();
|
|
13088
|
+
}
|
|
13089
|
+
}
|
|
13090
|
+
function startCommandUpdateNotifier(version, args2, runtime, env) {
|
|
13091
|
+
const error = runtime.stderr ?? process.stderr;
|
|
13092
|
+
if (runtime.checkForUpdate || error.isTTY !== true || cliUpdateChecksDisabled(env) || args2.some((arg) => ["--json", "--version", "-V", "--help", "-h"].includes(arg)) || ["upgrade", "update", "help"].includes(args2[0] ?? "")) return null;
|
|
13093
|
+
const cacheFile = getCliUpdateCacheFile(env);
|
|
13094
|
+
if (cliUpdateCacheIsStale(cacheFile)) spawnCliUpdateRefresh(cacheFile);
|
|
13095
|
+
return () => {
|
|
13096
|
+
if (isJsonMode()) return;
|
|
13097
|
+
const update = cachedCliUpdate(version, cacheFile);
|
|
13098
|
+
if (update) error.write(`
|
|
13099
|
+
${formatCliUpdateNotice(update)}
|
|
13100
|
+
`);
|
|
13101
|
+
};
|
|
12630
13102
|
}
|
|
12631
13103
|
|
|
12632
13104
|
// src/index.ts
|
|
12633
|
-
runCli("0.
|
|
13105
|
+
runCli("0.22.1").catch((err) => {
|
|
12634
13106
|
reportError(err);
|
|
12635
13107
|
process.exit(1);
|
|
12636
13108
|
});
|