@remcp/remcp 0.2.45 → 0.2.46

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/cli/service.mjs +32 -12
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remcp/remcp",
3
- "version": "0.2.45",
3
+ "version": "0.2.46",
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",
@@ -65,23 +65,41 @@ function macJobLoaded(target) {
65
65
  return spawnSync('launchctl', ['print', target], { stdio: 'ignore' }).status === 0;
66
66
  }
67
67
 
68
- function scheduleMacServiceReload(domain, target) {
68
+ function submitMacHelper(kind, lines) {
69
69
  fs.mkdirSync(configDir, { recursive: true, mode: 0o700 });
70
- const helperFile = path.join(configDir, `launchd-reload-${process.pid}.sh`);
71
- const helperLabel = `${macServiceLabel}.reload.${process.pid}`;
70
+ const nonce = `${process.pid}.${Date.now()}`;
71
+ const helperFile = path.join(configDir, `launchd-${kind}-${nonce}.sh`);
72
+ const helperLabel = `${macServiceLabel}.${kind}.${nonce}`;
72
73
  const script = [
73
74
  '#!/bin/sh',
74
75
  'sleep 1',
75
- `launchctl bootout ${shellQuote(target)} >/dev/null 2>&1 || true`,
76
- `launchctl bootstrap ${shellQuote(domain)} ${shellQuote(macServiceFile)}`,
77
- `launchctl enable ${shellQuote(target)}`,
78
- `launchctl kickstart -k ${shellQuote(target)}`,
76
+ 'status=0',
77
+ ...lines.map(line => `${line} || status=$?`),
78
+ `if [ "$status" -ne 0 ]; then echo "ReMCP launchd ${kind} helper failed with status $status" >> ${shellQuote(macLogFile)}; fi`,
79
79
  `rm -f ${shellQuote(helperFile)}`,
80
+ `launchctl remove ${shellQuote(helperLabel)} >/dev/null 2>&1 || true`,
81
+ 'exit 0',
80
82
  '',
81
83
  ].join('\n');
82
84
  fs.writeFileSync(helperFile, script, { mode: 0o700 });
83
85
  fs.chmodSync(helperFile, 0o700);
84
86
  run('launchctl', ['submit', '-l', helperLabel, '--', '/bin/sh', helperFile]);
87
+ return helperLabel;
88
+ }
89
+
90
+ function scheduleMacServiceReload(domain, target) {
91
+ return submitMacHelper('reload', [
92
+ `launchctl bootout ${shellQuote(target)} >/dev/null 2>&1 || true`,
93
+ `launchctl bootstrap ${shellQuote(domain)} ${shellQuote(macServiceFile)}`,
94
+ `launchctl enable ${shellQuote(target)}`,
95
+ `launchctl kickstart -k ${shellQuote(target)}`,
96
+ ]);
97
+ }
98
+
99
+ function scheduleMacServiceRestart(target) {
100
+ return submitMacHelper('restart', [
101
+ `launchctl kickstart -k ${shellQuote(target)}`,
102
+ ]);
85
103
  }
86
104
 
87
105
  export function installMacService(cliPath = globalCliPath(), { restart = true } = {}) {
@@ -255,12 +273,14 @@ export function restartPersistentServiceIfInstalled(config) {
255
273
  return 'remcp-agent.service';
256
274
  }
257
275
  if (platform === 'darwin' && fs.existsSync(macServiceFile)) {
258
- try {
259
- run('launchctl', ['kickstart', '-k', `${macLaunchDomain()}/${macServiceLabel}`]);
260
- } catch {
276
+ const target = `${macLaunchDomain()}/${macServiceLabel}`;
277
+ if (macJobLoaded(target)) {
278
+ // Never kill a loaded LaunchAgent inline: the caller may itself be a child of that job.
279
+ // A transient helper survives the handoff and performs the restart after this CLI returns.
280
+ scheduleMacServiceRestart(target);
281
+ } else {
261
282
  // A plist can survive while launchd has no loaded job (older installs, logout/login cleanup,
262
- // manual bootout, or a failed previous update). Re-register the job instead of surfacing the
263
- // opaque launchctl 113 error. installMacService is idempotent and rewrites stale Node paths too.
283
+ // manual bootout, or a failed previous update). Re-register it directly.
264
284
  installMacService(globalCliPath());
265
285
  }
266
286
  return macServiceLabel;