nodus-wechat 0.5.0 → 0.5.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 CHANGED
@@ -20,6 +20,7 @@ npx nodus-wechat status
20
20
  npx nodus-wechat logs
21
21
  npx nodus-wechat stop
22
22
  npx nodus-wechat uninstall --yes
23
+ npx nodus-wechat clean --yes
23
24
  ```
24
25
 
25
26
  For a server-bound OpeniLink origin:
@@ -46,7 +47,25 @@ with `--skip-setup` and the same Hermes home used by this CLI.
46
47
  - Stores gateway base URL, api key, model, Hermes paths, OpeniLink origin, webhook port, and runtime path.
47
48
  - Checks Node.js, local configuration, Hermes files, runtime files, Docker Compose availability, Hermes CLI availability, and WeChat app detection with `doctor`.
48
49
  - Starts/stops the local runtime through Docker Compose.
49
- - Removes only files created by this CLI with `uninstall --yes`.
50
+ - Removes Nodus WeChat config/runtime files with `uninstall --yes`.
51
+ - Cleans Nodus WeChat config/runtime plus generated Hermes settings with `clean --yes`.
52
+
53
+ ## Uninstall and clean
54
+
55
+ ```sh
56
+ npx nodus-wechat stop
57
+ npx nodus-wechat uninstall --yes
58
+ ```
59
+
60
+ Use `clean --yes` when you also want to remove the generated Hermes settings:
61
+
62
+ ```sh
63
+ npx nodus-wechat clean --yes
64
+ ```
65
+
66
+ `clean --yes` removes `~/.nodus-wechat`, removes `ASTRAGATE_API_KEY` from
67
+ `~/.hermes/.env`, and removes `~/.hermes/config.yaml` only when it still matches
68
+ the config generated by this CLI.
50
69
 
51
70
  ## Current non-goals
52
71
 
@@ -7,7 +7,7 @@ const os = require("node:os");
7
7
  const path = require("node:path");
8
8
  const childProcess = require("node:child_process");
9
9
 
10
- const VERSION = "0.5";
10
+ const VERSION = "0.5.2";
11
11
  const DEFAULT_BASE_URL = "https://api.nodus.sbs/";
12
12
  const DEFAULT_MODEL = "gpt-5.5";
13
13
  const DEFAULT_OPENILINK_ORIGIN = "http://localhost:9800";
@@ -34,6 +34,7 @@ function printHelp() {
34
34
  Local CLI installer for Nodus WeChat, Hermes settings, and the OpeniLink webhook runtime.
35
35
 
36
36
  Usage:
37
+ nodus-wechat [--api-key <key>] [--base-url <url>] [--model <model>]
37
38
  nodus-wechat setup [--api-key <key>] [--base-url <url>] [--model <model>]
38
39
  [--runtime-dir <path>] [--openilink-origin <url>]
39
40
  [--openilink-rp-id <id>] [--webhook-port <port>]
@@ -45,16 +46,18 @@ Usage:
45
46
  nodus-wechat logs
46
47
  nodus-wechat stop
47
48
  nodus-wechat uninstall --yes
49
+ nodus-wechat clean --yes
48
50
 
49
51
  Commands:
50
- setup Create or update local configuration and runtime files.
52
+ setup Create or update local configuration and runtime files. This is the default.
51
53
  install-hermes Install Hermes Agent CLI with the official installer.
52
54
  doctor Check local prerequisites and configuration.
53
55
  start Start the local OpeniLink + webhook runtime with Docker Compose.
54
56
  status Show Docker Compose service status.
55
57
  logs Follow webhook logs.
56
58
  stop Stop the local runtime.
57
- uninstall Remove files created by this CLI.
59
+ uninstall Remove Nodus WeChat config and runtime files.
60
+ clean Stop runtime if possible, then remove Nodus WeChat files and generated Hermes settings.
58
61
 
59
62
  This version installs an OpeniLink webhook POC runtime. It does not inject into,
60
63
  read, or control WeChat directly.`);
@@ -555,6 +558,61 @@ function uninstall(options) {
555
558
  return 0;
556
559
  }
557
560
 
561
+ function removeHermesApiKey(envPath) {
562
+ if (!fs.existsSync(envPath)) {
563
+ return "missing";
564
+ }
565
+
566
+ const lines = fs.readFileSync(envPath, "utf8").split(/\r?\n/);
567
+ const kept = lines.filter((line) => line && !line.startsWith("ASTRAGATE_API_KEY="));
568
+ if (kept.length === 0) {
569
+ fs.rmSync(envPath, { force: true });
570
+ return "removed";
571
+ }
572
+
573
+ fs.writeFileSync(envPath, `${kept.join("\n")}\n`, { mode: 0o600 });
574
+ return "updated";
575
+ }
576
+
577
+ function removeGeneratedHermesConfig(config) {
578
+ const hermesConfigPath = config.hermes?.configPath || path.join(hermesHome(), "config.yaml");
579
+ if (!fs.existsSync(hermesConfigPath)) {
580
+ return "missing";
581
+ }
582
+
583
+ const current = fs.readFileSync(hermesConfigPath, "utf8");
584
+ if (current !== buildHermesConfig(config)) {
585
+ return "kept";
586
+ }
587
+
588
+ fs.rmSync(hermesConfigPath, { force: true });
589
+ return "removed";
590
+ }
591
+
592
+ function clean(options) {
593
+ if (!options.yes) {
594
+ console.error("Refusing to clean without --yes.");
595
+ return 1;
596
+ }
597
+
598
+ const config = fs.existsSync(configPath()) ? readConfig() : null;
599
+ if (config) {
600
+ const docker = dockerComposeAvailable();
601
+ if (docker.ok && config.runtime?.dir && fs.existsSync(path.join(config.runtime.dir, "docker-compose.yml"))) {
602
+ runDockerCompose(config, ["down"], "pipe");
603
+ }
604
+
605
+ const hermesConfigStatus = removeGeneratedHermesConfig(config);
606
+ const hermesEnvStatus = removeHermesApiKey(config.hermes?.envPath || path.join(hermesHome(), ".env"));
607
+ console.log(`Hermes config: ${hermesConfigStatus}`);
608
+ console.log(`Hermes env: ${hermesEnvStatus}`);
609
+ }
610
+
611
+ fs.rmSync(configHome(), { recursive: true, force: true });
612
+ console.log(`Removed: ${configHome()}`);
613
+ return 0;
614
+ }
615
+
558
616
  function main() {
559
617
  let args;
560
618
  try {
@@ -564,8 +622,8 @@ function main() {
564
622
  return 1;
565
623
  }
566
624
 
567
- const command = args._[0];
568
- if (!command || args.help || command === "help") {
625
+ const command = args._[0] || "setup";
626
+ if (args.help || command === "help") {
569
627
  printHelp();
570
628
  return 0;
571
629
  }
@@ -603,6 +661,10 @@ function main() {
603
661
  if (command === "uninstall") {
604
662
  return uninstall(args);
605
663
  }
664
+
665
+ if (command === "clean") {
666
+ return clean(args);
667
+ }
606
668
  } catch (error) {
607
669
  console.error(error.message);
608
670
  return 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodus-wechat",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "CLI installer for Nodus WeChat, Hermes, and the local OpeniLink webhook runtime.",
5
5
  "license": "MIT",
6
6
  "private": false,