panrouter 3.2.0 → 3.4.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 (2) hide show
  1. package/cli.mjs +32 -8
  2. package/package.json +1 -1
package/cli.mjs CHANGED
@@ -91,7 +91,19 @@ async function startTray() {
91
91
  const psPath = path.join(__dirname, "tray-daemon.ps1");
92
92
  log("..", "正在后台启动代理...", "yellow");
93
93
 
94
- // 1. 由主程序直接启动 Node 代理,彻底杜绝 PowerShell 启动慢导致的超时
94
+ // 【终极编码修复】:PowerShell 在中文系统下默认以 GBK 解析无 BOM 的 UTF-8 文件,导致中文吞掉相邻的引号。
95
+ // 方案:将脚本内容强制加上 UTF-8 BOM 头 (EF BB BF),存入临时文件后再让 PowerShell 执行。
96
+ let runPsPath = psPath;
97
+ try {
98
+ const tempDir = process.env.TEMP || process.env.TMP || __dirname;
99
+ runPsPath = path.join(tempDir, "panrouter_tray_run.ps1");
100
+ 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")]));
103
+ } catch (e) {
104
+ runPsPath = psPath;
105
+ }
106
+
95
107
  try {
96
108
  if (process.platform === "win32") {
97
109
  execSync('taskkill /f /fi "WINDOWTITLE eq Pan Router*" >nul 2>&1', { stdio: "pipe" });
@@ -106,7 +118,6 @@ async function startTray() {
106
118
  });
107
119
  srv.unref();
108
120
 
109
- // 2. 验证端口(由于是直接用 Node 启动,这步通常 1 秒内就会通过)
110
121
  let ok = false;
111
122
  for (let i = 0; i < 15; i++) {
112
123
  if (await isPortOpen()) {
@@ -122,23 +133,36 @@ async function startTray() {
122
133
  log("!!", "服务启动超时,但仍将尝试加载托盘", "red");
123
134
  }
124
135
 
125
- // 3. 独立拉起系统托盘
126
136
  log("..", "正在加载系统托盘...", "yellow");
137
+
127
138
  const tray = spawn("powershell.exe", [
128
139
  "-NoProfile",
140
+ "-STA",
129
141
  "-ExecutionPolicy", "Bypass",
130
142
  "-WindowStyle", "Hidden",
131
- "-File", psPath
143
+ "-File", `"${runPsPath}"`
132
144
  ], {
133
145
  cwd: __dirname,
134
- stdio: "ignore",
146
+ stdio: ['ignore', 'pipe', 'pipe'],
135
147
  windowsHide: true,
136
- detached: true,
148
+ shell: true,
137
149
  env: { ...process.env, PANROUTER_NODE: process.execPath }
138
150
  });
139
- tray.unref();
140
151
 
141
- console.log(" API 代理已立即可用。托盘图标稍后将在右下角显示。");
152
+ let psOutput = "";
153
+ tray.stdout.on("data", d => psOutput += d.toString());
154
+ tray.stderr.on("data", d => psOutput += d.toString());
155
+
156
+ await new Promise(rs => setTimeout(rs, 2500));
157
+
158
+ if (tray.exitCode !== null) {
159
+ log("!!", "托盘进程未能驻留,发生闪退!", "red");
160
+ console.log(`\n\x1b[31m=== PowerShell 启动失败原因 ===\x1b[0m\n${psOutput || "(无报错输出,可能是被杀毒软件静默拦截)"}\n\x1b[31m===============================\x1b[0m\n`);
161
+ console.log("提示:如果代理可用,你可以暂时无视此错误。");
162
+ } else {
163
+ tray.unref();
164
+ console.log(" 托盘图标应该已在右下角显示。");
165
+ }
142
166
  }
143
167
 
144
168
  async function main() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "panrouter",
3
- "version": "3.2.0",
3
+ "version": "3.4.0",
4
4
  "description": "让 Claude Code 免费使用 DeepSeek 等模型,无需 API Key",
5
5
  "type": "module",
6
6
  "bin": {