@remcp/remcp 0.2.26 → 0.2.27
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/package.json +1 -1
- package/src/agent.mjs +12 -1
- package/src/cli.mjs +22 -4
package/package.json
CHANGED
package/src/agent.mjs
CHANGED
|
@@ -531,10 +531,21 @@ export async function runAgent(options) {
|
|
|
531
531
|
child.stderr?.on('data', forward);
|
|
532
532
|
child.on('exit', code => {
|
|
533
533
|
updateInFlight = false;
|
|
534
|
-
|
|
534
|
+
// The updater installs the packages and then restarts the service this agent runs in, so it is
|
|
535
|
+
// routinely killed by that restart and exits with a signal (`code` is null). That is success,
|
|
536
|
+
// not failure: the installed version is the proof. Without this check the agent kept
|
|
537
|
+
// reinstalling every few seconds — each cycle taking the device offline and making every tool
|
|
538
|
+
// call in that window fail in 1-3 ms ("Device is offline").
|
|
539
|
+
const targetVersion = String(target).split('@').pop();
|
|
540
|
+
const installedNow = globalInstalledVersion();
|
|
541
|
+
const installedTarget = installedNow && targetVersion && !isNewer(targetVersion, installedNow);
|
|
542
|
+
if (code !== 0 && !installedTarget) {
|
|
535
543
|
console.error(`remcp update exited with ${code}; keeping ${VERSION} and retrying after the cooldown.`);
|
|
536
544
|
return;
|
|
537
545
|
}
|
|
546
|
+
if (code !== 0) {
|
|
547
|
+
console.error(`remcp update was terminated (${code}) after installing ${installedNow}; applying it.`);
|
|
548
|
+
}
|
|
538
549
|
void restartToApplyUpdate(cli, stop, () => { stopping = true; }, async () => {
|
|
539
550
|
// The packages are installed now: clear the failure, reset the backoff and start again.
|
|
540
551
|
runtimeRestartDelay = RUNTIME_RESTART_BASE_MS;
|
package/src/cli.mjs
CHANGED
|
@@ -255,9 +255,25 @@ function ensureServiceIfRecorded(config) {
|
|
|
255
255
|
try {
|
|
256
256
|
const cliPath = globalCliPath();
|
|
257
257
|
const platform = servicePlatform();
|
|
258
|
-
if (platform === 'linux') {
|
|
259
|
-
|
|
260
|
-
|
|
258
|
+
if (platform === 'linux') {
|
|
259
|
+
if (!fs.existsSync(linuxServiceFile)) {
|
|
260
|
+
installLinuxService(cliPath);
|
|
261
|
+
} else {
|
|
262
|
+
// Node managers can move the global npm prefix between updates (nvm -> Hermes was observed in
|
|
263
|
+
// production). An existing systemd unit then keeps launching the old CLI forever even though
|
|
264
|
+
// npm successfully installed the new one. Repair the launcher in place before restarting it.
|
|
265
|
+
const unit = fs.readFileSync(linuxServiceFile, 'utf8');
|
|
266
|
+
const expected = `ExecStart=${quoteSystemd(cliPath)} start`;
|
|
267
|
+
if (!unit.includes(expected)) {
|
|
268
|
+
const repaired = unit.replace(/^ExecStart=.*$/m, expected);
|
|
269
|
+
if (repaired === unit) throw new Error('remcp-agent.service has no ExecStart line to repair');
|
|
270
|
+
fs.writeFileSync(linuxServiceFile, repaired);
|
|
271
|
+
run('systemctl', ['--user', 'daemon-reload']);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
} else if (platform === 'darwin') {
|
|
275
|
+
if (!fs.existsSync(macServiceFile)) installMacService(cliPath);
|
|
276
|
+
} else if (platform === 'win32') installWindowsService(cliPath);
|
|
261
277
|
return true;
|
|
262
278
|
} catch (error) {
|
|
263
279
|
console.error(`Could not ensure the background service: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -646,9 +662,11 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
646
662
|
return;
|
|
647
663
|
}
|
|
648
664
|
const before = { cli: VERSION, runtime: installedVersion(cfg.runtime.packageName) };
|
|
649
|
-
ensureServiceIfRecorded(cfg);
|
|
650
665
|
console.log(`Updating ReMCP to the latest published version (${runtimeSpec})…`);
|
|
651
666
|
npmGlobalInstall(`${PACKAGE_NAME}@latest`, runtimeSpec);
|
|
667
|
+
// The npm prefix can change across Node-manager upgrades. Repair an existing persistent-service
|
|
668
|
+
// launcher only after the install, when globalCliPath() points at the CLI we just installed.
|
|
669
|
+
ensureServiceIfRecorded(cfg);
|
|
652
670
|
// Only a validated spec is persisted, so a failed update cannot leave the install unable to start.
|
|
653
671
|
if (requested && runtimeSpec !== cfg.runtime.packageSpec) saveConfig({ ...cfg, runtime: { ...cfg.runtime, packageSpec: runtimeSpec } });
|
|
654
672
|
const after = { cli: installedVersion(PACKAGE_NAME), runtime: installedVersion(cfg.runtime.packageName) };
|