hermes-agent 0.14.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 ADDED
@@ -0,0 +1,111 @@
1
+ # hermes-agent npm package
2
+
3
+ This repository publishes the npm bridge for
4
+ [NousResearch/Hermes-Agent](https://github.com/NousResearch/Hermes-Agent).
5
+
6
+ The npm package name is:
7
+
8
+ ```bash
9
+ hermes-agent
10
+ ```
11
+
12
+ The installed commands are:
13
+
14
+ ```bash
15
+ hermes
16
+ hermes-agent
17
+ ```
18
+
19
+ The npm package name `hermes` is already owned by another package on npm, so this
20
+ repository publishes `hermes-agent` and exposes `hermes` as a CLI binary.
21
+
22
+ ## Install
23
+
24
+ Prerequisites:
25
+
26
+ - Node.js 20 or newer
27
+ - Python 3.11 or newer
28
+ - pip available for that Python installation
29
+
30
+ Install globally:
31
+
32
+ ```bash
33
+ npm install -g hermes-agent
34
+ ```
35
+
36
+ Use it:
37
+
38
+ ```bash
39
+ hermes --help
40
+ hermes-agent --help
41
+ ```
42
+
43
+ During npm installation, `postinstall` installs the matching Python package:
44
+
45
+ ```bash
46
+ python -m pip install --upgrade hermes-agent==<npm package version>
47
+ ```
48
+
49
+ ## Automated publishing
50
+
51
+ `.github/workflows/npm-publish.yml` runs:
52
+
53
+ - manually with `workflow_dispatch`
54
+ - daily on a schedule
55
+ - when a tag matching `npm-v*` is pushed
56
+
57
+ The workflow:
58
+
59
+ 1. Fetches the current Hermes Agent version from upstream `pyproject.toml`.
60
+ 2. Updates `package.json` in the workflow workspace.
61
+ 3. Skips publishing if `hermes-agent@<version>` already exists on npm.
62
+ 4. Runs `npm test`.
63
+ 5. Runs `npm pack --dry-run`.
64
+ 6. Publishes to npm with the `NPM_TOKEN` GitHub Actions secret.
65
+
66
+ ## GitHub setup
67
+
68
+ Create a GitHub repository named:
69
+
70
+ ```text
71
+ hermes-agent-npm
72
+ ```
73
+
74
+ Create a classic or automation npm token with publish access, then add it as a
75
+ GitHub Actions secret:
76
+
77
+ ```text
78
+ Repository -> Settings -> Secrets and variables -> Actions -> New repository secret
79
+ Name: NPM_TOKEN
80
+ Value: your npm token
81
+ ```
82
+
83
+ After the first package version exists on npm, this repository can be switched
84
+ back to npm trusted publishing if desired:
85
+
86
+ ```text
87
+ npm package: hermes-agent
88
+ publisher: GitHub Actions
89
+ organization or user: wyrtensi
90
+ repository: hermes-agent-npm
91
+ workflow filename: npm-publish.yml
92
+ allowed action: npm publish
93
+ ```
94
+
95
+ Then push this repository:
96
+
97
+ ```bash
98
+ git remote add origin git@github.com:wyrtensi/hermes-agent-npm.git
99
+ git push -u origin main
100
+ ```
101
+
102
+ After that, open GitHub Actions and run `Publish npm package` manually for the
103
+ first publish.
104
+
105
+ ## Local checks
106
+
107
+ ```bash
108
+ python scripts/sync_upstream_version.py
109
+ npm test
110
+ npm pack --dry-run
111
+ ```
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { runHermes } = require("../lib/python-launcher");
4
+
5
+ runHermes(process.argv[1], process.argv.slice(2));
@@ -0,0 +1,99 @@
1
+ const { spawn, spawnSync } = require("node:child_process");
2
+ const path = require("node:path");
3
+
4
+ const packageJson = require("../package.json");
5
+
6
+ function getPythonCandidates(platform = process.platform) {
7
+ if (platform === "win32") {
8
+ return [
9
+ { command: "py", args: ["-3"] },
10
+ { command: "python", args: [] },
11
+ { command: "python3", args: [] }
12
+ ];
13
+ }
14
+
15
+ return [
16
+ { command: "python3", args: [] },
17
+ { command: "python", args: [] }
18
+ ];
19
+ }
20
+
21
+ function findPython(candidates = getPythonCandidates()) {
22
+ for (const candidate of candidates) {
23
+ const result = spawnSync(
24
+ candidate.command,
25
+ [...candidate.args, "-c", "import sys; raise SystemExit(0 if sys.version_info >= (3, 11) else 1)"],
26
+ { encoding: "utf8", windowsHide: true }
27
+ );
28
+
29
+ if (result.status === 0) {
30
+ return candidate;
31
+ }
32
+ }
33
+
34
+ return null;
35
+ }
36
+
37
+ function normalizeBinName(binName) {
38
+ const baseName = path.basename(binName || "hermes-agent").toLowerCase();
39
+ return baseName.replace(/(\.cmd|\.exe)$/i, "");
40
+ }
41
+
42
+ function getPythonEntryPoint(binName) {
43
+ return normalizeBinName(binName) === "hermes" ? "hermes_cli.main" : "run_agent";
44
+ }
45
+
46
+ function getPythonCode(binName) {
47
+ const moduleName = getPythonEntryPoint(binName);
48
+ return `from ${moduleName} import main; raise SystemExit(main())`;
49
+ }
50
+
51
+ function buildPythonInvocation(candidate, binName, userArgs) {
52
+ return {
53
+ command: candidate.command,
54
+ args: [...candidate.args, "-c", getPythonCode(binName), ...userArgs]
55
+ };
56
+ }
57
+
58
+ function getPythonPackageSpec() {
59
+ const version = packageJson.hermesAgent?.pythonPackageVersion || packageJson.version;
60
+ return `hermes-agent==${version}`;
61
+ }
62
+
63
+ function runHermes(binName, userArgs, stdio = "inherit") {
64
+ const candidate = findPython();
65
+
66
+ if (!candidate) {
67
+ console.error("Hermes Agent requires Python 3.11 or newer.");
68
+ console.error("Install Python, then run: python -m pip install --upgrade " + getPythonPackageSpec());
69
+ return 1;
70
+ }
71
+
72
+ const invocation = buildPythonInvocation(candidate, binName, userArgs);
73
+ const child = spawn(invocation.command, invocation.args, { stdio, windowsHide: false });
74
+
75
+ child.on("exit", (code, signal) => {
76
+ if (signal) {
77
+ process.kill(process.pid, signal);
78
+ return;
79
+ }
80
+
81
+ process.exit(code ?? 1);
82
+ });
83
+
84
+ child.on("error", (error) => {
85
+ console.error(error.message);
86
+ process.exit(1);
87
+ });
88
+
89
+ return 0;
90
+ }
91
+
92
+ module.exports = {
93
+ buildPythonInvocation,
94
+ findPython,
95
+ getPythonCandidates,
96
+ getPythonEntryPoint,
97
+ getPythonPackageSpec,
98
+ runHermes
99
+ };
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "hermes-agent",
3
+ "version": "0.14.0",
4
+ "description": "npm bridge for Hermes Agent 0.14.0: The self-improving AI agent \u2014 creates skills from experience, improves them during use, and runs anywhere",
5
+ "license": "MIT",
6
+ "type": "commonjs",
7
+ "bin": {
8
+ "hermes": "bin/hermes-agent.js",
9
+ "hermes-agent": "bin/hermes-agent.js"
10
+ },
11
+ "scripts": {
12
+ "postinstall": "node scripts/postinstall.js",
13
+ "test": "node --test"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/wyrtensi/hermes-agent-npm.git"
18
+ },
19
+ "bugs": {
20
+ "url": "https://github.com/NousResearch/Hermes-Agent/issues"
21
+ },
22
+ "homepage": "https://github.com/NousResearch/Hermes-Agent#readme",
23
+ "engines": {
24
+ "node": ">=20.0.0"
25
+ },
26
+ "files": [
27
+ "bin/",
28
+ "lib/",
29
+ "scripts/postinstall.js",
30
+ "README.md"
31
+ ],
32
+ "hermesAgent": {
33
+ "pythonPackageVersion": "0.14.0",
34
+ "upstreamRepository": "nousresearch/hermes-agent"
35
+ }
36
+ }
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { spawnSync } = require("node:child_process");
4
+ const { findPython, getPythonPackageSpec } = require("../lib/python-launcher");
5
+
6
+ const candidate = findPython();
7
+ const packageSpec = getPythonPackageSpec();
8
+
9
+ if (!candidate) {
10
+ console.error("Hermes Agent requires Python 3.11 or newer.");
11
+ console.error(`Install Python, then run: python -m pip install --upgrade ${packageSpec}`);
12
+ process.exit(1);
13
+ }
14
+
15
+ function runPip(extraArgs) {
16
+ return spawnSync(
17
+ candidate.command,
18
+ [...candidate.args, "-m", "pip", "install", "--upgrade", ...extraArgs, packageSpec],
19
+ { stdio: "inherit", windowsHide: true }
20
+ );
21
+ }
22
+
23
+ let result = runPip([]);
24
+
25
+ if (result.status !== 0) {
26
+ console.warn("Global pip install failed; retrying with --user.");
27
+ result = runPip(["--user"]);
28
+ }
29
+
30
+ if (result.status !== 0) {
31
+ console.error(`Failed to install ${packageSpec}.`);
32
+ process.exit(result.status || 1);
33
+ }