panrouter 1.6.1 → 1.7.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.
Files changed (3) hide show
  1. package/cli.mjs +9 -14
  2. package/daemon.mjs +51 -33
  3. package/package.json +1 -1
package/cli.mjs CHANGED
@@ -140,17 +140,6 @@ async function startServer() {
140
140
 
141
141
  // ─── 4. 以托盘模式启动 ──────────────────────────────────────────────────
142
142
 
143
- /**
144
- * 启动 daemon (Node 常驻进程, 管理 server + PS tray)
145
- *
146
- * cli.mjs ─→ node daemon.mjs (detached, hidden)
147
- * ├─ 启动 server.mjs (子进程, detached, hidden)
148
- * └─ 启动 powershell tray-daemon.ps1 (子进程, hidden)
149
- * └─ 保持存活, 30s 健康检查
150
- *
151
- * key: 用 process.execPath (绝对路径) 启动
152
- * 避免 VBS/WScript/CMD 的 PATH 查找问题
153
- */
154
143
  function startTray() {
155
144
  const daemonPath = path.join(__dirname, "daemon.mjs");
156
145
 
@@ -170,9 +159,15 @@ function startTray() {
170
159
  });
171
160
  child.unref();
172
161
 
173
- log("OK", "Pan Router 托盘已启动", "green");
174
- console.log(" 图标出现在右下角后, 即可运行 claude");
175
- }
162
+ log("OK", "Pan Router 托盘服务已启动", "green");
163
+ console.log("");
164
+ console.log(" \x1b[33m实时查看日志:\x1b[0m");
165
+ console.log(" powershell -Command \"Get-Content -Wait -Tail 20 $env:TEMP\\panrouter-daemon.log\"");
166
+ console.log("");
167
+ console.log(" \x1b[33m查看全部日志:\x1b[0m");
168
+ console.log(" notepad %TEMP%\\panrouter-daemon.log");
169
+ console.log("");
170
+ console.log(" 若 10 秒后图标未出现,请查看日志并反馈");
176
171
 
177
172
  // ─── 主流程 ──────────────────────────────────────────────────────────────
178
173
 
package/daemon.mjs CHANGED
@@ -1,14 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * Pan Router Daemon (v4)
4
+ * Pan Router Daemon (v5)
5
5
  *
6
- * 一个 Node 进程同时:
7
- * 1. 隐藏启动 server.mjs(子进程)
8
- * 2. 隐藏启动 tray-daemon.ps1(子进程)
9
- * 3. 保持存活,守护两者
10
- *
11
- * 由 cli.mjs --tray 启动 (detached, 无窗口)。
6
+ * 1. spawn server.mjs (detached, hidden) — 正常
7
+ * 2. VBS 启动 PS tray(解决 detached 进程无法创建通知图标的问题)
8
+ * 3. 保持存活,30s 健康检查
12
9
  */
13
10
 
14
11
  import { spawn, execSync } from "node:child_process";
@@ -20,16 +17,15 @@ import http from "node:http";
20
17
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
21
18
  const serverPath = path.join(__dirname, "server.mjs");
22
19
  const trayPsPath = path.join(__dirname, "tray-daemon.ps1");
23
- const nodeExe = process.execPath; // ← 绝对路径!不依赖 PATH
20
+ const nodeExe = process.execPath;
24
21
  const logPath = path.join(process.env.TEMP || "/tmp", "panrouter-daemon.log");
25
22
 
26
23
  function log(msg) {
27
24
  try { fs.appendFileSync(logPath, `${new Date().toISOString().slice(11,19)} ${msg}\n`); } catch {}
28
25
  }
29
26
 
30
- log("=== Daemon v4 ===");
27
+ log("=== Daemon v5 ===");
31
28
  log(`nodeExe=${nodeExe}`);
32
- log(`serverPath=${serverPath}`);
33
29
 
34
30
  // ─── 1. 杀旧 server ──────────────────────────────
