@remcp/runtime 0.2.221 → 0.2.222

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remcp/runtime",
3
- "version": "0.2.221",
3
+ "version": "0.2.222",
4
4
  "description": "First-party ReMCP local device runtime: filesystem, terminal, computer-use, browser, diagnostics and document tools over MCP.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -34,6 +34,17 @@ export function cpuPerCoreUtilizationRatios(before, after) {
34
34
  return ratios.every(value => value !== null) ? ratios : null;
35
35
  }
36
36
 
37
+ // Windows diagnostics spawn PowerShell probes. Measure host CPU first, or the
38
+ // diagnostics themselves can appear as a false 100% CPU spike on small VMs.
39
+ export async function scheduleCpuSampleAndProbes(platform, sampleCpu, startProbes) {
40
+ if (platform === 'win32') {
41
+ const cpus = await sampleCpu();
42
+ return { cpus, probes: startProbes() };
43
+ }
44
+ const probes = startProbes();
45
+ return { cpus: await sampleCpu(), probes };
46
+ }
47
+
37
48
  export function cpuFrequencyMHz(cores) {
38
49
  if (!Array.isArray(cores) || !cores.length) return null;
39
50
  const speeds = cores.map(core => core?.speed).filter(speed => Number.isFinite(speed) && speed > 0 && speed <= 100000);
@@ -6,7 +6,7 @@ import { statfs } from 'node:fs/promises';
6
6
  import { promisify } from 'node:util';
7
7
  import { runtimeConfig } from '../config.mjs';
8
8
  import { clampInteger, fail, requireInteger, text } from '../util.mjs';
9
- import { cpuUtilizationRatio, cpuFrequencyMHz, cpuPerCoreUtilizationRatios } from './cpu-telemetry.mjs';
9
+ import { cpuUtilizationRatio, cpuFrequencyMHz, cpuPerCoreUtilizationRatios, scheduleCpuSampleAndProbes } from './cpu-telemetry.mjs';
10
10
  import { diskVolumes, networkRates, thermalReadings } from './system-telemetry.mjs';
11
11
  import { readDarwinMemoryPressure } from './darwin-memory-pressure.mjs';
12
12
 
@@ -63,14 +63,21 @@ export async function getSystemInfoTool() {
63
63
  const totalMem = os.totalmem();
64
64
  const freeMem = os.freemem();
65
65
  const load = os.loadavg();
66
- // Sample for 140 ms while retrieving disk facts, so CPU % is actual host activity.
67
- // Load average is a queue-length metric and must never be displayed as a percentage.
68
- const diskPromise = diskUsage();
69
- const volumesPromise = diskVolumes();
70
- const thermalPromise = thermalReadings();
71
- const networkPromise = networkRates();
72
- const memoryPressurePromise = process.platform === 'darwin' ? readDarwinMemoryPressure() : Promise.resolve(null);
73
- const sampledCpus = await new Promise(resolve => setTimeout(() => resolve(os.cpus()), 140));
66
+ // On Windows, the PowerShell sensor probes can saturate short CPU samples.
67
+ // Measure CPU before launching them; keep other platforms' parallel probes.
68
+ // Load average is queue length, never a percentage.
69
+ const { cpus: sampledCpus, probes } = await scheduleCpuSampleAndProbes(
70
+ process.platform,
71
+ () => new Promise(resolve => setTimeout(() => resolve(os.cpus()), 140)),
72
+ () => ({
73
+ diskPromise: diskUsage(),
74
+ volumesPromise: diskVolumes(),
75
+ thermalPromise: thermalReadings(),
76
+ networkPromise: networkRates(),
77
+ memoryPressurePromise: process.platform === 'darwin'
78
+ ? readDarwinMemoryPressure() : Promise.resolve(null),
79
+ }),
80
+ );
74
81
  const utilizationRatio = cpuUtilizationRatio(cpus, sampledCpus);
75
82
  const frequencyMHz = cpuFrequencyMHz(sampledCpus);
76
83
  return text(JSON.stringify({
@@ -95,12 +102,12 @@ export async function getSystemInfoTool() {
95
102
  freeBytes: freeMem,
96
103
  usedRatio: totalMem ? Number(((totalMem - freeMem) / totalMem).toFixed(3)) : 0,
97
104
  usedMethod: 'os.freemem-physical-occupancy',
98
- ...(await memoryPressurePromise),
105
+ ...(await probes.memoryPressurePromise),
99
106
  },
100
- disk: await diskPromise,
101
- volumes: await volumesPromise,
102
- temperatures: await thermalPromise,
103
- network: await networkPromise,
107
+ disk: await probes.diskPromise,
108
+ volumes: await probes.volumesPromise,
109
+ temperatures: await probes.thermalPromise,
110
+ network: await probes.networkPromise,
104
111
  home: os.homedir(),
105
112
  tempDir: os.tmpdir(),
106
113
  runtimeName: runtimeConfig.name,