@remcp/remcp 0.2.237 → 0.2.239
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 +2 -2
- package/src/cli/service-inventory.mjs +6 -4
- package/src/cli/service-linux.mjs +95 -0
- package/src/cli/service.mjs +50 -19
- package/src/cli/update.mjs +2 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remcp/remcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.239",
|
|
4
4
|
"description": "ReMCP device client: pair a computer with ReMCP and run the outbound-only agent that hosts the local MCP runtime.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"README.md"
|
|
19
19
|
],
|
|
20
20
|
"scripts": {
|
|
21
|
-
"check": "node --check bin/remcp.mjs && node --check src/agent-deploy-reconnect.mjs && node --check src/agent-network-probe-client.mjs && node --check src/agent-relay-connection.mjs && node --check src/agent-responder.mjs && node --check src/agent-runtime-capabilities.mjs && node --check src/agent-update-monitor.mjs && node --check src/agent-update-rollout.mjs && node --check src/agent-update.mjs && node --check src/agent-utilities.mjs && node --check src/agent.mjs && node --check src/cli.mjs && node --check src/cli/config.mjs && node --check src/cli/connect.mjs && node --check src/cli/doctor.mjs && node --check src/cli/env.mjs && node --check src/cli/installation-audit.mjs && node --check src/cli/mac-native-temperature.mjs && node --check src/cli/npm-global.mjs && node --check src/cli/pairing-qr.mjs && node --check src/cli/service-inventory.mjs && node --check src/cli/service-macos.mjs && node --check src/cli/service-paths.mjs && node --check src/cli/service.mjs && node --check src/cli/shell.mjs && node --check src/cli/supervised-agent-lifecycle.mjs && node --check src/cli/update.mjs && node --check src/cli/windows-cli-shim.mjs && node --check src/cli/windows-owned-job-source.mjs && node --check src/cli/windows-owned-job.mjs && node --check src/cli/windows-supervisor.mjs && node --check src/cli/windows-update-lock.mjs && node --check src/cli/windows-user-supervisor.mjs && node --check src/fetch-update-manifest.mjs && node --check src/fs-access.mjs && node --check src/npm.mjs && node --check src/runtime.mjs && node --check src/version.mjs",
|
|
21
|
+
"check": "node --check bin/remcp.mjs && node --check src/agent-deploy-reconnect.mjs && node --check src/agent-network-probe-client.mjs && node --check src/agent-relay-connection.mjs && node --check src/agent-responder.mjs && node --check src/agent-runtime-capabilities.mjs && node --check src/agent-update-monitor.mjs && node --check src/agent-update-rollout.mjs && node --check src/agent-update.mjs && node --check src/agent-utilities.mjs && node --check src/agent.mjs && node --check src/cli.mjs && node --check src/cli/config.mjs && node --check src/cli/connect.mjs && node --check src/cli/doctor.mjs && node --check src/cli/env.mjs && node --check src/cli/installation-audit.mjs && node --check src/cli/mac-native-temperature.mjs && node --check src/cli/npm-global.mjs && node --check src/cli/pairing-qr.mjs && node --check src/cli/service-inventory.mjs && node --check src/cli/service-linux.mjs && node --check src/cli/service-macos.mjs && node --check src/cli/service-paths.mjs && node --check src/cli/service.mjs && node --check src/cli/shell.mjs && node --check src/cli/supervised-agent-lifecycle.mjs && node --check src/cli/update.mjs && node --check src/cli/windows-cli-shim.mjs && node --check src/cli/windows-owned-job-source.mjs && node --check src/cli/windows-owned-job.mjs && node --check src/cli/windows-supervisor.mjs && node --check src/cli/windows-update-lock.mjs && node --check src/cli/windows-user-supervisor.mjs && node --check src/fetch-update-manifest.mjs && node --check src/fs-access.mjs && node --check src/npm.mjs && node --check src/runtime.mjs && node --check src/version.mjs",
|
|
22
22
|
"test": "node --test test/*.test.mjs"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
@@ -5,6 +5,7 @@ import { spawnSync } from 'node:child_process';
|
|
|
5
5
|
import { PACKAGE_NAME, VERSION } from '../version.mjs';
|
|
6
6
|
import { saveConfig } from './config.mjs';
|
|
7
7
|
import { linuxServiceFile, linuxServiceLauncherFile, macServiceFile, macServiceLabel, windowsStartupScriptFile, windowsTaskName } from './env.mjs';
|
|
8
|
+
import { linuxSystemAgentOwned } from './service-linux.mjs';
|
|
8
9
|
import { servicePlatform, globalCliPath, npmGlobalUpdateForNode } from './npm-global.mjs';
|
|
9
10
|
import { windowsStartupScriptInstalled } from './windows-supervisor.mjs';
|
|
10
11
|
|
|
@@ -12,7 +13,7 @@ export function persistentServiceExpected(config) {
|
|
|
12
13
|
if (config?.serviceInstalled === false) return false;
|
|
13
14
|
if (config?.serviceInstalled === true) return true;
|
|
14
15
|
const platform = servicePlatform();
|
|
15
|
-
if (platform === 'linux') return fs.existsSync(linuxServiceFile);
|
|
16
|
+
if (platform === 'linux') return linuxSystemAgentOwned() || fs.existsSync(linuxServiceFile);
|
|
16
17
|
if (platform === 'darwin') return fs.existsSync(macServiceFile);
|
|
17
18
|
if (platform === 'win32') {
|
|
18
19
|
return windowsStartupScriptInstalled(windowsStartupScriptFile) ||
|
|
@@ -25,9 +26,10 @@ export function persistentServiceState(config) {
|
|
|
25
26
|
const platform = servicePlatform();
|
|
26
27
|
const expected = persistentServiceExpected(config);
|
|
27
28
|
if (platform === 'linux') {
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
29
|
+
const system = linuxSystemAgentOwned();
|
|
30
|
+
const installed = system || fs.existsSync(linuxServiceFile);
|
|
31
|
+
const active = installed && spawnSync('systemctl', [...(system ? [] : ['--user']), 'is-active', '--quiet', 'remcp-agent.service'], { stdio: 'ignore' }).status === 0;
|
|
32
|
+
return { expected, installed, active, manager:system ? 'systemd-system' : 'systemd-user', name:'remcp-agent.service' };
|
|
31
33
|
}
|
|
32
34
|
if (platform === 'darwin') {
|
|
33
35
|
const installed = fs.existsSync(macServiceFile);
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Linux headless agents may be supervised by PID 1. Never mistake a system unit for
|
|
2
|
+
// a session-owned user unit during status checks, repairs or auto-updates.
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import process from 'node:process';
|
|
7
|
+
import { spawnSync } from 'node:child_process';
|
|
8
|
+
import { home, linuxServiceFile, linuxServiceLauncherFile } from './env.mjs';
|
|
9
|
+
import { resolvedCliScript, shellQuote } from './service-paths.mjs';
|
|
10
|
+
|
|
11
|
+
export const linuxSystemServiceFile = '/etc/systemd/system/remcp-agent.service';
|
|
12
|
+
|
|
13
|
+
export function isManagedLinuxSystemUnit(text, launcher = linuxServiceLauncherFile) {
|
|
14
|
+
if (typeof text !== 'string') return false;
|
|
15
|
+
const expected = new Set([
|
|
16
|
+
'ExecStart="' + launcher.replaceAll('\\', '\\\\').replaceAll('"', '\\"') + '" start --service',
|
|
17
|
+
'ExecStart=' + launcher + ' start --service',
|
|
18
|
+
]);
|
|
19
|
+
return text.split(/\r?\n/).some(line => expected.has(line.trim()));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function linuxSystemAgentOwned() {
|
|
23
|
+
if (process.platform !== 'linux' || process.getuid?.() !== 0) return false;
|
|
24
|
+
try {
|
|
25
|
+
return isManagedLinuxSystemUnit(fs.readFileSync(linuxSystemServiceFile, 'utf8'));
|
|
26
|
+
} catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function linuxServiceScope() {
|
|
32
|
+
return linuxSystemAgentOwned() ? 'system' : 'user';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function linuxActiveServiceFile() {
|
|
36
|
+
return linuxServiceScope() === 'system' ? linuxSystemServiceFile : linuxServiceFile;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Without linger, logind terminates user@UID.service at the final logout,
|
|
40
|
+
// even if systemctl --user enable --now reported success.
|
|
41
|
+
export function ensureLinuxLinger() {
|
|
42
|
+
if (process.platform !== 'linux') return;
|
|
43
|
+
// Test-only synthetic HOME has no logind account and must never mutate the host.
|
|
44
|
+
// Guard before os.userInfo(): an isolated CI UID may not have a passwd entry.
|
|
45
|
+
if (process.env.NODE_ENV === 'test' && process.env.REMCP_TEST_PLATFORM === 'linux') return;
|
|
46
|
+
let account;
|
|
47
|
+
try { account = os.userInfo(); }
|
|
48
|
+
catch { throw new Error('ReMCP cannot resolve the current Linux account for persistent systemd supervision.'); }
|
|
49
|
+
if (path.resolve(home) !== path.resolve(account.homedir)) {
|
|
50
|
+
throw new Error('Refusing a persistent Linux service with HOME different from the account home directory.');
|
|
51
|
+
}
|
|
52
|
+
const username = account.username;
|
|
53
|
+
const query = () => spawnSync('loginctl', ['show-user', username, '-p', 'Linger', '--value'],
|
|
54
|
+
{ encoding:'utf8', timeout:10000 });
|
|
55
|
+
let state = query();
|
|
56
|
+
if (state.status === 0 && state.stdout.trim() === 'yes') return;
|
|
57
|
+
const enabled = spawnSync('loginctl', ['enable-linger', username],
|
|
58
|
+
{ encoding:'utf8', timeout:10000 });
|
|
59
|
+
if (enabled.status !== 0) {
|
|
60
|
+
throw new Error('ReMCP cannot guarantee background operation after logout: '
|
|
61
|
+
+ 'loginctl enable-linger failed. Ask an administrator to enable lingering for this account.');
|
|
62
|
+
}
|
|
63
|
+
state = query();
|
|
64
|
+
if (state.status !== 0 || state.stdout.trim() !== 'yes') {
|
|
65
|
+
throw new Error('ReMCP cannot verify systemd lingering; refusing to claim persistent installation.');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// The vetted bootstrap may install npm under ~/.local/share/remcp/npm and Node
|
|
70
|
+
// under ~/.local/share/remcp/bootstrap; neither bin is necessarily on login PATH.
|
|
71
|
+
export function linuxCliShimText(cliPath, nodePath) {
|
|
72
|
+
const entry = resolvedCliScript(cliPath);
|
|
73
|
+
const suffix = path.join('lib', 'node_modules', '@remcp', 'remcp', 'bin', 'remcp.mjs');
|
|
74
|
+
const prefix = entry.endsWith(path.sep + suffix)
|
|
75
|
+
? entry.slice(0, -(suffix.length + 1)) : path.dirname(path.dirname(cliPath));
|
|
76
|
+
return '#!/bin/sh\n# ReMCP managed CLI shim\nNPM_CONFIG_PREFIX=' + shellQuote(prefix)
|
|
77
|
+
+ '\nexport NPM_CONFIG_PREFIX\nPATH=' + shellQuote(path.dirname(nodePath)) + ':$PATH'
|
|
78
|
+
+ '\nexport PATH\nexec ' + shellQuote(nodePath) + ' ' + shellQuote(entry) + ' "$@"\n';
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function ensureLinuxCliCommand(cliPath, nodePath) {
|
|
82
|
+
if (process.platform !== 'linux') return;
|
|
83
|
+
const destination = process.getuid?.() === 0
|
|
84
|
+
? '/usr/local/bin/remcp' : path.join(home, '.local', 'bin', 'remcp');
|
|
85
|
+
fs.mkdirSync(path.dirname(destination), { recursive:true, mode:0o755 });
|
|
86
|
+
const marker = '# ReMCP managed CLI shim';
|
|
87
|
+
if (fs.existsSync(destination)) {
|
|
88
|
+
const current = fs.readFileSync(destination, 'utf8');
|
|
89
|
+
if (!current.includes(marker)) return; // Never overwrite an unrelated executable.
|
|
90
|
+
}
|
|
91
|
+
const content = linuxCliShimText(cliPath, nodePath);
|
|
92
|
+
const temp = destination + '.' + process.pid + '.tmp';
|
|
93
|
+
fs.writeFileSync(temp, content, { mode:0o755 });
|
|
94
|
+
fs.renameSync(temp, destination);
|
|
95
|
+
}
|
package/src/cli/service.mjs
CHANGED
|
@@ -5,6 +5,7 @@ export { persistentServiceExpected, persistentServiceState, releasePairPresentAt
|
|
|
5
5
|
// Installing, repairing and removing the background agent: one supervisor per platform, plus the
|
|
6
6
|
// write-access tweaks a fresh install needs. Service maintenance follows local OS permissions.
|
|
7
7
|
import fs from 'node:fs';
|
|
8
|
+
import os from 'node:os';
|
|
8
9
|
import path from 'node:path';
|
|
9
10
|
import process from 'node:process';
|
|
10
11
|
import { spawnSync } from 'node:child_process';
|
|
@@ -17,6 +18,7 @@ import { PACKAGE_NAME, VERSION } from '../version.mjs';
|
|
|
17
18
|
import { saveConfig } from './config.mjs';
|
|
18
19
|
import { configDir, home, linuxServiceFile, linuxServiceLauncherFile, macServiceFile, macServiceLabel, windowsServiceLauncherFile, windowsStartupScriptFile, windowsTaskName } from './env.mjs';
|
|
19
20
|
import { run } from './shell.mjs';
|
|
21
|
+
import { linuxActiveServiceFile, linuxServiceScope, linuxSystemAgentOwned, linuxSystemServiceFile, ensureLinuxLinger, ensureLinuxCliCommand } from './service-linux.mjs';
|
|
20
22
|
import { windowsServiceLauncherText, windowsTaskAbsenceCommand, windowsStartupScriptText, windowsStartupScriptInstalled } from './windows-supervisor.mjs';
|
|
21
23
|
import { ensureWindowsSupervisorKey, windowsSupervisorCommand } from './windows-user-supervisor.mjs';
|
|
22
24
|
|
|
@@ -62,11 +64,32 @@ function writeLinuxServiceLauncher(cliPath = globalCliPath(), nodePath = process
|
|
|
62
64
|
|
|
63
65
|
export function installLinuxService(cliPath = globalCliPath(), nodePath = process.execPath) {
|
|
64
66
|
const launcherFile = writeLinuxServiceLauncher(cliPath, nodePath);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
// Fresh root installs are boot services owned by PID 1. Legacy per-user units are
|
|
68
|
+
// left under their existing supervisor, but must have linger enabled.
|
|
69
|
+
const syntheticLinuxFixture = process.env.NODE_ENV === 'test' && process.env.REMCP_TEST_PLATFORM === 'linux';
|
|
70
|
+
const privileged = !syntheticLinuxFixture && process.getuid?.() === 0
|
|
71
|
+
&& path.resolve(home) === path.resolve(os.userInfo().homedir);
|
|
72
|
+
if (privileged && fs.existsSync(linuxSystemServiceFile) && !linuxSystemAgentOwned()) {
|
|
73
|
+
throw new Error('Refusing to replace an unmanaged systemd remcp-agent.service');
|
|
74
|
+
}
|
|
75
|
+
const system = privileged && (linuxSystemAgentOwned() || !fs.existsSync(linuxServiceFile));
|
|
76
|
+
if (system) {
|
|
77
|
+
if (fs.existsSync(linuxSystemServiceFile) && !linuxSystemAgentOwned()) {
|
|
78
|
+
throw new Error('Refusing to replace an unmanaged systemd remcp-agent.service');
|
|
79
|
+
}
|
|
80
|
+
const unit = `[Unit]\nDescription=ReMCP headless device agent (system service)\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\nUser=root\nWorkingDirectory=/root\nEnvironment=HOME=/root\nUMask=0077\nExecStart=${quoteSystemd(launcherFile)} start --service\nRestart=always\nRestartSec=5\n\n[Install]\nWantedBy=multi-user.target\n`;
|
|
81
|
+
fs.writeFileSync(linuxSystemServiceFile, unit, { mode:0o644 });
|
|
82
|
+
run('systemctl', ['daemon-reload']);
|
|
83
|
+
run('systemctl', ['enable', '--now', 'remcp-agent.service']);
|
|
84
|
+
} else {
|
|
85
|
+
ensureLinuxLinger();
|
|
86
|
+
const unit = `[Unit]\nDescription=ReMCP device agent\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\nExecStart=${quoteSystemd(launcherFile)} start --service\nRestart=always\nRestartSec=3\n\n[Install]\nWantedBy=default.target\n`;
|
|
87
|
+
fs.mkdirSync(path.dirname(linuxServiceFile), { recursive: true });
|
|
88
|
+
fs.writeFileSync(linuxServiceFile, unit);
|
|
89
|
+
run('systemctl', ['--user', 'daemon-reload']);
|
|
90
|
+
run('systemctl', ['--user', 'enable', '--now', 'remcp-agent.service']);
|
|
91
|
+
}
|
|
92
|
+
ensureLinuxCliCommand(cliPath, nodePath);
|
|
70
93
|
}
|
|
71
94
|
|
|
72
95
|
export function writeWindowsServiceLauncher(cliPath = globalCliPath(), nodePath = process.execPath) {
|
|
@@ -241,11 +264,13 @@ export function ensureServiceIfRecorded(config) {
|
|
|
241
264
|
const platform = servicePlatform();
|
|
242
265
|
let restartScheduled = null;
|
|
243
266
|
if (platform === 'linux') {
|
|
244
|
-
|
|
245
|
-
|
|
267
|
+
const scope = linuxServiceScope();
|
|
268
|
+
if (scope === 'user') ensureLinuxLinger();
|
|
269
|
+
// Read and repair the active unit through one descriptor. Never create a
|
|
270
|
+
// second user agent when a PID-1 system service already owns this pairing.
|
|
246
271
|
let fd = null;
|
|
247
272
|
try {
|
|
248
|
-
fd = fs.openSync(
|
|
273
|
+
fd = fs.openSync(linuxActiveServiceFile(), fs.constants.O_RDWR | (fs.constants.O_NOFOLLOW || 0));
|
|
249
274
|
} catch (error) {
|
|
250
275
|
if (error?.code !== 'ENOENT') throw error;
|
|
251
276
|
}
|
|
@@ -279,7 +304,7 @@ export function ensureServiceIfRecorded(config) {
|
|
|
279
304
|
}
|
|
280
305
|
fs.ftruncateSync(fd, data.length);
|
|
281
306
|
fs.fsyncSync(fd);
|
|
282
|
-
run('systemctl', ['--user', 'daemon-reload']);
|
|
307
|
+
run('systemctl', [...(scope === 'user' ? ['--user'] : []), 'daemon-reload']);
|
|
283
308
|
}
|
|
284
309
|
} finally {
|
|
285
310
|
fs.closeSync(fd);
|
|
@@ -308,24 +333,28 @@ export function ensureServiceIfRecorded(config) {
|
|
|
308
333
|
}
|
|
309
334
|
}
|
|
310
335
|
|
|
311
|
-
export function deferredLinuxAgentRestartArgs(pid) {
|
|
336
|
+
export function deferredLinuxAgentRestartArgs(pid, scope = 'user') {
|
|
312
337
|
if (!Number.isSafeInteger(pid) || pid <= 0) throw new Error('Invalid process identifier');
|
|
313
|
-
|
|
314
|
-
|
|
338
|
+
if (scope !== 'user' && scope !== 'system') throw new Error('Invalid Linux service scope');
|
|
339
|
+
const option = scope === 'user' ? ['--user'] : [];
|
|
340
|
+
return [...option, '--on-active=3s', `--unit=remcp-agent-settings-${pid}`,
|
|
341
|
+
'systemctl', ...option, 'restart', 'remcp-agent.service'];
|
|
315
342
|
}
|
|
316
343
|
|
|
317
344
|
export function restartPersistentServiceIfInstalled(config, { deferLinux = false, deferWindows = false } = {}) {
|
|
318
345
|
if (!persistentServiceExpected(config)) return null;
|
|
319
346
|
const platform = servicePlatform();
|
|
320
|
-
if (platform === 'linux' && fs.existsSync(
|
|
347
|
+
if (platform === 'linux' && fs.existsSync(linuxActiveServiceFile())) {
|
|
348
|
+
const scope = linuxServiceScope();
|
|
349
|
+
const option = scope === 'user' ? ['--user'] : [];
|
|
321
350
|
// Only owner-confirmed remote policy changes defer their restart. Ordinary
|
|
322
351
|
// installs and updates preserve their existing synchronous supervisor contract.
|
|
323
352
|
if (deferLinux) {
|
|
324
|
-
run('systemd-run', deferredLinuxAgentRestartArgs(process.pid));
|
|
353
|
+
run('systemd-run', deferredLinuxAgentRestartArgs(process.pid, scope));
|
|
325
354
|
return 'remcp-agent.service (restart scheduled)';
|
|
326
355
|
}
|
|
327
|
-
run('systemctl', [
|
|
328
|
-
run('systemctl', [
|
|
356
|
+
run('systemctl', [...option, 'daemon-reload']);
|
|
357
|
+
run('systemctl', [...option, 'restart', 'remcp-agent.service']);
|
|
329
358
|
return 'remcp-agent.service';
|
|
330
359
|
}
|
|
331
360
|
if (platform === 'darwin' && fs.existsSync(macServiceFile)) {
|
|
@@ -357,9 +386,11 @@ export function restartPersistentServiceIfInstalled(config, { deferLinux = false
|
|
|
357
386
|
export function uninstallPersistentService() {
|
|
358
387
|
const platform = servicePlatform();
|
|
359
388
|
if (platform === 'linux') {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
spawnSync('systemctl', ['--
|
|
389
|
+
const scope = linuxServiceScope();
|
|
390
|
+
const option = scope === 'user' ? ['--user'] : [];
|
|
391
|
+
spawnSync('systemctl', [...option, 'disable', '--now', 'remcp-agent.service'], { stdio:'inherit' });
|
|
392
|
+
try { fs.unlinkSync(linuxActiveServiceFile()); } catch {}
|
|
393
|
+
spawnSync('systemctl', [...option, 'daemon-reload'], { stdio:'inherit' });
|
|
363
394
|
} else if (platform === 'darwin') {
|
|
364
395
|
const domain = macLaunchDomain();
|
|
365
396
|
spawnSync('launchctl', ['bootout', domain, macServiceFile], { stdio: 'ignore' });
|
package/src/cli/update.mjs
CHANGED
|
@@ -12,6 +12,7 @@ import { loadConfig, saveConfig } from './config.mjs';
|
|
|
12
12
|
import { assertSecureServerUrl } from './connect.mjs';
|
|
13
13
|
import { installedVersion } from './doctor.mjs';
|
|
14
14
|
import { linuxServiceFile, macServiceFile, officialOrigin } from './env.mjs';
|
|
15
|
+
import { linuxSystemAgentOwned } from './service-linux.mjs';
|
|
15
16
|
import { assertWindowsUpdateLifecycleSafe, currentInstallationInfo, ensureMacCliCommand, ensureServiceIfRecorded, npmGlobalUpdate, persistentServiceExpected, rememberCurrentInstallation, restartPersistentServiceIfInstalled, servicePlatform, serviceInstallationInfo, syncKnownInstallations } from './service.mjs';
|
|
16
17
|
|
|
17
18
|
const UPDATE_DISCOVERY_TIMEOUT_MS = 5000;
|
|
@@ -235,7 +236,7 @@ export async function updateCommand(flags) {
|
|
|
235
236
|
updateSource: targets.source,
|
|
236
237
|
installable: targets.installable,
|
|
237
238
|
upToDate: alreadyCurrent,
|
|
238
|
-
managedService: fs.existsSync(linuxServiceFile) || fs.existsSync(macServiceFile),
|
|
239
|
+
managedService: linuxSystemAgentOwned() || fs.existsSync(linuxServiceFile) || fs.existsSync(macServiceFile),
|
|
239
240
|
supervisor: supervisorRestart() ?? 'none',
|
|
240
241
|
}, null, 2));
|
|
241
242
|
return;
|