neoagent 2.1.9 → 2.1.10
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/lib/manager.js +111 -35
- package/package.json +1 -1
- package/server/http/middleware.js +1 -0
- package/server/public/flutter_bootstrap.js +1 -1
package/lib/manager.js
CHANGED
|
@@ -70,6 +70,16 @@ function detectPlatform() {
|
|
|
70
70
|
return 'other';
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
function launchctlDomain() {
|
|
74
|
+
if (typeof process.getuid !== 'function') return null;
|
|
75
|
+
return `gui/${process.getuid()}`;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function launchctlServiceTarget() {
|
|
79
|
+
const domain = launchctlDomain();
|
|
80
|
+
return domain ? `${domain}/${SERVICE_LABEL}` : SERVICE_LABEL;
|
|
81
|
+
}
|
|
82
|
+
|
|
73
83
|
function loadEnvPort() {
|
|
74
84
|
try {
|
|
75
85
|
const env = fs.readFileSync(ENV_FILE, 'utf8');
|
|
@@ -210,6 +220,49 @@ function killByPort(port) {
|
|
|
210
220
|
return killed;
|
|
211
221
|
}
|
|
212
222
|
|
|
223
|
+
function listNeoAgentServerProcesses() {
|
|
224
|
+
const res = runQuiet('ps', ['-axo', 'pid=,ppid=,command=']);
|
|
225
|
+
if (res.status !== 0) return [];
|
|
226
|
+
|
|
227
|
+
return res.stdout
|
|
228
|
+
.split('\n')
|
|
229
|
+
.map((line) => line.trim())
|
|
230
|
+
.filter(Boolean)
|
|
231
|
+
.map((line) => {
|
|
232
|
+
const match = line.match(/^(\d+)\s+(\d+)\s+(.*)$/);
|
|
233
|
+
if (!match) return null;
|
|
234
|
+
return {
|
|
235
|
+
pid: Number(match[1]),
|
|
236
|
+
ppid: Number(match[2]),
|
|
237
|
+
command: match[3],
|
|
238
|
+
};
|
|
239
|
+
})
|
|
240
|
+
.filter(Boolean)
|
|
241
|
+
.filter((entry) =>
|
|
242
|
+
entry.pid !== process.pid &&
|
|
243
|
+
/(^|\s)node(\s|$)/.test(entry.command) &&
|
|
244
|
+
(
|
|
245
|
+
entry.command.includes('/neoagent/server/index.js') ||
|
|
246
|
+
entry.command.includes(`${path.sep}NeoAgent${path.sep}server${path.sep}index.js`) ||
|
|
247
|
+
entry.command.includes(`${APP_DIR}${path.sep}server${path.sep}index.js`)
|
|
248
|
+
)
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function killNeoAgentServerProcesses() {
|
|
253
|
+
const processes = listNeoAgentServerProcesses();
|
|
254
|
+
let killed = false;
|
|
255
|
+
for (const proc of processes) {
|
|
256
|
+
try {
|
|
257
|
+
process.kill(proc.pid, 'SIGTERM');
|
|
258
|
+
killed = true;
|
|
259
|
+
} catch {
|
|
260
|
+
// Ignore stale processes.
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return { killed, processes };
|
|
264
|
+
}
|
|
265
|
+
|
|
213
266
|
function isPortOpen(port) {
|
|
214
267
|
return new Promise((resolve) => {
|
|
215
268
|
const sock = new net.Socket();
|
|
@@ -338,8 +391,21 @@ function installMacService() {
|
|
|
338
391
|
|
|
339
392
|
fs.writeFileSync(PLIST_DST, content);
|
|
340
393
|
|
|
341
|
-
|
|
342
|
-
|
|
394
|
+
const domain = launchctlDomain();
|
|
395
|
+
if (domain) {
|
|
396
|
+
runQuiet('launchctl', ['bootout', domain, PLIST_DST]);
|
|
397
|
+
const bootstrap = runQuiet('launchctl', ['bootstrap', domain, PLIST_DST]);
|
|
398
|
+
if (bootstrap.status !== 0) {
|
|
399
|
+
runQuiet('launchctl', ['unload', PLIST_DST]);
|
|
400
|
+
runOrThrow('launchctl', ['load', PLIST_DST]);
|
|
401
|
+
} else {
|
|
402
|
+
runQuiet('launchctl', ['enable', launchctlServiceTarget()]);
|
|
403
|
+
runQuiet('launchctl', ['kickstart', '-k', launchctlServiceTarget()]);
|
|
404
|
+
}
|
|
405
|
+
} else {
|
|
406
|
+
runQuiet('launchctl', ['unload', PLIST_DST]);
|
|
407
|
+
runOrThrow('launchctl', ['load', PLIST_DST]);
|
|
408
|
+
}
|
|
343
409
|
logOk(`launchd service loaded (${SERVICE_LABEL})`);
|
|
344
410
|
}
|
|
345
411
|
|
|
@@ -401,7 +467,7 @@ function cmdStart() {
|
|
|
401
467
|
const platform = detectPlatform();
|
|
402
468
|
|
|
403
469
|
if (platform === 'macos' && fs.existsSync(PLIST_DST)) {
|
|
404
|
-
|
|
470
|
+
installMacService();
|
|
405
471
|
logOk('launchd start requested');
|
|
406
472
|
return;
|
|
407
473
|
}
|
|
@@ -420,39 +486,49 @@ function cmdStop() {
|
|
|
420
486
|
const platform = detectPlatform();
|
|
421
487
|
|
|
422
488
|
if (platform === 'macos' && fs.existsSync(PLIST_DST)) {
|
|
489
|
+
const domain = launchctlDomain();
|
|
490
|
+
if (domain) {
|
|
491
|
+
runQuiet('launchctl', ['bootout', domain, PLIST_DST]);
|
|
492
|
+
runQuiet('launchctl', ['bootout', launchctlServiceTarget()]);
|
|
493
|
+
}
|
|
423
494
|
runQuiet('launchctl', ['unload', PLIST_DST]);
|
|
424
495
|
logOk('launchd stop requested');
|
|
425
|
-
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
if (platform === 'linux' && fs.existsSync(SYSTEMD_UNIT)) {
|
|
496
|
+
} else if (platform === 'linux' && fs.existsSync(SYSTEMD_UNIT)) {
|
|
429
497
|
runQuiet('systemctl', ['--user', 'stop', 'neoagent']);
|
|
430
498
|
logOk('systemd stop requested');
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
logWarn(`pid ${pid} not running`);
|
|
499
|
+
} else {
|
|
500
|
+
const pidPath = PID_FILE;
|
|
501
|
+
let stopped = false;
|
|
502
|
+
if (fs.existsSync(pidPath)) {
|
|
503
|
+
const pid = Number(fs.readFileSync(pidPath, 'utf8').trim());
|
|
504
|
+
if (Number.isFinite(pid) && pid > 0) {
|
|
505
|
+
try {
|
|
506
|
+
process.kill(pid, 'SIGTERM');
|
|
507
|
+
logOk(`Stopped pid ${pid}`);
|
|
508
|
+
stopped = true;
|
|
509
|
+
} catch {
|
|
510
|
+
logWarn(`pid ${pid} not running`);
|
|
511
|
+
}
|
|
445
512
|
}
|
|
513
|
+
fs.rmSync(pidPath, { force: true });
|
|
446
514
|
}
|
|
447
|
-
|
|
515
|
+
|
|
516
|
+
const port = loadEnvPort();
|
|
517
|
+
if (killByPort(port)) {
|
|
518
|
+
logOk(`Stopped process listening on port ${port}`);
|
|
519
|
+
stopped = true;
|
|
520
|
+
}
|
|
521
|
+
if (!stopped) logWarn('No running process found');
|
|
448
522
|
}
|
|
449
523
|
|
|
450
524
|
const port = loadEnvPort();
|
|
525
|
+
const { killed, processes } = killNeoAgentServerProcesses();
|
|
526
|
+
if (killed) {
|
|
527
|
+
logOk(`Stopped ${processes.length} extra NeoAgent process${processes.length === 1 ? '' : 'es'}`);
|
|
528
|
+
}
|
|
451
529
|
if (killByPort(port)) {
|
|
452
530
|
logOk(`Stopped process listening on port ${port}`);
|
|
453
|
-
stopped = true;
|
|
454
531
|
}
|
|
455
|
-
if (!stopped) logWarn('No running process found');
|
|
456
532
|
}
|
|
457
533
|
|
|
458
534
|
function cmdRestart() {
|
|
@@ -496,15 +572,15 @@ async function cmdStatus() {
|
|
|
496
572
|
logWarn(`not reachable on port ${port}`);
|
|
497
573
|
}
|
|
498
574
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
console.log(` version ${gitVersion.stdout.trim().replace(/^v/, '')}`);
|
|
502
|
-
return;
|
|
503
|
-
}
|
|
575
|
+
console.log(` install root ${APP_DIR}`);
|
|
576
|
+
console.log(` version ${currentInstalledVersionLabel()}`);
|
|
504
577
|
|
|
505
|
-
const
|
|
506
|
-
if (
|
|
507
|
-
console.log(`
|
|
578
|
+
const processes = listNeoAgentServerProcesses();
|
|
579
|
+
if (processes.length > 0) {
|
|
580
|
+
console.log(` neoagent pids ${processes.map((proc) => proc.pid).join(', ')}`);
|
|
581
|
+
if (processes.length > 1) {
|
|
582
|
+
logWarn(`multiple NeoAgent server processes detected (${processes.length})`);
|
|
583
|
+
}
|
|
508
584
|
}
|
|
509
585
|
}
|
|
510
586
|
|
|
@@ -551,12 +627,12 @@ function cmdUpdate() {
|
|
|
551
627
|
if (commandExists('npm')) {
|
|
552
628
|
try {
|
|
553
629
|
backupRuntimeData();
|
|
554
|
-
runOrThrow('npm', ['install', '-g', 'neoagent@latest'], {
|
|
630
|
+
runOrThrow('npm', ['install', '-g', 'neoagent@latest', '--force'], {
|
|
555
631
|
env: withInstallEnv()
|
|
556
632
|
});
|
|
557
|
-
logOk('npm global update completed');
|
|
633
|
+
logOk('npm global update completed (forced reinstall)');
|
|
558
634
|
} catch {
|
|
559
|
-
logWarn('npm global update failed. Run: npm install -g neoagent@latest');
|
|
635
|
+
logWarn('npm global update failed. Run: npm install -g neoagent@latest --force');
|
|
560
636
|
}
|
|
561
637
|
} else {
|
|
562
638
|
logWarn('npm not found. Cannot perform global update.');
|
package/package.json
CHANGED
|
@@ -33,6 +33,7 @@ function buildHelmetOptions({ secureCookies }) {
|
|
|
33
33
|
'https://fonts.googleapis.com',
|
|
34
34
|
'https://fonts.gstatic.com',
|
|
35
35
|
'https://www.gstatic.com',
|
|
36
|
+
'https://api.qrserver.com',
|
|
36
37
|
...wsConnectSrc
|
|
37
38
|
],
|
|
38
39
|
fontSrc: ["'self'", 'data:', 'https://fonts.gstatic.com'],
|
|
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"052f31d115eceda8cbff1b3481fcde4330c4ae
|
|
|
37
37
|
|
|
38
38
|
_flutter.loader.load({
|
|
39
39
|
serviceWorkerSettings: {
|
|
40
|
-
serviceWorkerVersion: "
|
|
40
|
+
serviceWorkerVersion: "2457264468" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
|
|
41
41
|
}
|
|
42
42
|
});
|