panrouter 3.4.0 → 3.6.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.
Files changed (3) hide show
  1. package/cli.mjs +8 -11
  2. package/package.json +1 -1
  3. package/tray-daemon.ps1 +29 -19
package/cli.mjs CHANGED
@@ -91,17 +91,15 @@ async function startTray() {
91
91
  const psPath = path.join(__dirname, "tray-daemon.ps1");
92
92
  log("..", "正在后台启动代理...", "yellow");
93
93
 
94
- // 【终极编码修复】:PowerShell 在中文系统下默认以 GBK 解析无 BOM 的 UTF-8 文件,导致中文吞掉相邻的引号。
95
- // 方案:将脚本内容强制加上 UTF-8 BOM 头 (EF BB BF),存入临时文件后再让 PowerShell 执行。
96
- let runPsPath = psPath;
94
+ // 【核心修复】:直接在原文件上追加 UTF-8 BOM 头,彻底修复乱码并保持原目录路径不变
97
95
  try {
98
- const tempDir = process.env.TEMP || process.env.TMP || __dirname;
99
- runPsPath = path.join(tempDir, "panrouter_tray_run.ps1");
100
96
  const psContent = fs.readFileSync(psPath, "utf8");
101
- const bom = Buffer.from([0xEF, 0xBB, 0xBF]);
102
- fs.writeFileSync(runPsPath, Buffer.concat([bom, Buffer.from(psContent, "utf8")]));
97
+ if (!psContent.startsWith("")) {
98
+ const bom = Buffer.from([0xEF, 0xBB, 0xBF]);
99
+ fs.writeFileSync(psPath, Buffer.concat([bom, Buffer.from(psContent, "utf8")]));
100
+ }
103
101
  } catch (e) {
104
- runPsPath = psPath;
102
+ // 忽略权限问题
105
103
  }
106
104
 
107
105
  try {
@@ -140,7 +138,7 @@ async function startTray() {
140
138
  "-STA",
141
139
  "-ExecutionPolicy", "Bypass",
142
140
  "-WindowStyle", "Hidden",
143
- "-File", `"${runPsPath}"`
141
+ "-File", `"${psPath}"`
144
142
  ], {
145
143
  cwd: __dirname,
146
144
  stdio: ['ignore', 'pipe', 'pipe'],
@@ -157,8 +155,7 @@ async function startTray() {
157
155
 
158
156
  if (tray.exitCode !== null) {
159
157
  log("!!", "托盘进程未能驻留,发生闪退!", "red");
160
- console.log(`\n\x1b[31m=== PowerShell 启动失败原因 ===\x1b[0m\n${psOutput || "(无报错输出,可能是被杀毒软件静默拦截)"}\n\x1b[31m===============================\x1b[0m\n`);
161
- console.log("提示:如果代理可用,你可以暂时无视此错误。");
158
+ console.log(`\n\x1b[31m=== PowerShell 启动失败原因 ===\x1b[0m\n${psOutput || "(无输出)"}\n\x1b[31m===============================\x1b[0m\n`);
162
159
  } else {
163
160
  tray.unref();
164
161
  console.log(" 托盘图标应该已在右下角显示。");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "panrouter",
3
- "version": "3.4.0",
3
+ "version": "3.6.0",
4
4
  "description": "让 Claude Code 免费使用 DeepSeek 等模型,无需 API Key",
5
5
  "type": "module",
6
6
  "bin": {
package/tray-daemon.ps1 CHANGED
@@ -1,8 +1,8 @@
1
1
  <#
2
2
  .SYNOPSIS
3
- Pan Router 托盘守护脚本 (终极原生挂载版 + 日志诊断)
3
+ Pan Router 托盘守护脚本 (终极完美版)
4
4
  #>
5
- $ErrorActionPreference = "Stop" # 遇到错误直接抛出,由 try-catch 捕获写日志
5
+ $ErrorActionPreference = "Stop"
6
6
 
7
7
  $logFile = "$env:TEMP\panrouter_tray.log"
8
8
  "--- $(Get-Date -Format 'HH:mm:ss') 托盘脚本启动 ---" | Out-File $logFile
@@ -15,11 +15,16 @@ try {
15
15
 
16
16
  $scriptDir = Split-Path $MyInvocation.MyCommand.Path -Parent
17
17
  $serverPath = Join-Path $scriptDir "server.mjs"
18
+ # 【修复1】:在全局作用域提前把准确的脚本路径存下来,防止在 Click 事件块内丢失
19
+ $trayScriptPath = $MyInvocation.MyCommand.Path
18
20
 
19
- # 拿到 Node 路径
20
21
  $nodePath = $env:PANROUTER_NODE
21
- if ([string]::IsNullOrWhiteSpace($nodePath)) { $nodePath = "node" }
22
+ if ([string]::IsNullOrWhiteSpace($nodePath)) {
23
+ $nodeCmd = Get-Command node -ErrorAction SilentlyContinue
24
+ if ($nodeCmd) { $nodePath = $nodeCmd.Source } else { $nodePath = "node" }
25
+ }
22
26
  "2. Node 路径: $nodePath" | Out-File $logFile -Append
27
+ " Server 路径: $serverPath" | Out-File $logFile -Append
23
28
 
24
29
  # ─── 管理后台代理 ──────────────────────────────────────────
25
30
  function Start-Backend {
@@ -28,7 +33,22 @@ try {
28
33
  Where-Object CommandLine -match "server\.mjs" |
29
34
  ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }
30
35
 
31
- Start-Process -FilePath $nodePath -ArgumentList "`"$serverPath`"" -WorkingDirectory $scriptDir -WindowStyle Hidden
36
+ try {
37
+ $psi = New-Object System.Diagnostics.ProcessStartInfo
38
+ $psi.FileName = $nodePath
39
+ $psi.Arguments = "`"$serverPath`""
40
+ $psi.WorkingDirectory = $scriptDir
41
+ $psi.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden
42
+ $psi.CreateNoWindow = $true
43
+ $psi.UseShellExecute = $false
44
+ $psi.RedirectStandardOutput = $true
45
+ $psi.RedirectStandardError = $true
46
+
47
+ $proc = [System.Diagnostics.Process]::Start($psi)
48
+ "-> Node 服务进程已原生启动 (PID: $($proc.Id))" | Out-File $logFile -Append
49
+ } catch {
50
+ "-> Node 进程启动失败: $($_.Exception.Message)" | Out-File $logFile -Append
51
+ }
32
52
  }
33
53
 
34
54
  # 检查端口
@@ -40,7 +60,7 @@ try {
40
60
  $tcp.Close()
41
61
  "3. 端口探测完成,已开放状态: $portOpen" | Out-File $logFile -Append
42
62
  } catch {
43
- "3. 端口探测报错 (忽略并继续): $($_.Exception.Message)" | Out-File $logFile -Append
63
+ "3. 端口探测报错: $($_.Exception.Message)" | Out-File $logFile -Append
44
64
  }
45
65
 
46
66
  if (-not $portOpen) {
@@ -51,7 +71,6 @@ try {
51
71
  $notifyIcon = New-Object System.Windows.Forms.NotifyIcon
52
72
  $notifyIcon.Text = "Pan Router (:50816)"
53
73
 
54
- # 图标兜底处理
55
74
  try {
56
75
  $bmp = New-Object System.Drawing.Bitmap(16, 16)
57
76
  $g = [System.Drawing.Graphics]::FromImage($bmp)
@@ -59,26 +78,22 @@ try {
59
78
  $font = New-Object System.Drawing.Font("Arial", 8, [System.Drawing.FontStyle]::Bold)
60
79
  $g.DrawString("P", $font, [System.Drawing.Brushes]::White, 2, 1)
61
80
  $notifyIcon.Icon = [System.Drawing.Icon]::FromHandle($bmp.GetHicon())
62
- "4. 自定义图标绘制成功" | Out-File $logFile -Append
63
81
  } catch {
64
- "4. 画图异常,改用原生盾牌图标: $($_.Exception.Message)" | Out-File $logFile -Append
65
82
  $notifyIcon.Icon = [System.Drawing.SystemIcons]::Shield
66
83
  }
67
84
 
68
85
  # ─── 原生菜单配置 (ContextMenu) ────────────────────────────
69
- # 【核心修复】:使用原生的 ContextMenu 代替极易失去焦点的 ContextMenuStrip
70
86
  $menu = New-Object System.Windows.Forms.ContextMenu
71
87
 
72
88
  $titleItem = New-Object System.Windows.Forms.MenuItem("Pan Router | :50816")
73
89
  $titleItem.Enabled = $false
74
90
  $menu.MenuItems.Add($titleItem) | Out-Null
75
-
76
91
  $menu.MenuItems.Add("-") | Out-Null
77
92
 
78
93
  $restartItem = New-Object System.Windows.Forms.MenuItem("重启服务")
79
94
  $restartItem.Add_Click({
80
95
  Start-Backend
81
- $notifyIcon.ShowBalloonTip(2000, "Pan Router", "服务已重启", [System.Windows.Forms.ToolTipIcon]::Info)
96
+ $notifyIcon.ShowBalloonTip(2000, "Pan Router", "后台代理服务已重新启动 ✓", [System.Windows.Forms.ToolTipIcon]::Info)
82
97
  })
83
98
  $menu.MenuItems.Add($restartItem) | Out-Null
84
99
 
@@ -89,19 +104,18 @@ try {
89
104
  reg delete "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v PanRouter /f 2>&1 | Out-Null
90
105
  $autoItem.Checked = $false
91
106
  } else {
92
- $cmd = "powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$($MyInvocation.MyCommand.Path)`""
107
+ # 【修复2】:写入注册表时,务必加上 -STA 参数防止 UI 闪退,并使用刚刚存好的 $trayScriptPath
108
+ $cmd = "powershell.exe -WindowStyle Hidden -STA -ExecutionPolicy Bypass -File `"$trayScriptPath`""
93
109
  reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v PanRouter /t REG_SZ /d $cmd /f 2>&1 | Out-Null
94
110
  $autoItem.Checked = $true
95
111
  }
96
112
  })
97
113
  $menu.MenuItems.Add($autoItem) | Out-Null
98
-
99
114
  $menu.MenuItems.Add("-") | Out-Null
100
115
 
101
116
  $exitItem = New-Object System.Windows.Forms.MenuItem("退出")
102
117
  $exitItem.Add_Click({
103
118
  $notifyIcon.Visible = $false
104
- "-> 执行退出清理" | Out-File $logFile -Append
105
119
  Get-WmiObject Win32_Process -Filter "Name = 'node.exe'" | Where-Object CommandLine -match "server\.mjs" | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }
106
120
  [System.Windows.Forms.Application]::Exit()
107
121
  })
@@ -112,7 +126,6 @@ try {
112
126
  "5. 托盘图标已绑定并设置为可见" | Out-File $logFile -Append
113
127
 
114
128
  # ─── 隐形实体主窗口 ─────────────────────────────────────────
115
- # 【核心修复】:挂载真实的 Form 窗口,防止 Windows 将该 PowerShell UI 线程当做垃圾回收掉
116
129
  $form = New-Object System.Windows.Forms.Form
117
130
  $form.ShowInTaskbar = $false
118
131
  $form.WindowState = [System.Windows.Forms.FormWindowState]::Minimized
@@ -123,10 +136,7 @@ try {
123
136
  })
124
137
 
125
138
  [System.Windows.Forms.Application]::Run($form)
126
-
127
- "7. 程序正常退出" | Out-File $logFile -Append
128
139
  } catch {
129
140
  "【致命报错】无法完成执行:" | Out-File $logFile -Append
130
141
  $_.Exception.Message | Out-File $logFile -Append
131
- $_.Exception.StackTrace | Out-File $logFile -Append
132
142
  }