hirmos 1.3.0 → 1.3.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 +21 -6
- package/dist/commands/init.js +10 -3
- package/dist/index.js +3 -1
- package/dist/lib/args.js +29 -3
- package/dist/lib/source-install.js +80 -6
- 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,24 @@ 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
|
+
|
|
49
64
|
## Supported integrations
|
|
50
65
|
|
|
51
66
|
```text
|
|
@@ -104,4 +119,4 @@ hirmos system-design
|
|
|
104
119
|
hirmos implementation
|
|
105
120
|
```
|
|
106
121
|
|
|
107
|
-
The CLI
|
|
122
|
+
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
|
@@ -15,7 +15,9 @@ function main() {
|
|
|
15
15
|
const summary = (0, init_1.runInit)({
|
|
16
16
|
projectPath: parsed.projectPath,
|
|
17
17
|
integrations: parsed.integrations,
|
|
18
|
-
source: parsed.source
|
|
18
|
+
source: parsed.source,
|
|
19
|
+
version: parsed.version,
|
|
20
|
+
offline: parsed.offline
|
|
19
21
|
});
|
|
20
22
|
process.stdout.write(summary);
|
|
21
23
|
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
|
+
}
|