@remcp/runtime 0.2.96 → 0.2.98
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 +13 -0
- package/package.json +1 -1
- package/src/extended/catalog.mjs +1 -1
- package/src/extended/desktop-linux.mjs +47 -2
- package/src/extended/documents.mjs +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.98 — 2026-09-22
|
|
4
|
+
|
|
5
|
+
- `pdf_action info` fallback exposes numeric `annotation_count` instead of violating the declared `annotations` array output contract.
|
|
6
|
+
- Added outputSchema validation coverage for the no-`pdfinfo` fallback path.
|
|
7
|
+
- Live desktop smoke treats `record_screen` as capability-conditional and verifies every tool actually advertised by the runtime.
|
|
8
|
+
- Tool names remain unchanged.
|
|
9
|
+
|
|
10
|
+
## 0.2.97 — 2026-09-22
|
|
11
|
+
|
|
12
|
+
- Native GNOME Wayland `move`, `resize`, and `move_resize` no longer trust a portal drag as proof of success.
|
|
13
|
+
- Window geometry is re-read after each gesture and must match the requested coordinates/size within a bounded tolerance; otherwise the action fails closed.
|
|
14
|
+
- `move_resize` confirms the move before computing the resize gesture. Tool names and schemas remain unchanged.
|
|
15
|
+
|
|
3
16
|
## 0.2.96 — 2026-09-22
|
|
4
17
|
|
|
5
18
|
- Keeps readable search matches when an unreadable descendant is encountered while surfacing a warning.
|
package/package.json
CHANGED
package/src/extended/catalog.mjs
CHANGED
|
@@ -219,7 +219,7 @@ const OUTPUT_FIELDS = Object.freeze({
|
|
|
219
219
|
read_document: { text:outputString(), path:outputString(), data:{}, sheets:outputArray(outputObject()), sheet:outputString(), rows:outputArray({}), cells:outputArray({}) },
|
|
220
220
|
edit_spreadsheet: { path:outputString(), sheet:outputString(), edited_cells:outputNumber(), bytes:outputNumber(), created:outputBoolean() },
|
|
221
221
|
edit_document: { path:outputString(), operations:outputNumber(), changes:outputNumber(), bytes:outputNumber(), created:outputBoolean() },
|
|
222
|
-
pdf_action: { action:outputString(), path:outputString(), source:outputString(), output:outputString(), output_dir:outputString(), files:outputArray(outputString()), pages:outputString(), bytes:outputNumber(), annotations:outputArray(outputObject()), inputs:outputNumber() },
|
|
222
|
+
pdf_action: { action:outputString(), path:outputString(), source:outputString(), output:outputString(), output_dir:outputString(), files:outputArray(outputString()), pages:outputString(), bytes:outputNumber(), annotations:outputArray(outputObject()), annotation_count:outputNumber('Number of PDF annotations found by the info action.'), inputs:outputNumber() },
|
|
223
223
|
});
|
|
224
224
|
|
|
225
225
|
function outputSchemaFor(name, title) {
|
|
@@ -283,6 +283,34 @@ async function focusExplicitWaylandInputTarget(args = {}) {
|
|
|
283
283
|
return row;
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
+
function nativeWaylandGeometryMatches(row, expected = {}, tolerance = 24) {
|
|
287
|
+
for (const key of ['x','y','width','height']) {
|
|
288
|
+
if (expected[key] == null) continue;
|
|
289
|
+
const actual = Number(row?.[key]);
|
|
290
|
+
const wanted = Number(expected[key]);
|
|
291
|
+
if (!Number.isFinite(actual) || !Number.isFinite(wanted) || Math.abs(actual - wanted) > tolerance) return false;
|
|
292
|
+
}
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
async function verifyNativeWaylandGeometry(row, expected, label) {
|
|
297
|
+
let latest = row;
|
|
298
|
+
for (let attempt = 0; attempt < 6; attempt += 1) {
|
|
299
|
+
if (attempt > 0) await new Promise(resolve => setTimeout(resolve, 120));
|
|
300
|
+
try {
|
|
301
|
+
latest = await windowMatch({ id:row.id });
|
|
302
|
+
if (nativeWaylandGeometryMatches(latest, expected)) return latest;
|
|
303
|
+
} catch {}
|
|
304
|
+
}
|
|
305
|
+
const actual = ['x','y','width','height']
|
|
306
|
+
.map(key => `${key}=${Number.isFinite(Number(latest?.[key])) ? Number(latest[key]) : 'unknown'}`)
|
|
307
|
+
.join(' ');
|
|
308
|
+
const wanted = Object.entries(expected)
|
|
309
|
+
.map(([key,value]) => `${key}=${value}`)
|
|
310
|
+
.join(' ');
|
|
311
|
+
throw new Error(`Could not verify native Wayland window ${label} for ${row.title || row.app || row.id}: wanted ${wanted}; observed ${actual}`);
|
|
312
|
+
}
|
|
313
|
+
|
|
286
314
|
async function nativeWaylandWindowAction(row, action, args) {
|
|
287
315
|
const backend = inputBackend(args);
|
|
288
316
|
if (backend === 'x11') unavailable('Native Wayland window action', 'use backend=portal for compositor-managed windows');
|
|
@@ -336,8 +364,11 @@ async function nativeWaylandWindowAction(row, action, args) {
|
|
|
336
364
|
hold_ms:80,
|
|
337
365
|
duration_ms:120,
|
|
338
366
|
});
|
|
339
|
-
|
|
340
|
-
|
|
367
|
+
const verified = await verifyNativeWaylandGeometry(row, { x, y }, 'move');
|
|
368
|
+
currentX = Number(verified.x);
|
|
369
|
+
currentY = Number(verified.y);
|
|
370
|
+
currentWidth = Number(verified.width);
|
|
371
|
+
currentHeight = Number(verified.height);
|
|
341
372
|
}
|
|
342
373
|
|
|
343
374
|
if (action === 'resize' || action === 'move_resize') {
|
|
@@ -352,7 +383,21 @@ async function nativeWaylandWindowAction(row, action, args) {
|
|
|
352
383
|
hold_ms:80,
|
|
353
384
|
duration_ms:120,
|
|
354
385
|
});
|
|
386
|
+
const verified = await verifyNativeWaylandGeometry(row, { width, height }, 'resize');
|
|
387
|
+
currentX = Number(verified.x);
|
|
388
|
+
currentY = Number(verified.y);
|
|
389
|
+
currentWidth = Number(verified.width);
|
|
390
|
+
currentHeight = Number(verified.height);
|
|
355
391
|
}
|
|
392
|
+
return jsonResult({
|
|
393
|
+
action,
|
|
394
|
+
backend:'xdg-desktop-portal',
|
|
395
|
+
id:row.id,
|
|
396
|
+
x:currentX,
|
|
397
|
+
y:currentY,
|
|
398
|
+
width:currentWidth,
|
|
399
|
+
height:currentHeight,
|
|
400
|
+
});
|
|
356
401
|
}
|
|
357
402
|
return jsonResult({ action, backend:'xdg-desktop-portal', id:row.id });
|
|
358
403
|
}
|
|
@@ -442,7 +442,7 @@ export async function pdfAction(args) {
|
|
|
442
442
|
if (action === 'info') {
|
|
443
443
|
const source = await resolveSafePath(args.path,'path');
|
|
444
444
|
if (commandExists('pdfinfo')) return text((await runFile('pdfinfo',[source],{label:'pdfinfo'})).stdout);
|
|
445
|
-
const data = await readFile(source); return jsonResult({ path:source, bytes:data.length,
|
|
445
|
+
const data = await readFile(source); return jsonResult({ path:source, bytes:data.length, annotation_count:pdfAnnotations(data).length });
|
|
446
446
|
}
|
|
447
447
|
if (action === 'merge') {
|
|
448
448
|
const requested = Array.isArray(args.paths) ? args.paths : [];
|