@remcp/runtime 0.2.82 → 0.2.83
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/CHANGELOG.md +7 -0
- package/package.json +1 -1
- package/src/extended/diagnostics.mjs +9 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.83 — 2026-09-21
|
|
4
|
+
|
|
5
|
+
- Linux X11 `record_screen` capability now requires both `ffmpeg` and a real `DISPLAY`; headless hosts no longer advertise a recorder that will fail.
|
|
6
|
+
- The runtime no longer invents `:0.0` for headless X11 calls and fails closed with a clear display requirement before ffmpeg runs.
|
|
7
|
+
- `wf-recorder` is selected only for actual Wayland sessions.
|
|
8
|
+
- Regression coverage locks the headless capability and handler behavior; lockstep patch release at `0.2.83`.
|
|
9
|
+
|
|
3
10
|
## 0.2.82 — 2026-09-21
|
|
4
11
|
|
|
5
12
|
- Clarified `set_config_value` routing so local runtime preferences stay separate from hosted account-level `device_action` administration.
|
package/package.json
CHANGED
|
@@ -247,11 +247,12 @@ export async function powerAction(args) {
|
|
|
247
247
|
export function recordScreenAvailable({
|
|
248
248
|
platform = process.platform,
|
|
249
249
|
wayland = platform === 'linux' ? isWaylandSession() : false,
|
|
250
|
+
display = process.env.DISPLAY || '',
|
|
250
251
|
commandExistsFn = commandExists,
|
|
251
252
|
} = {}) {
|
|
252
253
|
if (platform === 'linux') {
|
|
253
254
|
if (wayland) return commandExistsFn('wf-recorder') && commandExistsFn('timeout');
|
|
254
|
-
return commandExistsFn('ffmpeg');
|
|
255
|
+
return Boolean(String(display).trim()) && commandExistsFn('ffmpeg');
|
|
255
256
|
}
|
|
256
257
|
if (platform === 'darwin' || platform === 'win32') return commandExistsFn('ffmpeg');
|
|
257
258
|
return false;
|
|
@@ -261,13 +262,17 @@ export async function recordScreen(args) {
|
|
|
261
262
|
const seconds = clamp(args.duration_seconds, 5, 1, 120);
|
|
262
263
|
const fps = clamp(args.fps, 15, 1, 60);
|
|
263
264
|
const destination = args.destination ? await resolveSafePath(args.destination, 'destination') : path.join(os.tmpdir(), `remcp-screen-${Date.now()}.mp4`);
|
|
264
|
-
|
|
265
|
+
const wayland = process.platform === 'linux' && isWaylandSession();
|
|
266
|
+
if (wayland && commandExists('wf-recorder') && commandExists('timeout')) {
|
|
265
267
|
const result = await runFile('timeout', ['--signal=INT', `${seconds}s`, 'wf-recorder', '-f',destination,'-r',String(fps),'-c','libx264'], { label:'screen recording', timeout:(seconds+10)*1000, allowFailure:true });
|
|
266
268
|
if (![0, 124, 130].includes(Number(result.code))) throw new Error(result.stderr.trim() || `wf-recorder exited ${result.code}`);
|
|
267
269
|
} else {
|
|
268
|
-
if (
|
|
270
|
+
if (wayland) {
|
|
269
271
|
unavailable('Screen recording', 'wf-recorder and timeout are required on Wayland');
|
|
270
272
|
}
|
|
273
|
+
if (process.platform === 'linux' && !String(process.env.DISPLAY || '').trim()) {
|
|
274
|
+
unavailable('Screen recording', 'an active X11 DISPLAY is required on Linux X11');
|
|
275
|
+
}
|
|
271
276
|
if (!commandExists('ffmpeg')) {
|
|
272
277
|
if (process.platform === 'darwin') unavailable('Screen recording', 'ffmpeg is required on macOS');
|
|
273
278
|
if (process.platform === 'win32') unavailable('Screen recording', 'ffmpeg is required on Windows');
|
|
@@ -276,7 +281,7 @@ export async function recordScreen(args) {
|
|
|
276
281
|
let argv;
|
|
277
282
|
if (process.platform === 'win32') argv=['-y','-f','gdigrab','-framerate',String(fps),'-i','desktop','-t',String(seconds),'-pix_fmt','yuv420p',destination];
|
|
278
283
|
else if (process.platform === 'darwin') argv=['-y','-f','avfoundation','-framerate',String(fps),'-i','1:none','-t',String(seconds),'-pix_fmt','yuv420p',destination];
|
|
279
|
-
else argv=['-y','-f','x11grab','-framerate',String(fps),'-i',process.env.DISPLAY
|
|
284
|
+
else argv=['-y','-f','x11grab','-framerate',String(fps),'-i',process.env.DISPLAY,'-t',String(seconds),'-pix_fmt','yuv420p',destination];
|
|
280
285
|
await runFile('ffmpeg', argv, { label:'screen recording', timeout:(seconds+20)*1000, maxBuffer:8*1024*1024 });
|
|
281
286
|
}
|
|
282
287
|
const info = await stat(destination);
|