@remcp/remcp 0.2.7 → 0.2.9

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/agent.mjs +24 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remcp/remcp",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
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",
package/src/agent.mjs CHANGED
@@ -79,6 +79,21 @@ function isNewer(candidate, current) {
79
79
  return false;
80
80
  }
81
81
 
82
+ // What the agent should install, if anything. The client version alone is not enough: a machine
83
+ // that already runs the newest client but an older local runtime would otherwise never catch up,
84
+ // because its runtime is what executes the tools.
85
+ export function updateDecision({ advertised, cliVersion, runtimeVersion }) {
86
+ const cliSpec = String(advertised?.cli || '');
87
+ const runtimeSpec = String(advertised?.runtime || '');
88
+ const installedRuntime = String(runtimeVersion || '');
89
+ const runtimeKnown = Boolean(installedRuntime) && !/^unknown$/i.test(installedRuntime);
90
+ if (isNewer(cliSpec, cliVersion)) return { needed: true, target: cliSpec, runtime: runtimeSpec, reason: 'client' };
91
+ if (runtimeKnown && runtimeSpec && isNewer(runtimeSpec, installedRuntime)) {
92
+ return { needed: true, target: cliSpec || `@remcp/remcp@${cliVersion}`, runtime: runtimeSpec, reason: 'runtime' };
93
+ }
94
+ return { needed: false, target: cliSpec, runtime: runtimeSpec, reason: 'current' };
95
+ }
96
+
82
97
  function globalCliEntry() {
83
98
  const prefix = spawnSync(npmCommand, ['prefix', '--global'], { encoding: 'utf8' });
84
99
  if (prefix.error || prefix.status !== 0) return null;
@@ -343,9 +358,10 @@ export async function runAgent(options) {
343
358
  if (minimum && isNewer(minimum, VERSION)) {
344
359
  console.error(`ReMCP ${VERSION} is older than the minimum supported agent ${minimum}; update with: remcp update`);
345
360
  }
346
- if (!isNewer(advertised.cli, VERSION)) return;
347
- const target = String(advertised.cli);
348
- queueEvent({ event: 'agent_update', at: Date.now(), reason: target.slice(0, 32), success: true });
361
+ const decision = updateDecision({ advertised, cliVersion: VERSION, runtimeVersion });
362
+ if (!decision.needed) return;
363
+ const target = decision.target;
364
+ queueEvent({ event: 'agent_update', at: Date.now(), reason: `${decision.reason}:${target}`.slice(0, 32), success: true });
349
365
  const cli = globalCliEntry();
350
366
  if (!cli || !existsSync(cli)) {
351
367
  console.error(`ReMCP ${target} is available; run: remcp update`);
@@ -353,12 +369,13 @@ export async function runAgent(options) {
353
369
  }
354
370
  // A version that already failed to install is retried only after a cooldown, so a broken
355
371
  // release cannot turn into an install loop.
356
- if (target === lastAttemptedVersion && Date.now() - lastAttemptAt < UPDATE_RETRY_COOLDOWN_MS) return;
357
- lastAttemptedVersion = target;
372
+ const attemptKey = `${target}|${decision.runtime}`;
373
+ if (attemptKey === lastAttemptedVersion && Date.now() - lastAttemptAt < UPDATE_RETRY_COOLDOWN_MS) return;
374
+ lastAttemptedVersion = attemptKey;
358
375
  lastAttemptAt = Date.now();
359
376
  updateInFlight = true;
360
- console.log(`Updating ReMCP to ${target}${advertised.runtime ? ` with ${advertised.runtime}` : ''}…`);
361
- const child = spawn(process.execPath, [cli, 'update', '--trust-runtime', ...(advertised.runtime ? ['--runtime', advertised.runtime] : [])], {
377
+ console.log(`Updating ReMCP to ${target}${decision.runtime ? ` with ${decision.runtime}` : ''} (${decision.reason})…`);
378
+ const child = spawn(process.execPath, [cli, 'update', '--trust-runtime', ...(decision.runtime ? ['--runtime', decision.runtime] : [])], {
362
379
  detached: true,
363
380
  stdio: 'ignore',
364
381
  env: { ...process.env },