panrouter 3.4.0 → 3.5.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 +25 -18
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.5.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
@@ -16,10 +16,13 @@ try {
16
16
  $scriptDir = Split-Path $MyInvocation.MyCommand.Path -Parent
17
17
  $serverPath = Join-Path $scriptDir "server.mjs"
18
18
 
19
- # 拿到 Node 路径
20
19
  $nodePath = $env:PANROUTER_NODE
21
- if ([string]::IsNullOrWhiteSpace($nodePath)) { $nodePath = "node" }
20
+ if ([string]::IsNullOrWhiteSpace($nodePath)) {
21
+ $nodeCmd = Get-Command node -ErrorAction SilentlyContinue
22
+ if ($nodeCmd) { $nodePath = $nodeCmd.Source } else { $nodePath = "node" }
23
+ }
22
24
  "2. Node 路径: $nodePath" | Out-File $logFile -Append
25
+ " Server 路径: $serverPath" | Out-File $logFile -Append
23
26
 
24
27
  # ─── 管理后台代理 ──────────────────────────────────────────
25
28
  function Start-Backend {
@@ -28,7 +31,22 @@ try {
28
31
  Where-Object CommandLine -match "server\.mjs" |
29
32
  ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }
30
33
 
31
- Start-Process -FilePath $nodePath -ArgumentList "`"$serverPath`"" -WorkingDirectory $scriptDir -WindowStyle Hidden
34
+ try {
35
+ $psi = New-Object System.Diagnostics.ProcessStartInfo
36
+ $psi.FileName = $nodePath
37
+ $psi.Arguments = "`"$serverPath`""
38
+ $psi.WorkingDirectory = $scriptDir
39
+ $psi.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden
40
+ $psi.CreateNoWindow = $true
41
+ $psi.UseShellExecute = $false
42
+ $psi.RedirectStandardOutput = $true
43
+ $psi.RedirectStandardError = $true
44
+
45
+ $proc = [System.Diagnostics.Process]::Start($psi)
46
+ "-> Node 服务进程已原生启动 (PID: $($proc.Id))" | Out-File $logFile -Append
47
+ } catch {
48
+ "-> Node 进程启动失败: $($_.Exception.Message)" | Out-File $logFile -Append
49
+ }
32
50
  }
33
51
 
34
52
  # 检查端口
@@ -40,7 +58,7 @@ try {
40
58
  $tcp.Close()
41
59
  "3. 端口探测完成,已开放状态: $portOpen" | Out-File $logFile -Append
42
60
  } catch {
43
- "3. 端口探测报错 (忽略并继续): $($_.Exception.Message)" | Out-File $logFile -Append
61
+ "3. 端口探测报错: $($_.Exception.Message)" | Out-File $logFile -Append
44
62
  }
45
63
 
46
64
  if (-not $portOpen) {
@@ -51,7 +69,6 @@ try {
51
69
  $notifyIcon = New-Object System.Windows.Forms.NotifyIcon
52
70
  $notifyIcon.Text = "Pan Router (:50816)"
53
71
 
54
- # 图标兜底处理
55
72
  try {
56
73
  $bmp = New-Object System.Drawing.Bitmap(16, 16)
57
74
  $g = [System.Drawing.Graphics]::FromImage($bmp)
@@ -59,26 +76,22 @@ try {
59
76
  $font = New-Object System.Drawing.Font("Arial", 8, [System.Drawing.FontStyle]::Bold)
60
77
  $g.DrawString("P", $font, [System.Drawing.Brushes]::White, 2, 1)
61
78
  $notifyIcon.Icon = [System.Drawing.Icon]::FromHandle($bmp.GetHicon())
62
- "4. 自定义图标绘制成功" | Out-File $logFile -Append
63
79
  } catch {
64
- "4. 画图异常,改用原生盾牌图标: $($_.Exception.Message)" | Out-File $logFile -Append
65
80
  $notifyIcon.Icon = [System.Drawing.SystemIcons]::Shield
66
81
  }
67
82
 
68
83
  # ─── 原生菜单配置 (ContextMenu) ────────────────────────────
69
- # 【核心修复】:使用原生的 ContextMenu 代替极易失去焦点的 ContextMenuStrip
70
84
  $menu = New-Object System.Windows.Forms.ContextMenu
71
85
 
72
86
  $titleItem = New-Object System.Windows.Forms.MenuItem("Pan Router | :50816")
73
87
  $titleItem.Enabled = $false
74
88
  $menu.MenuItems.Add($titleItem) | Out-Null
75
-
76
89
  $menu.MenuItems.Add("-") | Out-Null
77
90
 
78
91
  $restartItem = New-Object System.Windows.Forms.MenuItem("重启服务")
79
92
  $restartItem.Add_Click({
80
93
  Start-Backend
81
- $notifyIcon.ShowBalloonTip(2000, "Pan Router", "服务已重启", [System.Windows.Forms.ToolTipIcon]::Info)
94
+ $notifyIcon.ShowBalloonTip(2000, "Pan Router", "后台代理服务已重新启动 ✓", [System.Windows.Forms.ToolTipIcon]::Info)
82
95
  })
83
96
  $menu.MenuItems.Add($restartItem) | Out-Null
84
97
 
@@ -95,13 +108,11 @@ try {
95
108
  }
96
109
  })
97
110
  $menu.MenuItems.Add($autoItem) | Out-Null
98
-
99
111
  $menu.MenuItems.Add("-") | Out-Null
100
112
 
101
113
  $exitItem = New-Object System.Windows.Forms.MenuItem("退出")
102
114
  $exitItem.Add_Click({
103
115
  $notifyIcon.Visible = $false
104
- "-> 执行退出清理" | Out-File $logFile -Append
105
116
  Get-WmiObject Win32_Process -Filter "Name = 'node.exe'" | Where-Object CommandLine -match "server\.mjs" | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }
106
117
  [System.Windows.Forms.Application]::Exit()
107
118
  })
@@ -112,7 +123,6 @@ try {
112
123
  "5. 托盘图标已绑定并设置为可见" | Out-File $logFile -Append
113
124
 
114
125
  # ─── 隐形实体主窗口 ─────────────────────────────────────────
115
- # 【核心修复】:挂载真实的 Form 窗口,防止 Windows 将该 PowerShell UI 线程当做垃圾回收掉
116
126
  $form = New-Object System.Windows.Forms.Form
117
127
  $form.ShowInTaskbar = $false
118
128
  $form.WindowState = [System.Windows.Forms.FormWindowState]::Minimized
@@ -123,10 +133,7 @@ try {
123
133
  })
124
134
 
125
135
  [System.Windows.Forms.Application]::Run($form)
126
-
127
- "7. 程序正常退出" | Out-File $logFile -Append
128
136
  } catch {
129
137
  "【致命报错】无法完成执行:" | Out-File $logFile -Append
130
138
  $_.Exception.Message | Out-File $logFile -Append
131
- $_.Exception.StackTrace | Out-File $logFile -Append
132
139
  }