nodus-wechat 0.6.1 → 0.7.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 +5 -3
- package/bin/nodus-wechat.js +63 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,6 +17,8 @@ npx nodus-wechat install-hermes
|
|
|
17
17
|
npx nodus-wechat install-openilink
|
|
18
18
|
npx nodus-wechat doctor
|
|
19
19
|
npx nodus-wechat start
|
|
20
|
+
npx nodus-wechat start --no-install
|
|
21
|
+
npx nodus-wechat start --no-hermes
|
|
20
22
|
npx nodus-wechat start --docker
|
|
21
23
|
npx nodus-wechat status
|
|
22
24
|
npx nodus-wechat logs
|
|
@@ -51,7 +53,8 @@ the official OpeniLink installer.
|
|
|
51
53
|
- Writes runtime `.env`, Docker Compose, webhook server, helper scripts, and the OpeniLink reply plugin.
|
|
52
54
|
- Stores gateway base URL, api key, model, Hermes paths, OpeniLink origin, webhook port, and runtime path.
|
|
53
55
|
- Checks Node.js, local configuration, Hermes files, runtime files, Python, OpeniLink CLI, optional Docker Compose availability, Hermes CLI availability, and WeChat app detection with `doctor`.
|
|
54
|
-
- Starts/stops the local
|
|
56
|
+
- Starts/stops Hermes Gateway, OpeniLink, and the local webhook with native host processes by default.
|
|
57
|
+
- Installs Hermes and OpeniLink automatically during `start` when the native CLIs are missing.
|
|
55
58
|
- Keeps Docker Compose available only when `--docker` is passed.
|
|
56
59
|
- Removes Nodus WeChat config/runtime files with `uninstall --yes`.
|
|
57
60
|
- Cleans Nodus WeChat config/runtime plus generated Hermes settings with `clean --yes`.
|
|
@@ -75,9 +78,8 @@ the config generated by this CLI.
|
|
|
75
78
|
|
|
76
79
|
## Current non-goals
|
|
77
80
|
|
|
78
|
-
- Does not run a third-party installer unless `--install-hermes`, `install-hermes`, or `install-openilink` is explicitly requested.
|
|
79
81
|
- Does not automate, inject into, read, or control WeChat directly.
|
|
80
|
-
- Does not
|
|
82
|
+
- Does not install a LaunchAgent or system service; `start` uses managed host processes that `stop` can terminate.
|
|
81
83
|
- Does not redeem real CDKs or mutate sub2api accounts; the bundled webhook keeps the existing dry-run POC boundary.
|
|
82
84
|
|
|
83
85
|
## Runtime wiring
|
package/bin/nodus-wechat.js
CHANGED
|
@@ -8,7 +8,7 @@ const os = require("node:os");
|
|
|
8
8
|
const path = require("node:path");
|
|
9
9
|
const childProcess = require("node:child_process");
|
|
10
10
|
|
|
11
|
-
const VERSION = "0.
|
|
11
|
+
const VERSION = "0.7.0";
|
|
12
12
|
const DEFAULT_BASE_URL = "https://api.nodus.sbs/";
|
|
13
13
|
const DEFAULT_MODEL = "gpt-5.5";
|
|
14
14
|
const DEFAULT_OPENILINK_ORIGIN = "http://localhost:9800";
|
|
@@ -43,7 +43,7 @@ Usage:
|
|
|
43
43
|
nodus-wechat install-hermes
|
|
44
44
|
nodus-wechat install-openilink
|
|
45
45
|
nodus-wechat doctor
|
|
46
|
-
nodus-wechat start [--docker]
|
|
46
|
+
nodus-wechat start [--docker] [--no-install] [--no-hermes]
|
|
47
47
|
nodus-wechat status [--docker]
|
|
48
48
|
nodus-wechat logs [--docker]
|
|
49
49
|
nodus-wechat stop [--docker]
|
|
@@ -56,7 +56,7 @@ Commands:
|
|
|
56
56
|
install-openilink
|
|
57
57
|
Install OpeniLink Hub native CLI with the official installer.
|
|
58
58
|
doctor Check local prerequisites and configuration.
|
|
59
|
-
start Start OpeniLink
|
|
59
|
+
start Start Hermes Gateway, OpeniLink, and webhook on the host by default.
|
|
60
60
|
status Show local process status.
|
|
61
61
|
logs Follow local runtime logs.
|
|
62
62
|
stop Stop the local runtime.
|
|
@@ -78,7 +78,7 @@ function parseArgs(argv) {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
const key = item.slice(2);
|
|
81
|
-
if (key === "help" || key === "yes" || key === "install-hermes" || key === "docker") {
|
|
81
|
+
if (key === "help" || key === "yes" || key === "install-hermes" || key === "docker" || key === "no-install" || key === "no-hermes") {
|
|
82
82
|
result[key] = true;
|
|
83
83
|
continue;
|
|
84
84
|
}
|
|
@@ -377,7 +377,7 @@ function setup(options) {
|
|
|
377
377
|
console.log(`OpeniLink Hub: ${config.openilink.publicOrigin}`);
|
|
378
378
|
console.log(`Webhook URL for OpeniLink: http://poc-webhook:${config.webhook.port}/webhook`);
|
|
379
379
|
console.log("Runtime mode: host process by default; Docker is used only with `--docker`.");
|
|
380
|
-
console.log("Run `nodus-wechat start` to start the local host runtime.");
|
|
380
|
+
console.log("Run `nodus-wechat start` to start Hermes Gateway plus the local host runtime.");
|
|
381
381
|
}
|
|
382
382
|
|
|
383
383
|
function installHermes() {
|
|
@@ -519,6 +519,16 @@ function commandPath(name) {
|
|
|
519
519
|
return result.stdout.trim() || null;
|
|
520
520
|
}
|
|
521
521
|
|
|
522
|
+
function hermesPath(config) {
|
|
523
|
+
return (
|
|
524
|
+
commandPath("hermes") ||
|
|
525
|
+
(fs.existsSync(path.join(os.homedir(), ".local", "bin", "hermes")) ? path.join(os.homedir(), ".local", "bin", "hermes") : null) ||
|
|
526
|
+
(config?.hermes?.home && fs.existsSync(path.join(config.hermes.home, "hermes-agent", "venv", "bin", "hermes"))
|
|
527
|
+
? path.join(config.hermes.home, "hermes-agent", "venv", "bin", "hermes")
|
|
528
|
+
: null)
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
|
|
522
532
|
function runtimePath(config, name) {
|
|
523
533
|
return path.join(config.runtime.dir, name);
|
|
524
534
|
}
|
|
@@ -597,6 +607,7 @@ function localRuntimeEnv(config) {
|
|
|
597
607
|
return {
|
|
598
608
|
...process.env,
|
|
599
609
|
...env,
|
|
610
|
+
HERMES_HOME: config.hermes?.home || hermesHome(),
|
|
600
611
|
LISTEN: `:${config.openilink?.port || DEFAULT_OPENILINK_PORT}`,
|
|
601
612
|
RP_ORIGIN: config.openilink?.publicOrigin || DEFAULT_OPENILINK_ORIGIN,
|
|
602
613
|
RP_ID: config.openilink?.rpId || DEFAULT_OPENILINK_RP_ID,
|
|
@@ -670,7 +681,7 @@ function startDocker() {
|
|
|
670
681
|
return runDockerCompose(config, ["up", "-d"]);
|
|
671
682
|
}
|
|
672
683
|
|
|
673
|
-
function startLocal() {
|
|
684
|
+
function startLocal(options) {
|
|
674
685
|
const config = loadRuntimeConfig();
|
|
675
686
|
if (!config) {
|
|
676
687
|
return 1;
|
|
@@ -682,24 +693,61 @@ function startLocal() {
|
|
|
682
693
|
return 1;
|
|
683
694
|
}
|
|
684
695
|
|
|
685
|
-
|
|
696
|
+
let hermes = options["no-hermes"] ? null : hermesPath(config);
|
|
697
|
+
if (!hermes && !options["no-hermes"]) {
|
|
698
|
+
if (options["no-install"]) {
|
|
699
|
+
console.error("Hermes CLI `hermes` is not installed.");
|
|
700
|
+
console.error("Run: nodus-wechat install-hermes");
|
|
701
|
+
return 1;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
console.log("Hermes CLI `hermes` is not installed; installing it now.");
|
|
705
|
+
runHermesInstaller(config.hermes?.home || hermesHome());
|
|
706
|
+
hermes = hermesPath(config);
|
|
707
|
+
if (!hermes) {
|
|
708
|
+
console.error("Hermes installer completed, but `hermes` is still not on PATH.");
|
|
709
|
+
console.error("Open a new terminal or add the installed Hermes path to PATH, then rerun `nodus-wechat start`.");
|
|
710
|
+
return 1;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
let oih = commandPath("oih");
|
|
686
715
|
if (!oih) {
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
716
|
+
if (options["no-install"]) {
|
|
717
|
+
console.error("OpeniLink Hub CLI `oih` is not installed.");
|
|
718
|
+
console.error("Run: nodus-wechat install-openilink");
|
|
719
|
+
return 1;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
console.log("OpeniLink Hub CLI `oih` is not installed; installing it now.");
|
|
723
|
+
const installResult = installOpeniLink();
|
|
724
|
+
if (installResult !== 0) {
|
|
725
|
+
return installResult;
|
|
726
|
+
}
|
|
727
|
+
oih = commandPath("oih");
|
|
728
|
+
if (!oih) {
|
|
729
|
+
console.error("OpeniLink installer completed, but `oih` is still not on PATH.");
|
|
730
|
+
console.error("Open a new terminal or add the installed OpeniLink path to PATH, then rerun `nodus-wechat start`.");
|
|
731
|
+
return 1;
|
|
732
|
+
}
|
|
690
733
|
}
|
|
691
734
|
|
|
692
735
|
const env = localRuntimeEnv(config);
|
|
693
736
|
const webhookPath = path.join(config.runtime.dir, "poc-webhook", "server.py");
|
|
694
737
|
startManagedProcess(config, "webhook", python, [webhookPath], env);
|
|
695
738
|
startManagedProcess(config, "openilink", oih, [], env);
|
|
739
|
+
if (hermes) {
|
|
740
|
+
startManagedProcess(config, "hermes", hermes, ["gateway", "run"], env);
|
|
741
|
+
} else {
|
|
742
|
+
console.log("hermes: skipped (--no-hermes)");
|
|
743
|
+
}
|
|
696
744
|
console.log(`OpeniLink Hub: ${config.openilink?.publicOrigin || DEFAULT_OPENILINK_ORIGIN}`);
|
|
697
745
|
console.log(`Webhook health: http://127.0.0.1:${config.webhook?.port || DEFAULT_WEBHOOK_PORT}/health`);
|
|
698
746
|
return 0;
|
|
699
747
|
}
|
|
700
748
|
|
|
701
749
|
function start(options) {
|
|
702
|
-
return options.docker ? startDocker() : startLocal();
|
|
750
|
+
return options.docker ? startDocker() : startLocal(options);
|
|
703
751
|
}
|
|
704
752
|
|
|
705
753
|
function statusDocker() {
|
|
@@ -717,7 +765,7 @@ async function statusLocal() {
|
|
|
717
765
|
return 1;
|
|
718
766
|
}
|
|
719
767
|
|
|
720
|
-
for (const name of ["openilink", "webhook"]) {
|
|
768
|
+
for (const name of ["hermes", "openilink", "webhook"]) {
|
|
721
769
|
const pid = readPid(pidPath(config, name));
|
|
722
770
|
console.log(`${name}: ${processRunning(pid) ? `running (pid ${pid})` : "stopped"}`);
|
|
723
771
|
}
|
|
@@ -745,7 +793,7 @@ function logsLocal() {
|
|
|
745
793
|
return 1;
|
|
746
794
|
}
|
|
747
795
|
|
|
748
|
-
const files = ["openilink", "webhook"].map((name) => logPath(config, name)).filter((filePath) => fs.existsSync(filePath));
|
|
796
|
+
const files = ["hermes", "openilink", "webhook"].map((name) => logPath(config, name)).filter((filePath) => fs.existsSync(filePath));
|
|
749
797
|
if (files.length === 0) {
|
|
750
798
|
console.error("No local runtime logs found.");
|
|
751
799
|
return 1;
|
|
@@ -785,6 +833,7 @@ function stopLocal() {
|
|
|
785
833
|
|
|
786
834
|
stopManagedProcess(config, "webhook");
|
|
787
835
|
stopManagedProcess(config, "openilink");
|
|
836
|
+
stopManagedProcess(config, "hermes");
|
|
788
837
|
return 0;
|
|
789
838
|
}
|
|
790
839
|
|
|
@@ -842,7 +891,7 @@ function clean(options) {
|
|
|
842
891
|
|
|
843
892
|
const config = fs.existsSync(configPath()) ? readConfig() : null;
|
|
844
893
|
if (config) {
|
|
845
|
-
for (const name of ["webhook", "openilink"]) {
|
|
894
|
+
for (const name of ["webhook", "openilink", "hermes"]) {
|
|
846
895
|
stopManagedProcess({ ...config, runtime: { ...config.runtime, dir: config.runtime?.dir || path.join(configHome(), "runtime") } }, name);
|
|
847
896
|
}
|
|
848
897
|
const docker = dockerComposeAvailable();
|