shennian 0.2.24 → 0.2.26
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.
- package/dist/src/commands/daemon.js +16 -1
- package/dist/src/index.js +34 -3
- package/package.json +1 -1
|
@@ -504,6 +504,7 @@ export function installService() {
|
|
|
504
504
|
}
|
|
505
505
|
catch {
|
|
506
506
|
// Some Linux environments lack systemd user services; keep best-effort behavior.
|
|
507
|
+
return false;
|
|
507
508
|
}
|
|
508
509
|
// Enable linger so the user systemd session (and thus this service) persists
|
|
509
510
|
// across reboots even without an active login session.
|
|
@@ -513,7 +514,13 @@ export function installService() {
|
|
|
513
514
|
catch {
|
|
514
515
|
// loginctl is unavailable on some distros/containers; auto-start still works after login.
|
|
515
516
|
}
|
|
516
|
-
|
|
517
|
+
try {
|
|
518
|
+
execSync('systemctl --user restart shennian', { stdio: 'pipe' });
|
|
519
|
+
return true;
|
|
520
|
+
}
|
|
521
|
+
catch {
|
|
522
|
+
return false;
|
|
523
|
+
}
|
|
517
524
|
}
|
|
518
525
|
case 'win32': {
|
|
519
526
|
return installWindowsScheduledTask();
|
|
@@ -699,6 +706,14 @@ async function daemonRestart(opts = {}) {
|
|
|
699
706
|
console.log(chalk.gray('● Background service not running, starting it now'));
|
|
700
707
|
}
|
|
701
708
|
}
|
|
709
|
+
if (getPlatform() === 'linux') {
|
|
710
|
+
const startedByService = installService();
|
|
711
|
+
if (startedByService) {
|
|
712
|
+
if (opts.json)
|
|
713
|
+
printJson(getDaemonStatus());
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
702
717
|
startDaemonProcess({ quiet: opts.json });
|
|
703
718
|
if (opts.json)
|
|
704
719
|
printJson(getDaemonStatus());
|
package/dist/src/index.js
CHANGED
|
@@ -39,6 +39,25 @@ function formatDisconnectInfo(info) {
|
|
|
39
39
|
parts.push(`error=${info.error}`);
|
|
40
40
|
return parts.join(' ');
|
|
41
41
|
}
|
|
42
|
+
async function waitForPidExit(pid, timeoutMs = 5000) {
|
|
43
|
+
const startedAt = Date.now();
|
|
44
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
45
|
+
try {
|
|
46
|
+
process.kill(pid, 0);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
process.kill(pid, 0);
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
42
61
|
const program = new Command();
|
|
43
62
|
program.name('shennian').description('Shennian — AI Agent Mobile Console').version(cliVersion);
|
|
44
63
|
program
|
|
@@ -70,15 +89,27 @@ program
|
|
|
70
89
|
catch {
|
|
71
90
|
// env.json may not exist yet
|
|
72
91
|
}
|
|
73
|
-
// Single-instance guard
|
|
92
|
+
// Single-instance guard. systemd-managed starts are authoritative and may
|
|
93
|
+
// need to take over from an older detached `shennian start` process.
|
|
74
94
|
const pidFile = resolveShennianPath('daemon.pid');
|
|
75
95
|
try {
|
|
76
96
|
const oldPid = parseInt(fs.readFileSync(pidFile, 'utf-8').trim(), 10);
|
|
77
97
|
if (oldPid && oldPid !== process.pid) {
|
|
78
98
|
try {
|
|
79
99
|
process.kill(oldPid, 0);
|
|
80
|
-
|
|
81
|
-
|
|
100
|
+
if (process.env.INVOCATION_ID || process.env.JOURNAL_STREAM) {
|
|
101
|
+
console.log(`[${new Date().toISOString()}] systemd start taking over from existing daemon (PID ${oldPid})`);
|
|
102
|
+
process.kill(oldPid, 'SIGTERM');
|
|
103
|
+
const stopped = await waitForPidExit(oldPid);
|
|
104
|
+
if (!stopped) {
|
|
105
|
+
process.kill(oldPid, 'SIGKILL');
|
|
106
|
+
await waitForPidExit(oldPid, 2000);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
console.log(`[${new Date().toISOString()}] daemon already running (PID ${oldPid}), skipping duplicate start`);
|
|
111
|
+
process.exit(0);
|
|
112
|
+
}
|
|
82
113
|
}
|
|
83
114
|
catch {
|
|
84
115
|
// Stale pid; continue booting and overwrite it below.
|