@remcp/remcp 0.2.116 → 0.2.117
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/README.md +6 -4
- package/package.json +1 -1
- package/src/cli/env.mjs +1 -0
- package/src/cli/service.mjs +46 -10
package/README.md
CHANGED
|
@@ -9,10 +9,12 @@ remcp --version
|
|
|
9
9
|
remcp status
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
Pairing commands are generated in the workspace at <https://remcp.site/app/connect>.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
Pairing commands are generated in the workspace at <https://remcp.site/app/connect>. On Windows,
|
|
13
|
+
the browser shows a PowerShell bootstrap that needs no preinstalled system Node.js/npm/npx/winget;
|
|
14
|
+
it keeps the ReMCP runtime under `%LOCALAPPDATA%\ReMCP`. Generated one-time commands ultimately run
|
|
15
|
+
`remcp connect --server … --code … --install`, which stores a per-device credential, installs the
|
|
16
|
+
runtime, and registers a user service (systemd on Linux, LaunchAgent on macOS, Scheduled Task on
|
|
17
|
+
Windows).
|
|
16
18
|
|
|
17
19
|
## Commands
|
|
18
20
|
|
package/package.json
CHANGED
package/src/cli/env.mjs
CHANGED
|
@@ -16,6 +16,7 @@ export const macServiceLabel = 'com.remcp.agent';
|
|
|
16
16
|
export const macServiceFile = path.join(home, 'Library', 'LaunchAgents', `${macServiceLabel}.plist`);
|
|
17
17
|
export const macLogFile = path.join(home, 'Library', 'Logs', 'remcp-agent.log');
|
|
18
18
|
export const windowsTaskName = 'ReMCP Agent';
|
|
19
|
+
export const windowsServiceLauncherFile = path.join(configDir, 'remcp-agent.cmd');
|
|
19
20
|
// How npm is invoked is resolved from the running node when possible: a background service has a
|
|
20
21
|
// minimal PATH, which is why auto-update used to find no npm on macOS. See src/npm.mjs.
|
|
21
22
|
export const npm = resolveNpm();
|
package/src/cli/service.mjs
CHANGED
|
@@ -9,7 +9,7 @@ import { resolveNpm } from '../npm.mjs';
|
|
|
9
9
|
import { PACKAGE_NAME, VERSION } from '../version.mjs';
|
|
10
10
|
|
|
11
11
|
import { saveConfig } from './config.mjs';
|
|
12
|
-
import { configDir, home, linuxServiceFile, linuxServiceLauncherFile, macLogFile, macServiceFile, macServiceLabel, npm, windowsTaskName } from './env.mjs';
|
|
12
|
+
import { configDir, home, linuxServiceFile, linuxServiceLauncherFile, macLogFile, macServiceFile, macServiceLabel, npm, windowsServiceLauncherFile, windowsTaskName } from './env.mjs';
|
|
13
13
|
import { output, run } from './shell.mjs';
|
|
14
14
|
|
|
15
15
|
export function servicePlatform() {
|
|
@@ -350,8 +350,32 @@ export function installMacService(cliPath = globalCliPath(), { restart = true, n
|
|
|
350
350
|
return 'bootstrapped';
|
|
351
351
|
}
|
|
352
352
|
|
|
353
|
-
|
|
354
|
-
|
|
353
|
+
function windowsBatchValue(value) {
|
|
354
|
+
return String(value).replaceAll('%', '%%');
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export function writeWindowsServiceLauncher(cliPath = globalCliPath(), nodePath = process.execPath) {
|
|
358
|
+
const prefix = path.dirname(cliPath);
|
|
359
|
+
const nodeDir = path.dirname(nodePath);
|
|
360
|
+
const launcher = [
|
|
361
|
+
'@echo off',
|
|
362
|
+
'setlocal DisableDelayedExpansion',
|
|
363
|
+
`set "NPM_CONFIG_PREFIX=${windowsBatchValue(prefix)}"`,
|
|
364
|
+
`set "PATH=${windowsBatchValue(nodeDir)};%PATH%"`,
|
|
365
|
+
`call "${windowsBatchValue(cliPath)}" start --service`,
|
|
366
|
+
'exit /b %ERRORLEVEL%',
|
|
367
|
+
'',
|
|
368
|
+
].join('\r\n');
|
|
369
|
+
fs.mkdirSync(configDir, { recursive:true, mode:0o700 });
|
|
370
|
+
const temporary = `${windowsServiceLauncherFile}.${process.pid}.${Date.now()}.tmp`;
|
|
371
|
+
fs.writeFileSync(temporary, launcher, { mode:0o700 });
|
|
372
|
+
fs.renameSync(temporary, windowsServiceLauncherFile);
|
|
373
|
+
return windowsServiceLauncherFile;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export function installWindowsService(cliPath = globalCliPath(), { nodePath = process.execPath } = {}) {
|
|
377
|
+
const launcherFile = writeWindowsServiceLauncher(cliPath, nodePath);
|
|
378
|
+
const command = `"${launcherFile}"`;
|
|
355
379
|
run('schtasks.exe', ['/Create', '/TN', windowsTaskName, '/TR', command, '/SC', 'ONLOGON', '/RL', 'HIGHEST', '/F']);
|
|
356
380
|
run('schtasks.exe', ['/Run', '/TN', windowsTaskName]);
|
|
357
381
|
}
|
|
@@ -450,13 +474,24 @@ function packageVersionBesideCli(cliPath, packageName) {
|
|
|
450
474
|
return versionFromPackageJson(path.join(nodeModules, ...String(packageName).split('/'), 'package.json'));
|
|
451
475
|
}
|
|
452
476
|
|
|
477
|
+
function packageVersionForCli(cliPath, packageName) {
|
|
478
|
+
const beside = packageVersionBesideCli(cliPath, packageName);
|
|
479
|
+
if (beside || servicePlatform() !== 'win32' || !cliPath || !packageName) return beside;
|
|
480
|
+
// npm's Windows global executable is a .cmd shim in the prefix root, not a symlink into
|
|
481
|
+
// node_modules. realpath() therefore cannot reveal the package directory like it does on Unix.
|
|
482
|
+
// Resolve the package from the same prefix layout npm uses on Windows.
|
|
483
|
+
if (path.basename(cliPath).toLowerCase() !== 'remcp.cmd') return null;
|
|
484
|
+
const prefix = path.dirname(cliPath);
|
|
485
|
+
return versionFromPackageJson(path.join(prefix, 'node_modules', ...String(packageName).split('/'), 'package.json'));
|
|
486
|
+
}
|
|
487
|
+
|
|
453
488
|
export function installationVersionsAtCliPath(cliPath, runtimePackageName) {
|
|
454
489
|
if (!cliPath) return { cliVersion:null, runtimeVersion:null, cliPath:null };
|
|
455
490
|
let resolvedCliPath = cliPath;
|
|
456
491
|
try { if (fs.existsSync(cliPath)) resolvedCliPath = fs.realpathSync(cliPath); } catch {}
|
|
457
492
|
return {
|
|
458
|
-
cliVersion:
|
|
459
|
-
runtimeVersion:
|
|
493
|
+
cliVersion:packageVersionForCli(resolvedCliPath, PACKAGE_NAME),
|
|
494
|
+
runtimeVersion:packageVersionForCli(resolvedCliPath, runtimePackageName),
|
|
460
495
|
cliPath:resolvedCliPath,
|
|
461
496
|
};
|
|
462
497
|
}
|
|
@@ -468,8 +503,8 @@ export function serviceInstallationInfo(config) {
|
|
|
468
503
|
let resolvedCliPath = cliPath;
|
|
469
504
|
try { if (cliPath && fs.existsSync(cliPath)) resolvedCliPath = fs.realpathSync(cliPath); } catch {}
|
|
470
505
|
return {
|
|
471
|
-
cliVersion:
|
|
472
|
-
runtimeVersion:
|
|
506
|
+
cliVersion:packageVersionForCli(resolvedCliPath, PACKAGE_NAME),
|
|
507
|
+
runtimeVersion:packageVersionForCli(resolvedCliPath, config?.runtime?.packageName),
|
|
473
508
|
cliPath:resolvedCliPath || cliPath,
|
|
474
509
|
nodePath,
|
|
475
510
|
};
|
|
@@ -480,7 +515,7 @@ export function currentInstallationInfo(config) {
|
|
|
480
515
|
try { if (cliPath && fs.existsSync(cliPath)) cliPath = fs.realpathSync(cliPath); } catch {}
|
|
481
516
|
return {
|
|
482
517
|
cliVersion:VERSION,
|
|
483
|
-
runtimeVersion:config?.runtime?.packageName ?
|
|
518
|
+
runtimeVersion:config?.runtime?.packageName ? packageVersionForCli(cliPath, config.runtime.packageName) : null,
|
|
484
519
|
cliPath:cliPath || null,
|
|
485
520
|
nodePath:process.execPath,
|
|
486
521
|
};
|
|
@@ -599,7 +634,7 @@ export function installPersistentAgent(config) {
|
|
|
599
634
|
else if (platform === 'darwin') {
|
|
600
635
|
installMacService(cliPath, { nodePath });
|
|
601
636
|
ensureMacCliCommand(config, { cliPath:cliScript, nodePath });
|
|
602
|
-
} else installWindowsService(cliPath);
|
|
637
|
+
} else installWindowsService(cliPath, { nodePath });
|
|
603
638
|
configurePostInstallAccess();
|
|
604
639
|
saveConfig({ ...config, serviceInstalled: true, serviceCliPath: cliScript, serviceNodePath: nodePath });
|
|
605
640
|
console.log('ReMCP is installed as a background service. Future updates: remcp update');
|
|
@@ -663,7 +698,7 @@ export function ensureServiceIfRecorded(config) {
|
|
|
663
698
|
const state = installMacService(cliPath, { restart: false, nodePath });
|
|
664
699
|
ensureMacCliCommand(config, { cliPath, nodePath });
|
|
665
700
|
if (state === 'reload-scheduled') restartScheduled = macServiceLabel;
|
|
666
|
-
} else if (platform === 'win32') installWindowsService(cliPath);
|
|
701
|
+
} else if (platform === 'win32') installWindowsService(cliPath, { nodePath });
|
|
667
702
|
// Upgrade the legacy inferred state only after the supervisor repair succeeded. A failed repair
|
|
668
703
|
// must not turn a stale artifact into a permanent "managed service" declaration.
|
|
669
704
|
const cliScript = resolvedCliScript(cliPath);
|
|
@@ -722,5 +757,6 @@ export function uninstallPersistentService() {
|
|
|
722
757
|
} else if (platform === 'win32') {
|
|
723
758
|
spawnSync('schtasks.exe', ['/End', '/TN', windowsTaskName], { stdio: 'ignore' });
|
|
724
759
|
spawnSync('schtasks.exe', ['/Delete', '/TN', windowsTaskName, '/F'], { stdio: 'ignore' });
|
|
760
|
+
try { fs.unlinkSync(windowsServiceLauncherFile); } catch {}
|
|
725
761
|
}
|
|
726
762
|
}
|