chore: add buildOutput RTK filter, drop legacy cloud sync, internal cleanup
- feat(rtk): buildOutput filter + autodetect for npm/yarn/cargo logs - chore: remove unused cloud sync module and related routes - ui: hide deprecated providers (qwen, iflow, antigravity) - chore: minor tray/cli/internal adjustments
This commit is contained in:
parent
21ea744c72
commit
3cca2252a6
26 changed files with 871 additions and 535 deletions
33
cli/cli.js
33
cli/cli.js
|
|
@ -219,8 +219,12 @@ function killAllAppProcesses(appPort) {
|
|||
});
|
||||
const lines = output.split("\n").slice(1).filter(l => l.trim());
|
||||
lines.forEach(line => {
|
||||
const isAppProcess = line.toLowerCase().includes("9router") ||
|
||||
line.toLowerCase().includes("next-server");
|
||||
// Whitelist: real node process running 9router/cli.js, or next-server.
|
||||
// Avoids killing editors/grep/strace/cursor that just have "9router" in cmdline.
|
||||
const cmd = line.toLowerCase();
|
||||
const isAppProcess =
|
||||
(cmd.includes("node") && cmd.includes("9router") && (cmd.includes("cli.js") || cmd.includes("\\9router") || cmd.includes("/9router")))
|
||||
|| cmd.includes("next-server");
|
||||
if (isAppProcess) {
|
||||
const match = line.match(/^"(\d+)"/);
|
||||
if (match && match[1] && match[1] !== process.pid.toString()) {
|
||||
|
|
@ -241,7 +245,12 @@ function killAllAppProcesses(appPort) {
|
|||
const lines = output.split('\n');
|
||||
|
||||
lines.forEach(line => {
|
||||
const isAppProcess = line.includes("9router") || line.includes("next-server");
|
||||
// Whitelist: real node process running 9router/cli.js, or next-server.
|
||||
// Avoids killing grep/strace/editors/cursor that incidentally match "9router".
|
||||
const cmd = line.toLowerCase();
|
||||
const isAppProcess =
|
||||
(cmd.includes("node") && cmd.includes("9router") && (cmd.includes("cli.js") || cmd.includes("/9router")))
|
||||
|| cmd.includes("next-server");
|
||||
if (isAppProcess) {
|
||||
const parts = line.trim().split(/\s+/);
|
||||
const pid = parts[1];
|
||||
|
|
@ -685,10 +694,10 @@ function startServer(latestVersion) {
|
|||
const { clearScreen } = require("./src/cli/utils/display");
|
||||
clearScreen();
|
||||
|
||||
// Kill current tray FIRST so the new bgProcess can register a fresh
|
||||
// NSStatusItem on macOS without conflicting with the orphan binary
|
||||
try { require("./src/cli/tray/tray").killTray(); } catch (e) { }
|
||||
await new Promise(r => setTimeout(r, 300));
|
||||
// Kill current tray and AWAIT Go binary fully exit. macOS needs the
|
||||
// old NSStatusItem released before a new tray process can register;
|
||||
// otherwise the bgProcess tray silently fails ("works sometimes").
|
||||
try { await require("./src/cli/tray/tray").killTray(); } catch (e) { }
|
||||
|
||||
// Enable auto startup on OS boot
|
||||
try {
|
||||
|
|
@ -699,10 +708,18 @@ function startServer(latestVersion) {
|
|||
}
|
||||
} catch (e) { }
|
||||
|
||||
// Log bgProcess stderr to file so silent tray failures are debuggable.
|
||||
// Previously stdio:"ignore" swallowed every error from systray2 init.
|
||||
const logDir = path.join(getAppDataDir(), "logs");
|
||||
try { fs.mkdirSync(logDir, { recursive: true }); } catch (e) { }
|
||||
const bgLogPath = path.join(logDir, "tray-bg.log");
|
||||
let bgLogFd = "ignore";
|
||||
try { bgLogFd = fs.openSync(bgLogPath, "a"); } catch (e) { }
|
||||
|
||||
// Spawn new detached process with --tray flag
|
||||
const bgProcess = spawn(process.execPath, [__filename, "--tray", "--skip-update", "-p", port.toString()], {
|
||||
detached: true,
|
||||
stdio: "ignore",
|
||||
stdio: ["ignore", bgLogFd, bgLogFd],
|
||||
windowsHide: true,
|
||||
env: { ...process.env }
|
||||
});
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ function initUnixTray(options) {
|
|||
items
|
||||
};
|
||||
|
||||
trayInstance = new SysTray({ menu, debug: false, copyDir: false });
|
||||
trayInstance = new SysTray({ menu, debug: false, copyDir: true });
|
||||
isWinTray = false;
|
||||
|
||||
trayInstance.onClick((action) => {
|
||||
|
|
@ -245,31 +245,49 @@ function initUnixTray(options) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Kill/close system tray gracefully
|
||||
* Kill tray, wait Go binary fully exit (returns Promise).
|
||||
* Critical for hide-to-tray: macOS must release NSStatusItem before bgProcess
|
||||
* spawns a new tray, otherwise the new icon silently fails to register.
|
||||
*/
|
||||
function killTray() {
|
||||
const instance = trayInstance;
|
||||
const wasWin = isWinTray;
|
||||
trayInstance = null;
|
||||
if (!instance) return Promise.resolve();
|
||||
|
||||
if (instance) {
|
||||
try {
|
||||
if (wasWin) instance.kill();
|
||||
else {
|
||||
// systray2.kill(false) closes IPC but leaves the Go tray binary
|
||||
// subprocess running, which keeps an orphan NSStatusItem on macOS
|
||||
// and blocks a freshly spawned tray (e.g. hide-to-tray bgProcess)
|
||||
// from registering. Kill the child PID directly first.
|
||||
try {
|
||||
const proc = instance._process || (typeof instance.process === "function" ? instance.process() : null);
|
||||
if (proc && proc.pid) {
|
||||
process.kill(proc.pid, "SIGKILL");
|
||||
}
|
||||
} catch (e) {}
|
||||
instance.kill(false);
|
||||
}
|
||||
} catch (e) {}
|
||||
if (wasWin) {
|
||||
try { instance.kill(); } catch (e) {}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// Unix: get the Go tray child process handle, SIGKILL it, await "exit"
|
||||
let proc = null;
|
||||
try {
|
||||
proc = instance._process || (typeof instance.process === "function" ? instance.process() : null);
|
||||
} catch (e) {}
|
||||
|
||||
// Always close IPC (best-effort, may throw if pipe already broken)
|
||||
const closeIpc = () => { try { instance.kill(false); } catch (e) {} };
|
||||
|
||||
if (!proc || !proc.pid) {
|
||||
closeIpc();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
let done = false;
|
||||
const finish = () => { if (done) return; done = true; closeIpc(); resolve(); };
|
||||
|
||||
proc.once("exit", finish);
|
||||
try { proc.kill("SIGKILL"); } catch (e) {}
|
||||
|
||||
// Fallback poll in case "exit" never fires (detached child, pipe closed)
|
||||
const deadline = Date.now() + 3000;
|
||||
const poll = setInterval(() => {
|
||||
try { process.kill(proc.pid, 0); } catch { clearInterval(poll); finish(); return; }
|
||||
if (Date.now() > deadline) { clearInterval(poll); finish(); }
|
||||
}, 50);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue