@elnora-ai/cli 1.3.0 → 1.3.2
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/cli.js +140 -86
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -25,7 +25,7 @@ var VERSION, PRODUCTION_BASE_URL, BASE_URL, AI_SERVER_URL, ENDPOINTS, DEFAULT_HE
|
|
|
25
25
|
var init_config = __esm({
|
|
26
26
|
"src/lib/config.ts"() {
|
|
27
27
|
"use strict";
|
|
28
|
-
VERSION =
|
|
28
|
+
VERSION = true ? "1.3.2" : process.env.npm_package_version ?? "0.0.0-dev";
|
|
29
29
|
PRODUCTION_BASE_URL = "https://platform.elnora.ai/api/v1";
|
|
30
30
|
BASE_URL = process.env.ELNORA_API_URL ?? PRODUCTION_BASE_URL;
|
|
31
31
|
AI_SERVER_URL = process.env.ELNORA_AI_SERVER_URL ?? "https://platform.elnora.ai/ai-server";
|
|
@@ -2020,10 +2020,9 @@ var CACHE_FILE = join2(CACHE_DIR, ".update-check");
|
|
|
2020
2020
|
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
2021
2021
|
var FETCH_TIMEOUT_MS = 3e3;
|
|
2022
2022
|
var SEMVER_RE = /^\d+\.\d+\.\d+(?:-[\w.]+)?(?:\+[\w.]+)?$/;
|
|
2023
|
-
function
|
|
2023
|
+
function shouldSkipEntirely() {
|
|
2024
2024
|
if (process.env.CI || process.env.GITHUB_ACTIONS) return true;
|
|
2025
2025
|
if (process.env.ELNORA_NO_UPDATE_CHECK) return true;
|
|
2026
|
-
if (!process.stderr.isTTY) return true;
|
|
2027
2026
|
return false;
|
|
2028
2027
|
}
|
|
2029
2028
|
function readCache() {
|
|
@@ -2043,13 +2042,14 @@ function writeCache(entry) {
|
|
|
2043
2042
|
}
|
|
2044
2043
|
}
|
|
2045
2044
|
function showUpdateNotice(latest) {
|
|
2045
|
+
if (!process.stderr.isTTY) return;
|
|
2046
2046
|
const color2 = isColorEnabled();
|
|
2047
2047
|
const msg = color2 ? `
|
|
2048
2048
|
${pc.yellow(`Update available: v${VERSION} \u2192 v${latest}`)}
|
|
2049
|
-
Run:
|
|
2049
|
+
Run: elnora update
|
|
2050
2050
|
` : `
|
|
2051
2051
|
Update available: v${VERSION} \u2192 v${latest}
|
|
2052
|
-
Run:
|
|
2052
|
+
Run: elnora update
|
|
2053
2053
|
`;
|
|
2054
2054
|
process.stderr.write(msg);
|
|
2055
2055
|
}
|
|
@@ -2065,7 +2065,7 @@ function isNewerVersion(a, b) {
|
|
|
2065
2065
|
return false;
|
|
2066
2066
|
}
|
|
2067
2067
|
function registerUpdateCheck() {
|
|
2068
|
-
if (
|
|
2068
|
+
if (shouldSkipEntirely()) return;
|
|
2069
2069
|
const cached = readCache();
|
|
2070
2070
|
if (cached) {
|
|
2071
2071
|
const elapsed = Date.now() - new Date(cached.checkedAt).getTime();
|
|
@@ -2078,7 +2078,9 @@ function registerUpdateCheck() {
|
|
|
2078
2078
|
return;
|
|
2079
2079
|
}
|
|
2080
2080
|
}
|
|
2081
|
-
|
|
2081
|
+
const keepAlive = setInterval(() => {
|
|
2082
|
+
}, 6e4);
|
|
2083
|
+
(async () => {
|
|
2082
2084
|
try {
|
|
2083
2085
|
const response = await fetch(NPM_REGISTRY_URL, {
|
|
2084
2086
|
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
|
|
@@ -2092,8 +2094,10 @@ function registerUpdateCheck() {
|
|
|
2092
2094
|
showUpdateNotice(latest);
|
|
2093
2095
|
}
|
|
2094
2096
|
} catch {
|
|
2097
|
+
} finally {
|
|
2098
|
+
clearInterval(keepAlive);
|
|
2095
2099
|
}
|
|
2096
|
-
}
|
|
2100
|
+
})();
|
|
2097
2101
|
}
|
|
2098
2102
|
|
|
2099
2103
|
// src/commands/doctor.ts
|
|
@@ -4873,6 +4877,30 @@ import { join as join6 } from "node:path";
|
|
|
4873
4877
|
import { Readable } from "node:stream";
|
|
4874
4878
|
import { pipeline } from "node:stream/promises";
|
|
4875
4879
|
import pc5 from "picocolors";
|
|
4880
|
+
|
|
4881
|
+
// src/lib/install-method.ts
|
|
4882
|
+
function detectInstallMethod() {
|
|
4883
|
+
const execPath = process.argv[1] ?? "";
|
|
4884
|
+
if (execPath.includes("node_modules")) {
|
|
4885
|
+
return "npm";
|
|
4886
|
+
}
|
|
4887
|
+
if (execPath.includes("/Cellar/") || execPath.includes("/homebrew/")) {
|
|
4888
|
+
return "homebrew";
|
|
4889
|
+
}
|
|
4890
|
+
return "binary";
|
|
4891
|
+
}
|
|
4892
|
+
function getUpdateInstruction(method) {
|
|
4893
|
+
switch (method) {
|
|
4894
|
+
case "npm":
|
|
4895
|
+
return "npm update -g @elnora-ai/cli";
|
|
4896
|
+
case "homebrew":
|
|
4897
|
+
return "brew upgrade elnora";
|
|
4898
|
+
case "binary":
|
|
4899
|
+
return "elnora update --install";
|
|
4900
|
+
}
|
|
4901
|
+
}
|
|
4902
|
+
|
|
4903
|
+
// src/commands/update.ts
|
|
4876
4904
|
var NPM_REGISTRY_URL2 = "https://registry.npmjs.org/@elnora-ai/cli/latest";
|
|
4877
4905
|
var GITHUB_REPO = "Elnora-AI/elnora-cli";
|
|
4878
4906
|
function getPlatformTarget() {
|
|
@@ -4888,8 +4916,11 @@ function getPlatformTarget() {
|
|
|
4888
4916
|
return null;
|
|
4889
4917
|
}
|
|
4890
4918
|
}
|
|
4891
|
-
function
|
|
4892
|
-
|
|
4919
|
+
async function fetchLatestVersion() {
|
|
4920
|
+
const res = await fetch(NPM_REGISTRY_URL2, { signal: AbortSignal.timeout(5e3) });
|
|
4921
|
+
if (!res.ok) throw new Error(`Registry returned HTTP ${res.status}`);
|
|
4922
|
+
const data = await res.json();
|
|
4923
|
+
return data.version ?? "unknown";
|
|
4893
4924
|
}
|
|
4894
4925
|
async function downloadToFile(url, dest) {
|
|
4895
4926
|
const res = await fetch(url, { signal: AbortSignal.timeout(12e4), redirect: "follow" });
|
|
@@ -4897,98 +4928,121 @@ async function downloadToFile(url, dest) {
|
|
|
4897
4928
|
const nodeStream = Readable.fromWeb(res.body);
|
|
4898
4929
|
await pipeline(nodeStream, createWriteStream(dest));
|
|
4899
4930
|
}
|
|
4931
|
+
async function installBinaryUpdate(latest) {
|
|
4932
|
+
const color2 = isColorEnabled();
|
|
4933
|
+
const platformInfo = getPlatformTarget();
|
|
4934
|
+
if (!platformInfo) {
|
|
4935
|
+
console.error(`Unsupported platform: ${process.platform}.`);
|
|
4936
|
+
console.error("Try: npm update -g @elnora-ai/cli");
|
|
4937
|
+
process.exitCode = 1;
|
|
4938
|
+
return;
|
|
4939
|
+
}
|
|
4940
|
+
const { target, ext } = platformInfo;
|
|
4941
|
+
const binaryUrl = `https://github.com/${GITHUB_REPO}/releases/download/v${latest}/${target}.${ext}`;
|
|
4942
|
+
const checksumUrl = `https://github.com/${GITHUB_REPO}/releases/download/v${latest}/${target}.sha256`;
|
|
4943
|
+
const tmp = join6(tmpdir(), `elnora-update-${Date.now()}`);
|
|
4944
|
+
mkdirSync4(tmp, { recursive: true });
|
|
4945
|
+
const archivePath = join6(tmp, `${target}.${ext}`);
|
|
4946
|
+
try {
|
|
4947
|
+
console.error("Downloading...");
|
|
4948
|
+
await downloadToFile(binaryUrl, archivePath);
|
|
4949
|
+
let checksumVerified = false;
|
|
4950
|
+
try {
|
|
4951
|
+
const checksumRes = await fetch(checksumUrl, { signal: AbortSignal.timeout(15e3) });
|
|
4952
|
+
if (checksumRes.ok) {
|
|
4953
|
+
const checksumText = await checksumRes.text();
|
|
4954
|
+
const expected = checksumText.split(/\s/)[0].trim();
|
|
4955
|
+
if (expected.length === 64) {
|
|
4956
|
+
const actual = createHash("sha256").update(readFileSync6(archivePath)).digest("hex");
|
|
4957
|
+
if (actual.toLowerCase() !== expected.toLowerCase()) {
|
|
4958
|
+
console.error("Checksum verification failed. The download may be corrupted.");
|
|
4959
|
+
process.exitCode = 1;
|
|
4960
|
+
return;
|
|
4961
|
+
}
|
|
4962
|
+
checksumVerified = true;
|
|
4963
|
+
}
|
|
4964
|
+
}
|
|
4965
|
+
} catch {
|
|
4966
|
+
}
|
|
4967
|
+
if (!checksumVerified) {
|
|
4968
|
+
console.error("Warning: Could not verify download checksum. Proceeding anyway.");
|
|
4969
|
+
}
|
|
4970
|
+
if (process.platform === "win32") {
|
|
4971
|
+
const extractDir = join6(tmp, "extracted");
|
|
4972
|
+
execFileSync("powershell", [
|
|
4973
|
+
"-NoProfile",
|
|
4974
|
+
"-Command",
|
|
4975
|
+
`Expand-Archive -Path '${archivePath}' -DestinationPath '${extractDir}' -Force`
|
|
4976
|
+
]);
|
|
4977
|
+
const installDir = join6(process.env.USERPROFILE ?? process.env.HOME ?? "", ".elnora", "bin");
|
|
4978
|
+
mkdirSync4(installDir, { recursive: true });
|
|
4979
|
+
copyFileSync(join6(extractDir, target), join6(installDir, "elnora.exe"));
|
|
4980
|
+
} else {
|
|
4981
|
+
execFileSync("tar", ["-xzf", archivePath, "-C", tmp]);
|
|
4982
|
+
const installDir = process.env.ELNORA_INSTALL_DIR ?? join6(process.env.HOME ?? "", ".local", "bin");
|
|
4983
|
+
mkdirSync4(installDir, { recursive: true });
|
|
4984
|
+
const dest = join6(installDir, "elnora");
|
|
4985
|
+
copyFileSync(join6(tmp, target), dest);
|
|
4986
|
+
chmodSync2(dest, 493);
|
|
4987
|
+
}
|
|
4988
|
+
const done = color2 ? `${pc5.green("\u2713")} Updated to v${latest}` : `\u2713 Updated to v${latest}`;
|
|
4989
|
+
console.error(done);
|
|
4990
|
+
} finally {
|
|
4991
|
+
try {
|
|
4992
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
4993
|
+
} catch {
|
|
4994
|
+
}
|
|
4995
|
+
}
|
|
4996
|
+
}
|
|
4900
4997
|
function addUpdateCommand(program2) {
|
|
4901
|
-
program2.command("update").description("
|
|
4998
|
+
program2.command("update").description("Check for updates (use --install to apply)").option("--install", "Download and install the update").action(async (opts) => {
|
|
4902
4999
|
const color2 = isColorEnabled();
|
|
4903
|
-
const
|
|
5000
|
+
const method = detectInstallMethod();
|
|
4904
5001
|
let latest;
|
|
4905
5002
|
try {
|
|
4906
|
-
|
|
4907
|
-
if (!res.ok) {
|
|
4908
|
-
console.error("Failed to check for updates. Try manually:");
|
|
4909
|
-
console.error(hint);
|
|
4910
|
-
process.exit(1);
|
|
4911
|
-
}
|
|
4912
|
-
const data = await res.json();
|
|
4913
|
-
latest = data.version ?? "unknown";
|
|
5003
|
+
latest = await fetchLatestVersion();
|
|
4914
5004
|
} catch {
|
|
4915
|
-
console.error("Failed to
|
|
4916
|
-
|
|
4917
|
-
|
|
5005
|
+
console.error("Failed to check for updates.");
|
|
5006
|
+
process.exitCode = 1;
|
|
5007
|
+
return;
|
|
5008
|
+
}
|
|
5009
|
+
if (latest === "unknown") {
|
|
5010
|
+
console.error("Could not determine latest version.");
|
|
5011
|
+
process.exitCode = 1;
|
|
5012
|
+
return;
|
|
4918
5013
|
}
|
|
4919
5014
|
if (latest === VERSION || !isNewerVersion(latest, VERSION)) {
|
|
4920
5015
|
const msg2 = color2 ? `${pc5.green("\u2713")} Already on the latest version (v${VERSION})` : `\u2713 Already on the latest version (v${VERSION})`;
|
|
4921
5016
|
console.error(msg2);
|
|
4922
5017
|
return;
|
|
4923
5018
|
}
|
|
5019
|
+
const instruction = getUpdateInstruction(method);
|
|
5020
|
+
if (!opts.install) {
|
|
5021
|
+
const msg2 = color2 ? `${pc5.yellow("Update available:")} v${VERSION} \u2192 v${latest}` : `Update available: v${VERSION} \u2192 v${latest}`;
|
|
5022
|
+
console.error(msg2);
|
|
5023
|
+
console.error(`Run: ${instruction}`);
|
|
5024
|
+
return;
|
|
5025
|
+
}
|
|
4924
5026
|
const msg = color2 ? `Updating Elnora CLI ${pc5.dim(`v${VERSION}`)} \u2192 ${pc5.green(`v${latest}`)}...` : `Updating Elnora CLI v${VERSION} \u2192 v${latest}...`;
|
|
4925
5027
|
console.error(msg);
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
console.error(`
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
5028
|
+
if (method === "npm") {
|
|
5029
|
+
console.error("Installed via npm. Run:");
|
|
5030
|
+
console.error(` npm update -g @elnora-ai/cli`);
|
|
5031
|
+
return;
|
|
5032
|
+
}
|
|
5033
|
+
if (method === "homebrew") {
|
|
5034
|
+
console.error("Installed via Homebrew. Run:");
|
|
5035
|
+
console.error(` brew upgrade elnora`);
|
|
5036
|
+
return;
|
|
4932
5037
|
}
|
|
4933
|
-
const { target, ext } = platformInfo;
|
|
4934
|
-
const binaryUrl = `https://github.com/${GITHUB_REPO}/releases/download/v${latest}/${target}.${ext}`;
|
|
4935
|
-
const checksumUrl = `https://github.com/${GITHUB_REPO}/releases/download/v${latest}/${target}.sha256`;
|
|
4936
|
-
const tmp = join6(tmpdir(), `elnora-update-${Date.now()}`);
|
|
4937
|
-
mkdirSync4(tmp, { recursive: true });
|
|
4938
|
-
const archivePath = join6(tmp, `${target}.${ext}`);
|
|
4939
5038
|
try {
|
|
4940
|
-
await
|
|
4941
|
-
let checksumVerified = false;
|
|
4942
|
-
try {
|
|
4943
|
-
const checksumRes = await fetch(checksumUrl, { signal: AbortSignal.timeout(15e3) });
|
|
4944
|
-
if (checksumRes.ok) {
|
|
4945
|
-
const checksumText = await checksumRes.text();
|
|
4946
|
-
const expected = checksumText.split(/\s/)[0].trim();
|
|
4947
|
-
if (expected.length === 64) {
|
|
4948
|
-
const actual = createHash("sha256").update(readFileSync6(archivePath)).digest("hex");
|
|
4949
|
-
if (actual.toLowerCase() !== expected.toLowerCase()) {
|
|
4950
|
-
console.error("\nChecksum verification failed. The download may be corrupted.");
|
|
4951
|
-
console.error("Try again, or install manually:");
|
|
4952
|
-
console.error(hint);
|
|
4953
|
-
process.exit(1);
|
|
4954
|
-
}
|
|
4955
|
-
checksumVerified = true;
|
|
4956
|
-
}
|
|
4957
|
-
}
|
|
4958
|
-
} catch {
|
|
4959
|
-
}
|
|
4960
|
-
if (!checksumVerified) {
|
|
4961
|
-
console.error("Warning: Could not verify download checksum. Proceeding anyway.");
|
|
4962
|
-
}
|
|
4963
|
-
if (process.platform === "win32") {
|
|
4964
|
-
const extractDir = join6(tmp, "extracted");
|
|
4965
|
-
execFileSync("powershell", [
|
|
4966
|
-
"-NoProfile",
|
|
4967
|
-
"-Command",
|
|
4968
|
-
`Expand-Archive -Path '${archivePath}' -DestinationPath '${extractDir}' -Force`
|
|
4969
|
-
]);
|
|
4970
|
-
const installDir = join6(process.env.USERPROFILE ?? process.env.HOME ?? "", ".elnora", "bin");
|
|
4971
|
-
mkdirSync4(installDir, { recursive: true });
|
|
4972
|
-
copyFileSync(join6(extractDir, target), join6(installDir, "elnora.exe"));
|
|
4973
|
-
} else {
|
|
4974
|
-
execFileSync("tar", ["-xzf", archivePath, "-C", tmp]);
|
|
4975
|
-
const installDir = process.env.ELNORA_INSTALL_DIR ?? join6(process.env.HOME ?? "", ".local", "bin");
|
|
4976
|
-
mkdirSync4(installDir, { recursive: true });
|
|
4977
|
-
const dest = join6(installDir, "elnora");
|
|
4978
|
-
copyFileSync(join6(tmp, target), dest);
|
|
4979
|
-
chmodSync2(dest, 493);
|
|
4980
|
-
}
|
|
4981
|
-
const done = color2 ? `${pc5.green("\u2713")} Updated to v${latest}` : `\u2713 Updated to v${latest}`;
|
|
4982
|
-
console.error(done);
|
|
5039
|
+
await installBinaryUpdate(latest);
|
|
4983
5040
|
} catch {
|
|
4984
|
-
console.error("
|
|
4985
|
-
console.error(
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
4990
|
-
} catch {
|
|
4991
|
-
}
|
|
5041
|
+
console.error("Update failed. Try manually:");
|
|
5042
|
+
console.error(
|
|
5043
|
+
process.platform === "win32" ? " irm https://cli.elnora.ai/install.ps1 | iex" : " curl -fsSL https://cli.elnora.ai/install.sh | bash"
|
|
5044
|
+
);
|
|
5045
|
+
process.exitCode = 1;
|
|
4992
5046
|
}
|
|
4993
5047
|
});
|
|
4994
5048
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elnora-ai/cli",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "Elnora AI Platform CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"vitest": "^4.1.2"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
|
-
"build": "
|
|
56
|
+
"build": "node scripts/build-npm.mjs",
|
|
57
57
|
"build:binary": "node scripts/build.mjs --pkg",
|
|
58
58
|
"dev": "tsx src/cli.ts",
|
|
59
59
|
"test": "vitest run",
|