@remcp/runtime 0.2.194 → 0.2.196
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
|
@@ -84,12 +84,23 @@ export function browserAutoLaunchArgs(profile, {
|
|
|
84
84
|
return args;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
// macOS Chrome may take longer than 5 seconds to expose loopback CDP after
|
|
88
|
+
// a cold launch with a separate profile (measured on real Apple Silicon).
|
|
89
|
+
// Keep Linux/Windows fast-path unchanged; never auto-launch for read-only calls.
|
|
90
|
+
export function browserStartupReadyTimeoutMs(platform = process.platform) {
|
|
91
|
+
return platform === 'darwin' ? 12000 : 5000;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export async function waitForBrowserEndpoint(timeoutMs = 5000, {
|
|
95
|
+
available = browserCapabilityAvailable,
|
|
96
|
+
now = Date.now,
|
|
97
|
+
pause = ms => new Promise(resolve => setTimeout(resolve, ms)),
|
|
98
|
+
} = {}) {
|
|
99
|
+
const deadline = now() + timeoutMs;
|
|
89
100
|
do {
|
|
90
|
-
if (await
|
|
91
|
-
await
|
|
92
|
-
} while (
|
|
101
|
+
if (await available(undefined, 250)) return true;
|
|
102
|
+
await pause(100);
|
|
103
|
+
} while (now() < deadline);
|
|
93
104
|
return false;
|
|
94
105
|
}
|
|
95
106
|
|
|
@@ -114,7 +125,7 @@ export async function ensureBrowserEndpoint(endpoint) {
|
|
|
114
125
|
onError:({ code }) => observeBrowserLaunchExit({ error:code || 'UNKNOWN' },
|
|
115
126
|
{ startedAt, restore, isolated:selected.isolated }),
|
|
116
127
|
});
|
|
117
|
-
if (!await waitForBrowserEndpoint(
|
|
128
|
+
if (!await waitForBrowserEndpoint(browserStartupReadyTimeoutMs())) throw new Error('ReMCP launched a browser but its local CDP endpoint did not become ready');
|
|
118
129
|
return true;
|
|
119
130
|
})().finally(() => { browserLaunchPromise = null; });
|
|
120
131
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Read-only macOS kernel telemetry. These readings are not physical RAM occupancy.
|
|
2
|
+
import { execFile } from 'node:child_process';
|
|
3
|
+
import { promisify } from 'node:util';
|
|
4
|
+
|
|
5
|
+
const exec = promisify(execFile);
|
|
6
|
+
const options = { timeout: 1200, maxBuffer: 4096, windowsHide: true };
|
|
7
|
+
const command = (file, args) => exec(file, args, options).then(({ stdout }) => stdout).catch(() => '');
|
|
8
|
+
|
|
9
|
+
export function parseDarwinMemoryPressure(output, levelOutput) {
|
|
10
|
+
const match = /^System-wide memory free percentage:\s*(\d{1,3})%\s*$/m.exec(String(output).slice(0, 4096));
|
|
11
|
+
const free = match ? Number(match[1]) : NaN;
|
|
12
|
+
const level = /^\s*([124])\s*$/.exec(String(levelOutput).slice(0, 32))?.[1];
|
|
13
|
+
return {
|
|
14
|
+
effectiveFreeRatio: Number.isInteger(free) && free >= 0 && free <= 100 ? free / 100 : null,
|
|
15
|
+
effectiveFreeMethod: Number.isInteger(free) && free >= 0 && free <= 100 ? 'darwin-memory_pressure-Q' : null,
|
|
16
|
+
pressureLevel: ({ '1': 'normal', '2': 'warning', '4': 'critical' })[level] ?? null,
|
|
17
|
+
pressureMethod: level ? 'darwin-kernel-sysctl' : null,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function readDarwinMemoryPressure(runner = command) {
|
|
22
|
+
const [free, level] = await Promise.all([
|
|
23
|
+
runner('/usr/bin/memory_pressure', ['-Q']),
|
|
24
|
+
runner('/usr/sbin/sysctl', ['-n', 'kern.memorystatus_vm_pressure_level']),
|
|
25
|
+
]);
|
|
26
|
+
return parseDarwinMemoryPressure(free, level);
|
|
27
|
+
}
|
package/src/tools/system.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import { runtimeConfig } from '../config.mjs';
|
|
|
6
6
|
import { clampInteger, fail, requireInteger, text } from '../util.mjs';
|
|
7
7
|
import { cpuUtilizationRatio, cpuFrequencyMHz, cpuPerCoreUtilizationRatios } from './cpu-telemetry.mjs';
|
|
8
8
|
import { diskVolumes, networkRates, thermalReadings } from './system-telemetry.mjs';
|
|
9
|
+
import { readDarwinMemoryPressure } from './darwin-memory-pressure.mjs';
|
|
9
10
|
|
|
10
11
|
const run = promisify(execFile);
|
|
11
12
|
|
|
@@ -50,6 +51,7 @@ export async function getSystemInfoTool() {
|
|
|
50
51
|
const volumesPromise = diskVolumes();
|
|
51
52
|
const thermalPromise = thermalReadings();
|
|
52
53
|
const networkPromise = networkRates();
|
|
54
|
+
const memoryPressurePromise = process.platform === 'darwin' ? readDarwinMemoryPressure() : Promise.resolve(null);
|
|
53
55
|
const sampledCpus = await new Promise(resolve => setTimeout(() => resolve(os.cpus()), 140));
|
|
54
56
|
const utilizationRatio = cpuUtilizationRatio(cpus, sampledCpus);
|
|
55
57
|
const frequencyMHz = cpuFrequencyMHz(sampledCpus);
|
|
@@ -74,6 +76,8 @@ export async function getSystemInfoTool() {
|
|
|
74
76
|
totalBytes: totalMem,
|
|
75
77
|
freeBytes: freeMem,
|
|
76
78
|
usedRatio: totalMem ? Number(((totalMem - freeMem) / totalMem).toFixed(3)) : 0,
|
|
79
|
+
usedMethod: 'os.freemem-physical-occupancy',
|
|
80
|
+
...(await memoryPressurePromise),
|
|
77
81
|
},
|
|
78
82
|
disk: await diskPromise,
|
|
79
83
|
volumes: await volumesPromise,
|