@tuned-tensor/cli 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -63,6 +63,11 @@ Selection metadata can be overridden per process with
63
63
  After configuration, run `tt` to open one terminal for conversation and
64
64
  commands:
65
65
 
66
+ Before the shell opens, `tt` performs a short, non-blocking npm version check.
67
+ If a newer stable release is available it recommends
68
+ `npm install -g @tuned-tensor/cli@latest`; offline or unavailable registry
69
+ checks are ignored.
70
+
66
71
  ```text
67
72
  tt cloud support-agent › What happened in my latest training run?
68
73
  TT Your latest run completed...
package/dist/index.js CHANGED
@@ -8213,6 +8213,95 @@ function registerPipelineCommands(parent) {
8213
8213
  });
8214
8214
  }
8215
8215
 
8216
+ // src/update-check.ts
8217
+ var PACKAGE_LATEST_URL = "https://registry.npmjs.org/@tuned-tensor%2fcli/latest";
8218
+ function parseVersion(version) {
8219
+ const match = version.trim().match(
8220
+ /^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-]+)*)?$/
8221
+ );
8222
+ if (!match) return null;
8223
+ const prerelease = match[4]?.split(".") ?? [];
8224
+ if (prerelease.some((part) => /^0\d+$/.test(part))) return null;
8225
+ return {
8226
+ major: BigInt(match[1]),
8227
+ minor: BigInt(match[2]),
8228
+ patch: BigInt(match[3]),
8229
+ prerelease
8230
+ };
8231
+ }
8232
+ function comparePrerelease(left, right) {
8233
+ if (left.length === 0 && right.length === 0) return 0;
8234
+ if (left.length === 0) return 1;
8235
+ if (right.length === 0) return -1;
8236
+ for (let index = 0; index < Math.max(left.length, right.length); index += 1) {
8237
+ const leftPart = left[index];
8238
+ const rightPart = right[index];
8239
+ if (leftPart === void 0) return -1;
8240
+ if (rightPart === void 0) return 1;
8241
+ if (leftPart === rightPart) continue;
8242
+ const leftNumeric = /^\d+$/.test(leftPart);
8243
+ const rightNumeric = /^\d+$/.test(rightPart);
8244
+ if (leftNumeric && rightNumeric) {
8245
+ if (leftPart.length !== rightPart.length) {
8246
+ return leftPart.length > rightPart.length ? 1 : -1;
8247
+ }
8248
+ return leftPart > rightPart ? 1 : -1;
8249
+ }
8250
+ if (leftNumeric !== rightNumeric) return leftNumeric ? -1 : 1;
8251
+ return leftPart > rightPart ? 1 : -1;
8252
+ }
8253
+ return 0;
8254
+ }
8255
+ function compareVersions(left, right) {
8256
+ for (const key of ["major", "minor", "patch"]) {
8257
+ if (left[key] !== right[key]) return left[key] > right[key] ? 1 : -1;
8258
+ }
8259
+ return comparePrerelease(left.prerelease, right.prerelease);
8260
+ }
8261
+ async function checkForCliUpdate(currentVersion, options = {}) {
8262
+ const current = parseVersion(currentVersion);
8263
+ if (!current) return null;
8264
+ const controller = new AbortController();
8265
+ const timeoutMs = options.timeoutMs ?? 750;
8266
+ let timeout;
8267
+ const request2 = (async () => {
8268
+ try {
8269
+ const response = await (options.fetchImpl ?? fetch)(PACKAGE_LATEST_URL, {
8270
+ headers: { accept: "application/json" },
8271
+ signal: controller.signal
8272
+ });
8273
+ if (!response.ok) return null;
8274
+ const payload = await response.json();
8275
+ if (typeof payload.version !== "string") return null;
8276
+ const latest = parseVersion(payload.version);
8277
+ if (!latest || latest.prerelease.length > 0 || compareVersions(latest, current) <= 0) return null;
8278
+ return {
8279
+ currentVersion,
8280
+ latestVersion: payload.version
8281
+ };
8282
+ } catch {
8283
+ return null;
8284
+ }
8285
+ })();
8286
+ const deadline = new Promise((resolve8) => {
8287
+ timeout = setTimeout(() => {
8288
+ controller.abort();
8289
+ resolve8(null);
8290
+ }, timeoutMs);
8291
+ });
8292
+ try {
8293
+ return await Promise.race([request2, deadline]);
8294
+ } finally {
8295
+ if (timeout) clearTimeout(timeout);
8296
+ }
8297
+ }
8298
+ function formatCliUpdateNotice(update) {
8299
+ return [
8300
+ `Update available: tt ${update.currentVersion} \u2192 ${update.latestVersion}`,
8301
+ "Upgrade with: npm install -g @tuned-tensor/cli@latest"
8302
+ ].join("\n");
8303
+ }
8304
+
8216
8305
  // src/cli.ts
8217
8306
  async function createDefaultAgentClient(runtime, env, cloud, workspaceRoot) {
8218
8307
  const selection = getAgentSelection(env);
@@ -8543,9 +8632,19 @@ async function runCli(version, runtime = {}) {
8543
8632
  stdoutIsTTY: runtime.stdoutIsTTY ?? process.stdout.isTTY,
8544
8633
  env
8545
8634
  })) {
8546
- const invokeSelf = runtime.runSelfCommand ?? runSelfCommand;
8547
8635
  const output = runtime.stdout ?? process.stdout;
8548
8636
  const error = runtime.stderr ?? process.stderr;
8637
+ let update = null;
8638
+ try {
8639
+ update = await (runtime.checkForUpdate ?? checkForCliUpdate)(version);
8640
+ } catch {
8641
+ }
8642
+ if (update) {
8643
+ error.write(`${formatCliUpdateNotice(update)}
8644
+
8645
+ `);
8646
+ }
8647
+ const invokeSelf = runtime.runSelfCommand ?? runSelfCommand;
8549
8648
  const agent = createShellAgent({
8550
8649
  client: runtime.agentClient ?? createLazyDefaultAgentClient(runtime, env, {
8551
8650
  apiKey: env.TUNED_TENSOR_API_KEY,
@@ -8578,7 +8677,7 @@ async function runCli(version, runtime = {}) {
8578
8677
  }
8579
8678
 
8580
8679
  // src/index.ts
8581
- runCli("0.10.0").catch((err) => {
8680
+ runCli("0.11.0").catch((err) => {
8582
8681
  reportError(err);
8583
8682
  process.exit(1);
8584
8683
  });