panrouter 5.4.4 → 5.4.6

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/package.json +1 -1
  2. package/pool-worker.mjs +44 -13
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "panrouter",
3
- "version": "5.4.4",
3
+ "version": "5.4.6",
4
4
  "description": "让 Claude Code 免费使用 DeepSeek 等模型,无需 API Key",
5
5
  "type": "module",
6
6
  "bin": {
package/pool-worker.mjs CHANGED
@@ -178,21 +178,41 @@ function scheduleReconnect() {
178
178
 
179
179
  function handleUpgrade() {
180
180
  log("收到主控升级指令,开始升级...", "WARN");
181
- // 设关闭标志,避免 ws.close onclose scheduleReconnect 启动重连
182
- isShuttingDown = true;
181
+ // 彻底断开——remove 所有 ws 事件监听,不让 close 事件触发 reconnect
182
+ stopHeartbeat();
183
+ if (reconnectTimer) {
184
+ clearTimeout(reconnectTimer);
185
+ reconnectTimer = null;
186
+ }
183
187
  if (ws) {
188
+ ws.removeAllListeners();
184
189
  try { ws.close(1000, "Upgrading"); } catch {}
185
190
  ws = null;
186
191
  }
187
- stopHeartbeat();
188
192
 
189
193
  const pkgPath = path.join(__dirname, "package.json");
190
194
  const oldVersion = JSON.parse(fs.readFileSync(pkgPath, "utf-8")).version;
191
- log(`当前版本: v${oldVersion},正在执行 npm install -g panrouter@latest ...`);
195
+ log(`当前版本: v${oldVersion}`);
196
+
197
+ // 先检查 npm registry 是否有新版,避免 Windows 下 EBUSY
198
+ let hasNewer = false;
192
199
  try {
193
- execSync("npm install -g panrouter@latest", { stdio: "inherit", timeout: 120000 });
194
- } catch (e) {
195
- log(`升级失败: ${e.message},仍尝试重启`, "ERR");
200
+ const latest = execSync("npm view panrouter version", { stdio: 'pipe', timeout: 10000 }).toString().trim();
201
+ hasNewer = latest !== oldVersion;
202
+ if (!hasNewer) {
203
+ log(`已是 v${latest}(最新版),跳过 npm install`, "OK");
204
+ }
205
+ } catch {
206
+ // 网络问题等,保守假设有新版本
207
+ hasNewer = true;
208
+ }
209
+
210
+ if (hasNewer) {
211
+ try {
212
+ execSync("npm install -g panrouter@latest", { stdio: "inherit", timeout: 120000 });
213
+ } catch (e) {
214
+ log(`升级失败: ${e.message},仍尝试重启`, "ERR");
215
+ }
196
216
  }
197
217
 
198
218
  // 从磁盘重新读(跳过 require 缓存)
@@ -203,13 +223,19 @@ function handleUpgrade() {
203
223
  killPort(SERVER_PORT);
204
224
 
205
225
  if (oldVersion !== newVersion) {
206
- // 版本变了spawn 新进程加载新代码
207
- log(`版本变更: v${oldVersion} → v${newVersion},启动新进程`, "OK");
208
- try {
209
- if (!fs.existsSync(RUNTIME_DIR)) fs.mkdirSync(RUNTIME_DIR, { recursive: true });
210
- fs.writeFileSync(PID_FILE, String(process.pid), "utf-8");
211
- } catch {}
226
+ log(`版本变更: v${oldVersion}v${newVersion},升级并重启`, "OK");
212
227
 
228
+ // Windows 下当前进程锁住了 npm 目录 → 先 exit 释放锁再 npm install
229
+ // 用 start /b 提交一个后台脚本,等 2 秒(进程退出锁释放)后执行升级 + 启动
230
+ // start /b 的输出会打到当前终端,用户能看到进度
231
+ if (process.platform === 'win32') {
232
+ const cmd = `start /b cmd /c "@ping 127.0.0.1 -n 3 >nul && npm install -g panrouter@latest && panrouter --pool"`;
233
+ try { execSync(cmd, { stdio: 'pipe', timeout: 5000, shell: true }); } catch {}
234
+ log("升级脚本已提交 (当前进程退出后自动执行),旧进程退出", "OFF");
235
+ process.exit(0);
236
+ }
237
+
238
+ // Unix 可以直接 spawn(不会锁)
213
239
  spawn(process.execPath, [process.argv[1], "--pool"], {
214
240
  cwd: __dirname,
215
241
  stdio: "inherit",
@@ -225,6 +251,11 @@ function handleUpgrade() {
225
251
 
226
252
  async function doRestart() {
227
253
  isShuttingDown = false;
254
+ // 确保重连定时器已经清掉,避免和 connectToHub 竞态
255
+ if (reconnectTimer) {
256
+ clearTimeout(reconnectTimer);
257
+ reconnectTimer = null;
258
+ }
228
259
  const serverOk = await ensureServer();
229
260
  if (!serverOk) {
230
261
  log("代理服务重启失败", "ERR");