35
31
  try {
@@ -40,19 +36,14 @@ try {
40
36
  for (const line of out.split("\n")) {
41
37
  if (line.includes("server.mjs")) {
42
38
  const m = line.match(/(\d+),.*?server\.mjs/);
43
- if (m) { try { process.kill(parseInt(m[1]), "SIGKILL"); log(`Killed old server PID=${m[1]}`); } catch {} }
39
+ if (m) { try { process.kill(parseInt(m[1]), "SIGKILL"); log(`Killed old PID=${m[1]}`); } catch {} }
44
40
  }
45
41
  }
46
42
  } catch {}
47
43
 
48
44
  // ─── 2. 启动 server.mjs ──────────────────────────
49
- // 关键: 用 process.execPath (绝对路径), 不用 "node" (可能找不到 PATH)
50
45
  const server = spawn(nodeExe, [serverPath], {
51
- cwd: __dirname,
52
- stdio: "ignore",
53
- windowsHide: true,
54
- detached: true,
55
- shell: false,
46
+ cwd: __dirname, stdio: "ignore", windowsHide: true, detached: true, shell: false,
56
47
  });
57
48
  server.unref();
58
49
  log(`Server spawned PID=${server.pid || "??"}`);
@@ -77,29 +68,56 @@ function isOnline() {
77
68
  }
78
69
  log(`Server online=${ready}`);
79
70
 
80
- // ─── 4. 启动 PS 托盘 ────────────────────────────
71
+ // ─── 4. 用 VBS 启动 PS 托盘 ─────────────────────
72
+ log("Starting PS tray via VBS...");
73
+
81
74
  if (fs.existsSync(trayPsPath)) {
82
- log("Starting PS tray...");
83
- const ps = spawn("powershell.exe", [
84
- "-NoProfile", "-ExecutionPolicy", "Bypass",
85
- "-WindowStyle", "Hidden",
86
- "-File", trayPsPath,
87
- ], {
88
- stdio: "ignore",
89
- windowsHide: true,
90
- shell: false,
91
- });
92
- ps.unref();
93
- log(`PS spawned PID=${ps.pid || "??"}`);
75
+ log(`trayPsPath exists: ${trayPsPath}`);
76
+
77
+ // 创建临时的 VBS 启动器
78
+ const vbsContent = `Set WshShell = CreateObject("WScript.Shell")
79
+ Set FSO = CreateObject("Scripting.FileSystemObject")
80
+ ' 写诊断日志
81
+ On Error Resume Next
82
+ Dim f : Set f = FSO.OpenTextFile("${(process.env.TEMP || "/tmp").replace(/\\/g, "\\\\")}\\panrouter-vbs.log", 2, True)
83
+ f.WriteLine Now & " VBS started"
84
+ f.Close
85
+ ' 启动 PS 托盘
86
+ WshShell.Run "powershell -ExecutionPolicy Bypass -WindowStyle Hidden -STA -File """ & "${trayPsPath.replace(/\\/g, "\\\\")}" & """", 0, False
87
+ If Err.Number <> 0 Then
88
+ Set f = FSO.OpenTextFile("${(process.env.TEMP || "/tmp").replace(/\\/g, "\\\\")}\\panrouter-vbs.log", 8, True)
89
+ f.WriteLine Now & " ERROR: " & Err.Description
90
+ f.Close
91
+ End If
92
+ `;
93
+ const vbsPath = path.join(process.env.TEMP || "/tmp", "panrouter-tray-launcher.vbs");
94
+ try {
95
+ fs.writeFileSync(vbsPath, vbsContent, "utf8");
96
+ log(`VBS written: ${vbsPath}`);
97
+ } catch (e) {
98
+ log(`VBS write FAILED: ${e.message}`);
99
+ }
100
+
101
+ log(`VBS content:\n${vbsContent}`);
102
+
103
+ // 先试 wscript //B
104
+ try {
105
+ const vbs = spawn("wscript.exe", ["//B", "//NoLogo", vbsPath], {
106
+ stdio: "ignore", windowsHide: true, shell: false,
107
+ });
108
+ vbs.unref();
109
+ log(`VBS spawned via wscript`);
110
+ } catch (e) {
111
+ log(`VBS via wscript FAILED: ${e.message}`);
112
+ }
94
113
  } else {
95
- log(`WARN: tray-daemon.ps1 not found at ${trayPsPath}`);
114
+ log(`WARN: tray-daemon.ps1 NOT FOUND at ${trayPsPath}`);
96
115
  }
97
116
 
98
117
  // ─── 5. 保持存活 ────────────────────────────────
99
- log("Daemon running, keeping session alive");
118
+ log("Daemon running");
100
119
  process.stdin.resume();
101
120
 
102
- // 定时检查 server, 挂了就重启
103
121
  setInterval(() => {
104
122
  isOnline().then(ok => {
105
123
  if (!ok) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "panrouter",
3
- "version": "1.6.1",
3
+ "version": "1.7.1",
4
4
  "description": "让 Claude Code 免费使用 DeepSeek 等模型,无需 API Key",
5
5
  "type": "module",
6
6
  "bin": {