diff --git a/main.js b/main.js index f851284..00f2b94 100644 --- a/main.js +++ b/main.js @@ -4,9 +4,10 @@ const http = require("node:http"); const fs = require("node:fs"); const path = require("node:path"); const os = require("node:os"); +const { spawn } = require("node:child_process"); const autostart = require("./lib/autostart"); const hooksInstaller = require("./lib/hooks-installer"); -const { unpacked, portableDir, isPackaged } = require("./lib/paths"); +const { unpacked, portableDir, portableExe, isPackaged } = require("./lib/paths"); const APP_DIR = __dirname; const HOME = os.homedir(); @@ -507,6 +508,12 @@ function startServer() { })); return; } + if (req.method === "POST" && req.url === "/restart") { + res.writeHead(204); + res.end(); + setTimeout(restartApp, 100); + return; + } if (req.method === "GET" && req.url === "/health") { res.writeHead(200, { "content-type": "text/plain" }); res.end("ok"); @@ -653,6 +660,7 @@ function buildMenu() { { label: "開啟設定檔", click: () => { saveConfig(); shell.openPath(CONFIG_PATH); } }, { label: "開啟事件紀錄", click: () => { appendLog("open log"); shell.openPath(LOG_PATH); } }, { type: "separator" }, + { label: "重啟", click: restartApp }, { label: "結束", click: () => app.quit() }, ]); } @@ -679,6 +687,23 @@ function setScale(scale) { refreshTray(); } +// 重啟。安裝版/開發模式用 app.relaunch()(等目前這個結束後才啟動新的)。 +// portable 版不能這樣:relaunch 會重跑解壓到 %TEMP% 的那顆 exe,而 portable 外殼在程式結束時會把 +// 整個解壓目錄刪掉、下次啟動再重新解壓;舊程序還在跑時檔案被鎖住,解壓也會失敗。 +// 所以改成延遲兩秒後重新執行原本的 -portable.exe,然後結束自己。 +function restartApp() { + appendLog("restart requested"); + const exe = portableExe(); + if (exe) { + const child = spawn("cmd.exe", ["/c", `ping -n 3 127.0.0.1 >nul && start "" "${exe}"`], + { detached: true, stdio: "ignore", windowsHide: true, windowsVerbatimArguments: true }); + child.unref(); + } else { + app.relaunch(); + } + app.quit(); +} + function resetPosition() { if (!win) return; const pos = defaultPosition(windowSizeFor(config.scale)); diff --git a/package-lock.json b/package-lock.json index 08ed285..9dab6ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "claude-pet", - "version": "2.0.12", + "version": "2.0.13", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "claude-pet", - "version": "2.0.12", + "version": "2.0.13", "devDependencies": { "electron": "^43.4.1", "electron-builder": "^26.0.12" diff --git a/package.json b/package.json index e3bca0e..8b05ba0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "claude-pet", - "version": "2.0.12", + "version": "2.0.13", "description": "Codex Pets 相容的 Claude Code 桌面寵物(spriteVersionNumber 2:9 個動作列 + 16 方向追視)", "main": "main.js", "private": true,