mslxdff 0.1.20 → 0.1.22

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/bin/mslxdff.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import { execFile } from "node:child_process";
3
- import { readFileSync, existsSync, statSync } from "node:fs";
3
+ import { readFileSync, existsSync, statSync, rmSync } from "node:fs";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { dirname, join, basename } from "node:path";
6
6
  import { startServer, resolvePort } from "../src/server.js";
7
- import { DEFAULT_PORT } from "../src/state.js";
7
+ import { DEFAULT_PORT, defaultStateFile } from "../src/state.js";
8
8
  import { createRouter } from "../src/routes.js";
9
9
  import { createUpstreamClient } from "../src/upstream.js";
10
10
  import { createModelsService } from "../src/models.js";
@@ -54,6 +54,37 @@ if (args.includes("-stop") || args.includes("--stop")) {
54
54
  process.exit(0);
55
55
  }
56
56
 
57
+ if (args.includes("-uninstall") || args.includes("--uninstall")) {
58
+ const { stopped, pid } = stopDaemon();
59
+ if (stopped) console.log(`mslxdff daemon stopped (pid ${pid})`);
60
+ else console.log("mslxdff daemon not running");
61
+
62
+ const stateFile = defaultStateFile();
63
+ const dir = dirname(stateFile);
64
+ const removed = [];
65
+ for (const f of [
66
+ stateFile,
67
+ pidFile(),
68
+ logFile(),
69
+ join(dir, "calls.log"),
70
+ join(dir, "errors.log"),
71
+ join(dir, "events.log"),
72
+ ]) {
73
+ try {
74
+ rmSync(f, { force: true });
75
+ removed.push(f);
76
+ } catch {
77
+ // already gone, fine
78
+ }
79
+ }
80
+ if (removed.length) console.log(`removed ${removed.length} file(s):\n ${removed.join("\n ")}`);
81
+ else console.log("no state/log files to remove");
82
+
83
+ console.log("\npackage still installed — finish with:");
84
+ console.log(" npm uninstall -g mslxdff");
85
+ process.exit(0);
86
+ }
87
+
57
88
  if (args.includes("-status") || args.includes("--status") || args.includes("-s")) {
58
89
  await printStatus();
59
90
  process.exit(0);
@@ -604,6 +635,7 @@ Usage:
604
635
  mslxdff -model refresh force-refresh the model cache from the upstream
605
636
  mslxdff -debug live-follow the daemon event stream (requests, errors, peer forwards)
606
637
  mslxdff -stop stop the running daemon
638
+ mslxdff -uninstall stop the daemon and delete all state/log files
607
639
  mslxdff -port N persist the listen port (restarts the daemon on it if running)
608
640
  mslxdff -update update mslxdff to the latest published version
609
641
  mslxdff -showtoken print the current auth token
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mslxdff",
3
- "version": "0.1.20",
3
+ "version": "0.1.22",
4
4
  "description": "测试项目,请勿使用。",
5
5
  "type": "module",
6
6
  "bin": {
package/src/groups.js CHANGED
@@ -27,6 +27,20 @@ export function createGroup(name, { file, key = name } = {}) {
27
27
  return { name, key, created: true };
28
28
  }
29
29
 
30
+ // Shared writer: register a member, de-duplicated by url (same ip:port
31
+ // re-registering under a different name updates the existing entry instead of
32
+ // creating a duplicate).
33
+ function writeMember(group, memberName, url, token) {
34
+ const members = group.members || (group.members = {});
35
+ const byUrl = Object.entries(members).find(([, m]) => m.url === url);
36
+ if (byUrl) {
37
+ members[byUrl[0]] = { url, token: token || "" };
38
+ return;
39
+ }
40
+ const id = memberName || url;
41
+ members[id] = { url, token: token || "" };
42
+ }
43
+
30
44
  // Leader side: add a member after verifying the join key.
31
45
  export function addGroupMember(name, { key, memberName, url, token, file } = {}) {
32
46
  const groups = loadGroups(file ? { file } : {});
@@ -34,8 +48,7 @@ export function addGroupMember(name, { key, memberName, url, token, file } = {})
34
48
  if (!group) throw new Error(`group "${name}" not found on this node`);
35
49
  if (!verifyGroupKey(key, group.key)) throw new Error("invalid group key");
36
50
  if (!url) throw new Error("member url is required");
37
- const id = memberName || url;
38
- group.members[id] = { url, token: token || "" };
51
+ writeMember(group, memberName, url, token);
39
52
  saveGroups(groups, file ? { file } : {});
40
53
  return group.members;
41
54
  }
@@ -47,8 +60,7 @@ export function upsertMember(name, { memberName, url, token, file } = {}) {
47
60
  const group = groups[name];
48
61
  if (!group) return null;
49
62
  if (!url) throw new Error("member url is required");
50
- const id = memberName || url;
51
- group.members[id] = { url, token: token || "" };
63
+ writeMember(group, memberName, url, token);
52
64
  saveGroups(groups, file ? { file } : {});
53
65
  return group.members;
54
66
  }