hirmos 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/README.md +38 -6
- package/dist/commands/init.js +10 -3
- package/dist/index.js +11 -1
- package/dist/lib/args.js +29 -3
- package/dist/lib/source-install.js +80 -6
- package/dist/lib/update-notice.js +79 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,27 +5,30 @@ Product-facing HIRMOS CLI.
|
|
|
5
5
|
Implemented command:
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
hirmos init [project-path] [--integration <ids>] [--source <path>]
|
|
8
|
+
hirmos init [project-path] [--integration <ids>] [--source <path>] [--version <version>] [--offline]
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
The CLI makes an installed HIRMOS project discoverable to selected agent-native tools by generating thin bootstrap integration files from `_hirmos/integrations/agent-tools/`.
|
|
12
12
|
|
|
13
|
-
It does not invoke agents, run HIRMOS workflows, install extensions,
|
|
13
|
+
It does not invoke agents, run HIRMOS workflows, install extensions, or generate slash-command packs.
|
|
14
14
|
|
|
15
15
|
## Usage
|
|
16
16
|
|
|
17
|
-
From a project
|
|
17
|
+
From a project root:
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
20
|
hirmos init
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
If `_hirmos/` is not present, the CLI downloads the latest HIRMOS framework release package and installs `_hirmos/` before generating integrations.
|
|
24
|
+
|
|
23
25
|
This defaults to:
|
|
24
26
|
|
|
25
27
|
```text
|
|
26
28
|
project-path = .
|
|
27
29
|
integration = agents
|
|
28
|
-
source = existing _hirmos/ in the project
|
|
30
|
+
source = existing _hirmos/ in the project, otherwise latest GitHub release
|
|
31
|
+
version = latest
|
|
29
32
|
```
|
|
30
33
|
|
|
31
34
|
Generate specific integrations:
|
|
@@ -40,12 +43,41 @@ Initialize another project path:
|
|
|
40
43
|
hirmos init /path/to/project --integration agents,claude
|
|
41
44
|
```
|
|
42
45
|
|
|
43
|
-
Install
|
|
46
|
+
Install a specific HIRMOS release:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
hirmos init --version 1.3.1
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Install `_hirmos/` from a local source folder or release zip instead of downloading:
|
|
44
53
|
|
|
45
54
|
```bash
|
|
46
55
|
hirmos init /path/to/project --source /path/to/hirmos-framework.zip --integration agents
|
|
47
56
|
```
|
|
48
57
|
|
|
58
|
+
Disable remote download and require an existing `_hirmos/` or local `--source`:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
hirmos init --offline
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## CLI update notice
|
|
65
|
+
|
|
66
|
+
When `hirmos init` runs online, it checks whether a newer published HIRMOS CLI version is available on npm. If a newer version exists, the CLI prints a non-blocking message such as:
|
|
67
|
+
|
|
68
|
+
```text
|
|
69
|
+
A newer HIRMOS CLI is available: 1.3.2.
|
|
70
|
+
Update with: npm install -g hirmos@latest
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The notice does not stop initialization. Network failures, registry errors, or timeouts are ignored.
|
|
74
|
+
|
|
75
|
+
Use `--offline` to disable both remote framework download and the update check. To disable only the update notice while keeping remote framework download available, run:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
HIRMOS_CLI_UPDATE_CHECK=0 hirmos init
|
|
79
|
+
```
|
|
80
|
+
|
|
49
81
|
## Supported integrations
|
|
50
82
|
|
|
51
83
|
```text
|
|
@@ -104,4 +136,4 @@ hirmos system-design
|
|
|
104
136
|
hirmos implementation
|
|
105
137
|
```
|
|
106
138
|
|
|
107
|
-
The CLI
|
|
139
|
+
The CLI implements `hirmos init`.
|
package/dist/commands/init.js
CHANGED
|
@@ -15,7 +15,11 @@ const validation_1 = require("../lib/validation");
|
|
|
15
15
|
function runInit(options) {
|
|
16
16
|
const projectRoot = path_1.default.resolve(options.projectPath);
|
|
17
17
|
(0, validation_1.validateProjectRoot)(projectRoot);
|
|
18
|
-
(0, source_install_1.ensureHirmosInstalled)(projectRoot,
|
|
18
|
+
const installResult = (0, source_install_1.ensureHirmosInstalled)(projectRoot, {
|
|
19
|
+
source: options.source,
|
|
20
|
+
version: options.version,
|
|
21
|
+
offline: options.offline
|
|
22
|
+
});
|
|
19
23
|
(0, validation_1.validateHirmosFramework)(projectRoot);
|
|
20
24
|
const hirmosDir = path_1.default.join(projectRoot, "_hirmos");
|
|
21
25
|
const registry = (0, integration_registry_1.loadRegistry)(hirmosDir);
|
|
@@ -38,12 +42,15 @@ function runInit(options) {
|
|
|
38
42
|
(0, filesystem_1.writeText)(write.path, write.content);
|
|
39
43
|
}
|
|
40
44
|
(0, project_config_1.writeProjectConfig)(projectRoot, mergeResult.config);
|
|
41
|
-
return formatInitSummary(mergeResult.wasFirstInitialization, selected, mergeResult.added, mergeResult.alreadyInstalled, renderedWrites.map((item) => item.relative));
|
|
45
|
+
return formatInitSummary(mergeResult.wasFirstInitialization, selected, mergeResult.added, mergeResult.alreadyInstalled, renderedWrites.map((item) => item.relative), installResult);
|
|
42
46
|
}
|
|
43
|
-
function formatInitSummary(first, selected, added, alreadyInstalled, targets) {
|
|
47
|
+
function formatInitSummary(first, selected, added, alreadyInstalled, targets, installResult) {
|
|
44
48
|
const lines = [];
|
|
45
49
|
if (first) {
|
|
46
50
|
lines.push("HIRMOS initialized.", "");
|
|
51
|
+
if (installResult.installed && installResult.sourceDescription) {
|
|
52
|
+
lines.push(`Installed framework from ${installResult.sourceDescription}.`, "");
|
|
53
|
+
}
|
|
47
54
|
lines.push("Installed integrations:");
|
|
48
55
|
for (const id of selected)
|
|
49
56
|
lines.push(`- ${id}`);
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
const args_1 = require("./lib/args");
|
|
5
5
|
const errors_1 = require("./lib/errors");
|
|
6
6
|
const init_1 = require("./commands/init");
|
|
7
|
+
const update_notice_1 = require("./lib/update-notice");
|
|
7
8
|
function main() {
|
|
8
9
|
try {
|
|
9
10
|
const parsed = (0, args_1.parseArgs)(process.argv.slice(2));
|
|
@@ -12,10 +13,19 @@ function main() {
|
|
|
12
13
|
return;
|
|
13
14
|
}
|
|
14
15
|
if (parsed.command === "init") {
|
|
16
|
+
if (!parsed.offline) {
|
|
17
|
+
const updateNotice = (0, update_notice_1.getUpdateNotice)();
|
|
18
|
+
if (updateNotice)
|
|
19
|
+
process.stderr.write(`${(0, update_notice_1.formatUpdateNotice)(updateNotice)}
|
|
20
|
+
|
|
21
|
+
`);
|
|
22
|
+
}
|
|
15
23
|
const summary = (0, init_1.runInit)({
|
|
16
24
|
projectPath: parsed.projectPath,
|
|
17
25
|
integrations: parsed.integrations,
|
|
18
|
-
source: parsed.source
|
|
26
|
+
source: parsed.source,
|
|
27
|
+
version: parsed.version,
|
|
28
|
+
offline: parsed.offline
|
|
19
29
|
});
|
|
20
30
|
process.stdout.write(summary);
|
|
21
31
|
return;
|
package/dist/lib/args.js
CHANGED
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.parseArgs = parseArgs;
|
|
7
|
+
exports.normalizeVersionOption = normalizeVersionOption;
|
|
7
8
|
exports.parseIntegrationList = parseIntegrationList;
|
|
8
9
|
exports.helpText = helpText;
|
|
9
10
|
const path_1 = __importDefault(require("path"));
|
|
@@ -14,12 +15,14 @@ function parseArgs(argv) {
|
|
|
14
15
|
}
|
|
15
16
|
const command = argv[0];
|
|
16
17
|
if (command !== "init") {
|
|
17
|
-
(0, errors_1.fail)(`Unsupported command: ${command}.
|
|
18
|
+
(0, errors_1.fail)(`Unsupported command: ${command}. This CLI currently supports: hirmos init`);
|
|
18
19
|
}
|
|
19
20
|
let projectPath = ".";
|
|
20
21
|
let projectPathSet = false;
|
|
21
22
|
let integrationValue;
|
|
22
23
|
let source;
|
|
24
|
+
let version = "latest";
|
|
25
|
+
let offline = false;
|
|
23
26
|
for (let i = 1; i < argv.length; i += 1) {
|
|
24
27
|
const arg = argv[i];
|
|
25
28
|
if (arg === "--integration") {
|
|
@@ -44,6 +47,21 @@ function parseArgs(argv) {
|
|
|
44
47
|
source = arg.slice("--source=".length);
|
|
45
48
|
continue;
|
|
46
49
|
}
|
|
50
|
+
if (arg === "--version") {
|
|
51
|
+
const value = argv[++i];
|
|
52
|
+
if (!value)
|
|
53
|
+
(0, errors_1.fail)("Missing value for --version");
|
|
54
|
+
version = value;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (arg.startsWith("--version=")) {
|
|
58
|
+
version = arg.slice("--version=".length);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (arg === "--offline") {
|
|
62
|
+
offline = true;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
47
65
|
if (arg === "--help" || arg === "-h") {
|
|
48
66
|
return { command: "help" };
|
|
49
67
|
}
|
|
@@ -61,9 +79,17 @@ function parseArgs(argv) {
|
|
|
61
79
|
command: "init",
|
|
62
80
|
projectPath: path_1.default.resolve(projectPath),
|
|
63
81
|
integrations,
|
|
64
|
-
source: source ? path_1.default.resolve(source) : undefined
|
|
82
|
+
source: source ? path_1.default.resolve(source) : undefined,
|
|
83
|
+
version: normalizeVersionOption(version),
|
|
84
|
+
offline
|
|
65
85
|
};
|
|
66
86
|
}
|
|
87
|
+
function normalizeVersionOption(value) {
|
|
88
|
+
const normalized = value.trim();
|
|
89
|
+
if (!normalized)
|
|
90
|
+
(0, errors_1.fail)("--version must not be empty");
|
|
91
|
+
return normalized;
|
|
92
|
+
}
|
|
67
93
|
function parseIntegrationList(value) {
|
|
68
94
|
const ids = value
|
|
69
95
|
.split(",")
|
|
@@ -75,5 +101,5 @@ function parseIntegrationList(value) {
|
|
|
75
101
|
return ids;
|
|
76
102
|
}
|
|
77
103
|
function helpText() {
|
|
78
|
-
return `HIRMOS CLI\n\nUsage:\n hirmos init [project-path] [--integration <ids>] [--source <path>]\n\nDefaults:\n project-path: .\n integration: agents\n source: existing _hirmos/ in the project\n\
|
|
104
|
+
return `HIRMOS CLI\n\nUsage:\n hirmos init [project-path] [--integration <ids>] [--source <path>] [--version <version>] [--offline]\n\nDefaults:\n project-path: .\n integration: agents\n source: existing _hirmos/ in the project, otherwise the latest GitHub release\n version: latest\n\nNotes:\n --source installs from a local _hirmos folder, framework folder, or hirmos-framework.zip.\n --version selects a GitHub release when _hirmos/ is missing and --source is not provided.\n --offline disables remote release download and requires an existing _hirmos/ or --source.\n\nThis CLI implements hirmos init. Workflow commands such as hirmos requirements are interpreted by an agent after HIRMOS Core is loaded.\n`;
|
|
79
105
|
}
|
|
@@ -4,20 +4,61 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.ensureHirmosInstalled = ensureHirmosInstalled;
|
|
7
|
+
exports.buildReleaseDownloadUrl = buildReleaseDownloadUrl;
|
|
8
|
+
exports.normalizeReleaseVersion = normalizeReleaseVersion;
|
|
7
9
|
const fs_1 = __importDefault(require("fs"));
|
|
8
10
|
const os_1 = __importDefault(require("os"));
|
|
9
11
|
const path_1 = __importDefault(require("path"));
|
|
10
12
|
const child_process_1 = require("child_process");
|
|
11
13
|
const errors_1 = require("./errors");
|
|
12
14
|
const filesystem_1 = require("./filesystem");
|
|
13
|
-
|
|
15
|
+
const RELEASE_OWNER = "ymarrerot";
|
|
16
|
+
const RELEASE_REPO = "HIRMOS";
|
|
17
|
+
const RELEASE_ASSET = "hirmos-framework.zip";
|
|
18
|
+
function ensureHirmosInstalled(projectRoot, options) {
|
|
14
19
|
const hirmosDir = path_1.default.join(projectRoot, "_hirmos");
|
|
15
20
|
if ((0, filesystem_1.pathExists)(hirmosDir)) {
|
|
16
|
-
return;
|
|
21
|
+
return { installed: false, sourceDescription: null };
|
|
22
|
+
}
|
|
23
|
+
if (options.source) {
|
|
24
|
+
installFromSource(projectRoot, options.source);
|
|
25
|
+
return { installed: true, sourceDescription: options.source };
|
|
26
|
+
}
|
|
27
|
+
if (options.offline) {
|
|
28
|
+
(0, errors_1.fail)(`Missing _hirmos/ in ${projectRoot}. Offline mode requires an existing _hirmos/ or --source <path-to-hirmos-framework.zip-or-folder>.`);
|
|
17
29
|
}
|
|
18
|
-
|
|
19
|
-
|
|
30
|
+
const version = normalizeReleaseVersion(options.version);
|
|
31
|
+
const url = buildReleaseDownloadUrl(version);
|
|
32
|
+
const tmp = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), "hirmos-release-"));
|
|
33
|
+
const zipPath = path_1.default.join(tmp, RELEASE_ASSET);
|
|
34
|
+
try {
|
|
35
|
+
downloadFile(url, zipPath);
|
|
36
|
+
installFromZip(projectRoot, zipPath);
|
|
37
|
+
return { installed: true, sourceDescription: version === "latest" ? "latest GitHub release" : `GitHub release ${version}` };
|
|
20
38
|
}
|
|
39
|
+
finally {
|
|
40
|
+
fs_1.default.rmSync(tmp, { recursive: true, force: true });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function buildReleaseDownloadUrl(version) {
|
|
44
|
+
const normalized = normalizeReleaseVersion(version);
|
|
45
|
+
const overrideBase = process.env.HIRMOS_CLI_RELEASE_BASE_URL;
|
|
46
|
+
if (overrideBase) {
|
|
47
|
+
const trimmed = overrideBase.replace(/\/+$/u, "");
|
|
48
|
+
return `${trimmed}/${normalized}/${RELEASE_ASSET}`;
|
|
49
|
+
}
|
|
50
|
+
if (normalized === "latest") {
|
|
51
|
+
return `https://github.com/${RELEASE_OWNER}/${RELEASE_REPO}/releases/latest/download/${RELEASE_ASSET}`;
|
|
52
|
+
}
|
|
53
|
+
return `https://github.com/${RELEASE_OWNER}/${RELEASE_REPO}/releases/download/${normalized}/${RELEASE_ASSET}`;
|
|
54
|
+
}
|
|
55
|
+
function normalizeReleaseVersion(version) {
|
|
56
|
+
const trimmed = version.trim();
|
|
57
|
+
if (!trimmed || trimmed === "latest")
|
|
58
|
+
return "latest";
|
|
59
|
+
return trimmed.startsWith("v") ? trimmed : `v${trimmed}`;
|
|
60
|
+
}
|
|
61
|
+
function installFromSource(projectRoot, source) {
|
|
21
62
|
if (!(0, filesystem_1.pathExists)(source)) {
|
|
22
63
|
(0, errors_1.fail)(`Source path does not exist: ${source}`);
|
|
23
64
|
}
|
|
@@ -46,11 +87,11 @@ function installFromZip(projectRoot, zipPath) {
|
|
|
46
87
|
extractZip(zipPath, tmp);
|
|
47
88
|
}
|
|
48
89
|
catch (error) {
|
|
49
|
-
(0, errors_1.fail)(`Unable to extract
|
|
90
|
+
(0, errors_1.fail)(`Unable to extract framework zip. Ensure the zip is valid and an extraction command is available: ${error.message}`);
|
|
50
91
|
}
|
|
51
92
|
const sourceHirmos = findHirmosDir(tmp);
|
|
52
93
|
if (!sourceHirmos) {
|
|
53
|
-
(0, errors_1.fail)(`
|
|
94
|
+
(0, errors_1.fail)(`Framework zip does not contain an _hirmos/ folder: ${zipPath}`);
|
|
54
95
|
}
|
|
55
96
|
copyHirmos(projectRoot, sourceHirmos);
|
|
56
97
|
}
|
|
@@ -79,6 +120,16 @@ function copyHirmos(projectRoot, sourceHirmos) {
|
|
|
79
120
|
}
|
|
80
121
|
(0, filesystem_1.ensureDir)(projectRoot);
|
|
81
122
|
fs_1.default.cpSync(sourceHirmos, target, { recursive: true, errorOnExist: true });
|
|
123
|
+
validateCopiedHirmos(projectRoot);
|
|
124
|
+
}
|
|
125
|
+
function validateCopiedHirmos(projectRoot) {
|
|
126
|
+
const required = ["_hirmos/HIRMOS_CORE.md", "_hirmos/VERSION", "_hirmos/project.json"];
|
|
127
|
+
for (const relative of required) {
|
|
128
|
+
if (!(0, filesystem_1.pathExists)(path_1.default.join(projectRoot, relative))) {
|
|
129
|
+
fs_1.default.rmSync(path_1.default.join(projectRoot, "_hirmos"), { recursive: true, force: true });
|
|
130
|
+
(0, errors_1.fail)(`Installed framework is incomplete; missing ${relative}. Removed partial _hirmos/ install.`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
82
133
|
}
|
|
83
134
|
function extractZip(zipPath, destination) {
|
|
84
135
|
if (process.platform === "win32") {
|
|
@@ -87,3 +138,26 @@ function extractZip(zipPath, destination) {
|
|
|
87
138
|
}
|
|
88
139
|
(0, child_process_1.execFileSync)("unzip", ["-q", zipPath, "-d", destination], { stdio: "ignore" });
|
|
89
140
|
}
|
|
141
|
+
function downloadFile(url, destination) {
|
|
142
|
+
(0, filesystem_1.ensureDir)(path_1.default.dirname(destination));
|
|
143
|
+
try {
|
|
144
|
+
if (process.platform === "win32") {
|
|
145
|
+
(0, child_process_1.execFileSync)("powershell", [
|
|
146
|
+
"-NoProfile",
|
|
147
|
+
"-Command",
|
|
148
|
+
"$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest -Uri $args[0] -OutFile $args[1]",
|
|
149
|
+
url,
|
|
150
|
+
destination
|
|
151
|
+
], { stdio: "ignore" });
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
(0, child_process_1.execFileSync)("curl", ["-fL", "--retry", "2", "--connect-timeout", "20", "--max-time", "120", "-o", destination, url], { stdio: "ignore" });
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
(0, errors_1.fail)(`Unable to download HIRMOS release from ${url}. Use --source for a local release package or --offline to disable downloads. ${error.message}`);
|
|
159
|
+
}
|
|
160
|
+
if (!(0, filesystem_1.pathExists)(destination) || fs_1.default.statSync(destination).size === 0) {
|
|
161
|
+
(0, errors_1.fail)(`Downloaded HIRMOS release is empty or missing: ${destination}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getInstalledCliVersion = getInstalledCliVersion;
|
|
7
|
+
exports.normalizeSemver = normalizeSemver;
|
|
8
|
+
exports.compareSemver = compareSemver;
|
|
9
|
+
exports.buildUpdateNotice = buildUpdateNotice;
|
|
10
|
+
exports.formatUpdateNotice = formatUpdateNotice;
|
|
11
|
+
exports.getLatestPublishedVersion = getLatestPublishedVersion;
|
|
12
|
+
exports.getUpdateNotice = getUpdateNotice;
|
|
13
|
+
const fs_1 = __importDefault(require("fs"));
|
|
14
|
+
const path_1 = __importDefault(require("path"));
|
|
15
|
+
const child_process_1 = require("child_process");
|
|
16
|
+
const PACKAGE_NAME = "hirmos";
|
|
17
|
+
const DEFAULT_TIMEOUT_MS = 1500;
|
|
18
|
+
const ANSI_BOLD = "\u001b[1m";
|
|
19
|
+
const ANSI_YELLOW = "\u001b[33m";
|
|
20
|
+
const ANSI_RESET = "\u001b[0m";
|
|
21
|
+
function getInstalledCliVersion(cliRoot = path_1.default.resolve(__dirname, "../..")) {
|
|
22
|
+
try {
|
|
23
|
+
const packageJsonPath = path_1.default.join(cliRoot, "package.json");
|
|
24
|
+
const raw = fs_1.default.readFileSync(packageJsonPath, "utf8");
|
|
25
|
+
const parsed = JSON.parse(raw);
|
|
26
|
+
return typeof parsed.version === "string" && parsed.version.trim() ? parsed.version.trim() : null;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function normalizeSemver(value) {
|
|
33
|
+
return value.trim().replace(/^v/u, "").split("-")[0];
|
|
34
|
+
}
|
|
35
|
+
function compareSemver(left, right) {
|
|
36
|
+
const leftParts = normalizeSemver(left).split(".").map((part) => Number.parseInt(part, 10));
|
|
37
|
+
const rightParts = normalizeSemver(right).split(".").map((part) => Number.parseInt(part, 10));
|
|
38
|
+
for (let i = 0; i < 3; i += 1) {
|
|
39
|
+
const leftValue = Number.isFinite(leftParts[i]) ? leftParts[i] : 0;
|
|
40
|
+
const rightValue = Number.isFinite(rightParts[i]) ? rightParts[i] : 0;
|
|
41
|
+
if (leftValue > rightValue)
|
|
42
|
+
return 1;
|
|
43
|
+
if (leftValue < rightValue)
|
|
44
|
+
return -1;
|
|
45
|
+
}
|
|
46
|
+
return 0;
|
|
47
|
+
}
|
|
48
|
+
function buildUpdateNotice(currentVersion, latestVersion) {
|
|
49
|
+
if (!currentVersion || !latestVersion)
|
|
50
|
+
return null;
|
|
51
|
+
if (compareSemver(latestVersion, currentVersion) <= 0)
|
|
52
|
+
return null;
|
|
53
|
+
return `A newer HIRMOS CLI is available: ${latestVersion}.\nUpdate with: npm install -g ${PACKAGE_NAME}@latest`;
|
|
54
|
+
}
|
|
55
|
+
function formatUpdateNotice(message, useColor = Boolean(process.stderr.isTTY) && process.env.NO_COLOR === undefined) {
|
|
56
|
+
return useColor ? `${ANSI_BOLD}${ANSI_YELLOW}${message}${ANSI_RESET}` : message;
|
|
57
|
+
}
|
|
58
|
+
function getLatestPublishedVersion(timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
59
|
+
if (process.env.HIRMOS_CLI_UPDATE_CHECK === "0" || process.env.HIRMOS_NO_UPDATE_CHECK === "1") {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
const result = (0, child_process_1.spawnSync)("npm", ["view", PACKAGE_NAME, "version", "--silent"], {
|
|
64
|
+
encoding: "utf8",
|
|
65
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
66
|
+
timeout: timeoutMs
|
|
67
|
+
});
|
|
68
|
+
if (result.error || result.status !== 0)
|
|
69
|
+
return null;
|
|
70
|
+
const version = String(result.stdout ?? "").trim();
|
|
71
|
+
return /^v?\d+\.\d+\.\d+(?:[-+][A-Za-z0-9.-]+)?$/u.test(version) ? version : null;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function getUpdateNotice() {
|
|
78
|
+
return buildUpdateNotice(getInstalledCliVersion(), getLatestPublishedVersion());
|
|
79
|
+
}
|