panrouter 1.6.0 → 1.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/daemon.mjs +27 -32
- package/package.json +1 -2
- package/tray-daemon.ps1 +39 -25
package/daemon.mjs
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Pan Router Daemon (
|
|
4
|
+
* Pan Router Daemon (v5)
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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;
|
|
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
|
|
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
|
|
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,33 @@ function isOnline() {
|
|
|
77
68
|
}
|
|
78
69
|
log(`Server online=${ready}`);
|
|
79
70
|
|
|
80
|
-
// ─── 4. 启动 PS 托盘
|
|
71
|
+
// ─── 4. 用 VBS 启动 PS 托盘 ─────────────────────
|
|
72
|
+
// 关键: spawn 的 detached 进程没有 Window Station 访问权限,
|
|
73
|
+
// 无法创建 NotifyIcon。WScript.Shell.Run 0 是可靠的解决方式。
|
|
81
74
|
if (fs.existsSync(trayPsPath)) {
|
|
82
|
-
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
75
|
+
// 创建临时的 VBS 启动器
|
|
76
|
+
const vbsContent = `Set WshShell = CreateObject("WScript.Shell")
|
|
77
|
+
WshShell.Run "powershell -ExecutionPolicy Bypass -WindowStyle Hidden -STA -File """ & "${trayPsPath.replace(/\\/g, "\\\\")}" & """", 0, False
|
|
78
|
+
`;
|
|
79
|
+
const vbsPath = path.join(process.env.TEMP || "/tmp", "panrouter-tray-launcher.vbs");
|
|
80
|
+
try { fs.writeFileSync(vbsPath, vbsContent, "utf8"); } catch {}
|
|
81
|
+
|
|
82
|
+
log(`VBS launcher: ${vbsPath}`);
|
|
83
|
+
|
|
84
|
+
// wscript //B = 批处理模式, 无交互
|
|
85
|
+
const vbs = spawn("wscript.exe", ["//B", "//NoLogo", vbsPath], {
|
|
86
|
+
stdio: "ignore", windowsHide: true, shell: false,
|
|
91
87
|
});
|
|
92
|
-
|
|
93
|
-
log(`
|
|
88
|
+
vbs.unref();
|
|
89
|
+
log(`VBS launched`);
|
|
94
90
|
} else {
|
|
95
|
-
log(`WARN:
|
|
91
|
+
log(`WARN: ${trayPsPath} not found`);
|
|
96
92
|
}
|
|
97
93
|
|
|
98
94
|
// ─── 5. 保持存活 ────────────────────────────────
|
|
99
|
-
log("Daemon running
|
|
95
|
+
log("Daemon running");
|
|
100
96
|
process.stdin.resume();
|
|
101
97
|
|
|
102
|
-
// 定时检查 server, 挂了就重启
|
|
103
98
|
setInterval(() => {
|
|
104
99
|
isOnline().then(ok => {
|
|
105
100
|
if (!ok) {
|
package/package.json
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "panrouter",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "让 Claude Code 免费使用 DeepSeek 等模型,无需 API Key",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"panrouter": "cli.mjs"
|
|
8
8
|
},
|
|
9
|
-
"version": "1.6.0",
|
|
10
9
|
"files": [
|
|
11
10
|
"cli.mjs",
|
|
12
11
|
"daemon.mjs",
|
package/tray-daemon.ps1
CHANGED
|
@@ -42,10 +42,46 @@ $bmp.Dispose()
|
|
|
42
42
|
$notifyIcon = New-Object System.Windows.Forms.NotifyIcon
|
|
43
43
|
$notifyIcon.Icon = $icon
|
|
44
44
|
$notifyIcon.Text = "Pan Router | 端口 50816"
|
|
45
|
-
$notifyIcon.Visible = $true
|
|
46
|
-
Write-Log "NotifyIcon visible"
|
|
47
45
|
|
|
48
|
-
# ───
|
|
46
|
+
# ─── 右键菜单 (PS5.1 用 .GetNewClosure()) ─────────
|
|
47
|
+
$menu = New-Object System.Windows.Forms.ContextMenuStrip
|
|
48
|
+
|
|
49
|
+
$titleItem = New-Object System.Windows.Forms.ToolStripMenuItem
|
|
50
|
+
$titleItem.Text = "Pan Router - :50816"
|
|
51
|
+
$titleItem.Enabled = $false
|
|
52
|
+
$titleItem.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold)
|
|
53
|
+
[void]$menu.Items.Add($titleItem)
|
|
54
|
+
[void]$menu.Items.Add((New-Object System.Windows.Forms.ToolStripSeparator))
|
|
55
|
+
|
|
56
|
+
$autoItem = New-Object System.Windows.Forms.ToolStripMenuItem
|
|
57
|
+
$autoItem.Text = "开机自启动"
|
|
58
|
+
$autoItem.Checked = Get-Autostart
|
|
59
|
+
$autoItem.Add_Click({
|
|
60
|
+
$ni = $notifyIcon
|
|
61
|
+
$ai = $autoItem
|
|
62
|
+
if ($ai.Checked) {
|
|
63
|
+
Set-Autostart $false; $ai.Checked = $false
|
|
64
|
+
$ni.ShowBalloonTip(2000, "Pan Router", "开机自启动已关闭", [System.Windows.Forms.ToolTipIcon]::Info)
|
|
65
|
+
} else {
|
|
66
|
+
Set-Autostart $true; $ai.Checked = $true
|
|
67
|
+
$ni.ShowBalloonTip(2000, "Pan Router", "开机自启动已开启 ✓", [System.Windows.Forms.ToolTipIcon]::Info)
|
|
68
|
+
}
|
|
69
|
+
}.GetNewClosure())
|
|
70
|
+
[void]$menu.Items.Add($autoItem)
|
|
71
|
+
[void]$menu.Items.Add((New-Object System.Windows.Forms.ToolStripSeparator))
|
|
72
|
+
|
|
73
|
+
$exitItem = New-Object System.Windows.Forms.ToolStripMenuItem
|
|
74
|
+
$exitItem.Text = "退出"
|
|
75
|
+
$exitItem.Add_Click({
|
|
76
|
+
Write-Log "Exit clicked"
|
|
77
|
+
$notifyIcon.Visible = $false
|
|
78
|
+
[System.Windows.Forms.Application]::Exit()
|
|
79
|
+
}.GetNewClosure())
|
|
80
|
+
[void]$menu.Items.Add($exitItem)
|
|
81
|
+
|
|
82
|
+
$notifyIcon.ContextMenuStrip = $menu
|
|
83
|
+
$notifyIcon.Visible = $true
|
|
84
|
+
Write-Log "NotifyIcon visible with menu"
|
|
49
85
|
function Test-Online {
|
|
50
86
|
try {
|
|
51
87
|
$req = [System.Net.WebRequest]::Create("http://127.0.0.1:50816/health")
|
|
@@ -115,28 +151,6 @@ if ($ready) {
|
|
|
115
151
|
}
|
|
116
152
|
}
|
|
117
153
|
|
|
118
|
-
# 右键菜单
|
|
119
|
-
$menu = New-Object System.Windows.Forms.ContextMenuStrip
|
|
120
|
-
$titleItem = New-Object System.Windows.Forms.ToolStripMenuItem("Pan Router - :50816")
|
|
121
|
-
$titleItem.Enabled = $false
|
|
122
|
-
$titleItem.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold)
|
|
123
|
-
$menu.Items.Add($titleItem)
|
|
124
|
-
$menu.Items.Add("-")
|
|
125
|
-
|
|
126
|
-
$autoItem = New-Object System.Windows.Forms.ToolStripMenuItem("开机自启动")
|
|
127
|
-
$autoItem.Checked = Get-Autostart
|
|
128
|
-
$autoItem.Add_Click({
|
|
129
|
-
if ($autoItem.Checked) { Set-Autostart $false; $autoItem.Checked = $false; $notifyIcon.ShowBalloonTip(2000, "Pan Router", "开机自启动已关闭", [System.Windows.Forms.ToolTipIcon]::Info) }
|
|
130
|
-
else { Set-Autostart $true; $autoItem.Checked = $true; $notifyIcon.ShowBalloonTip(2000, "Pan Router", "开机自启动已开启 ✓", [System.Windows.Forms.ToolTipIcon]::Info) }
|
|
131
|
-
})
|
|
132
|
-
$menu.Items.Add($autoItem)
|
|
133
|
-
$menu.Items.Add("-")
|
|
134
|
-
|
|
135
|
-
$exitItem = New-Object System.Windows.Forms.ToolStripMenuItem("退出")
|
|
136
|
-
$exitItem.Add_Click({ Write-Log "Exit"; $notifyIcon.Visible = $false; [System.Windows.Forms.Application]::Exit() })
|
|
137
|
-
$menu.Items.Add($exitItem)
|
|
138
|
-
$notifyIcon.ContextMenuStrip = $menu
|
|
139
|
-
|
|
140
154
|
# 左键: 状态
|
|
141
155
|
$notifyIcon.Add_MouseClick({
|
|
142
156
|
if ($_.Button -eq [System.Windows.Forms.MouseButtons]::Left) {
|