@remcp/runtime 0.2.76 → 0.2.78

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 CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.2.78 — 2026-09-21
6
+
7
+ - Native Wayland cursor telemetry no longer trusts stale XWayland `xdotool` coordinates; unavailable global cursor position is reported explicitly instead.
8
+ - `computer_snapshot` degrades that capture to `cursor: {x:null,y:null}` with a non-fatal cursor error while preserving the rest of the snapshot.
9
+ - Lockstep patch release with the ReMCP client/server at `0.2.78`.
10
+
11
+ ## 0.2.77 — 2026-09-21
12
+
13
+ - Fixed `browser_action` typing so the documented `text` argument reaches CDP `Input.insertText` with Unicode intact; `value` and `text_value` remain compatible aliases.
14
+ - Clarified the browser action schema so agents use `text` for typing and reusable selectors from `browser_find`.
15
+ - Lockstep patch release with the ReMCP client/server at `0.2.77`.
16
+
5
17
  ## 0.2.76 — 2026-09-21
6
18
 
7
19
  - `browser_find(text=...)` ranks exact semantic targets ahead of broad ancestor text containers, prefers actionable/semantic nodes, and de-duplicates nested matches before applying the result limit.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remcp/runtime",
3
- "version": "0.2.76",
3
+ "version": "0.2.78",
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",
@@ -572,6 +572,12 @@ function elementLookup(args) {
572
572
  })()`;
573
573
  }
574
574
 
575
+ export function browserActionInputValue(args = {}, action = '') {
576
+ // text is the public field models naturally use for type, while set_value/select historically
577
+ // used value/text_value. Keep all aliases compatible but give each action its semantic field.
578
+ return String(action === 'type' ? (args.text ?? args.text_value ?? args.value ?? '') : (args.value ?? args.text_value ?? args.text ?? ''));
579
+ }
580
+
575
581
  export async function browserAction(args) {
576
582
  const action = requireEnum(args.action, 'action', ['click', 'focus', 'type', 'set_value', 'select', 'scroll_into_view', 'upload', 'press', 'set_viewport']);
577
583
  return withTarget(args, async (session, target) => {
@@ -611,7 +617,7 @@ export async function browserAction(args) {
611
617
  return jsonResult({ target_id: target.id, action, key });
612
618
  }
613
619
  const lookup = elementLookup(args);
614
- const value = String(args.value ?? args.text_value ?? '');
620
+ const value = browserActionInputValue(args, action);
615
621
  const option = String(args.option ?? value);
616
622
 
617
623
  if (action === 'click') {
@@ -555,7 +555,7 @@ export const extendedToolDefinitions = [
555
555
  define('browser_navigate', 'Browser navigate', 'Open a new debuggable tab or navigate a selected browser page by URL, history back/forward, or reload through Chrome DevTools Protocol.', o({ ...browserTarget, action:e(['url','new_tab','back','forward','reload'], 'Default url when url is provided, otherwise reload. new_tab creates the first page target when needed.'), url:s('Destination URL for action=url or action=new_tab.'), wait:b('Wait for the page load event; default true.'), ignore_cache:b('Reload without cache when action=reload.') }), openMutatingNonDestructive, browserHandlers.browser_navigate, ['browser_cdp']),
556
556
  define('browser_snapshot', 'Browser snapshot', 'Return the selected browser page accessibility tree through Chrome DevTools Protocol and, when requested, attach a real rendered viewport PNG for visual verification. A selector is temporarily recentered for capture, its exact viewport bounds are returned, and the prior scroll position is restored before return.', o({ ...browserTarget, max_nodes:n('Maximum AX nodes; default 1500.'), include_screenshot:b('Attach a real CDP-rendered viewport PNG screenshot; default false.'), selector:s('When include_screenshot=true, center this CSS-selected element before capture and report its viewport bounds.') }), readOnlyLive, browserHandlers.browser_snapshot, ['browser_cdp']),
557
557
  define('browser_find', 'Find browser element', 'Find visible DOM elements by CSS selector, text, or ARIA role and return reusable selectors plus text, value, and bounding boxes.', o({ ...browserTarget, selector:s('CSS selector.'), text:s('Visible text substring.'), role:s('ARIA role.'), limit:n() }), readOnlyLive, browserHandlers.browser_find, ['browser_cdp']),
558
- define('browser_action', 'Browser element action', 'Click, focus, type/set a value, select, scroll to, upload files, press a key, or set an exact responsive-test viewport in a debuggable browser page using DOM/CDP semantics.', o({ ...browserTarget, action:e(['click','focus','type','set_value','select','scroll_into_view','upload','press','set_viewport']), selector:s(), text:s(), value:s(), text_value:s(), option:s(), path:s(), paths:{type:'array',items:{type:'string'}}, key:s(), width:n('CSS viewport width for set_viewport.'), height:n('CSS viewport height for set_viewport.'), device_scale_factor:n('Device scale factor for set_viewport; default 1.'), mobile:b('Enable mobile emulation for set_viewport.') }, ['action']), openMutating, browserHandlers.browser_action, ['browser_cdp']),
558
+ define('browser_action', 'Browser element action', 'Click, focus, type/set a value, select, scroll to, upload files, press a key, or set an exact responsive-test viewport in a debuggable browser page using DOM/CDP semantics.', o({ ...browserTarget, action:e(['click','focus','type','set_value','select','scroll_into_view','upload','press','set_viewport']), selector:s('CSS selector for the target element; prefer the reusable selector returned by browser_find.'), text:s('For action=type, Unicode text to insert. For element actions without selector, visible text may identify the target.'), value:s('Value for action=set_value; also accepted as a compatibility fallback for action=type.'), text_value:s('Compatibility alias for the type/set_value text value.'), option:s(), path:s(), paths:{type:'array',items:{type:'string'}}, key:s(), width:n('CSS viewport width for set_viewport.'), height:n('CSS viewport height for set_viewport.'), device_scale_factor:n('Device scale factor for set_viewport; default 1.'), mobile:b('Enable mobile emulation for set_viewport.') }, ['action']), openMutating, browserHandlers.browser_action, ['browser_cdp']),
559
559
  define('browser_wait', 'Wait for browser', 'Wait for DOM state, page text, URL, completed loading, a navigation away from the current URL, or a short network-idle period in a debuggable browser page. Use browser_evaluate separately for JavaScript predicates or page-specific inspection.', o({ ...browserTarget, condition:e(['selector','text','url_contains','load','navigation','network_idle']), selector:s(), text:s(), value:s(), poll_ms:n(), idle_ms:n('Required zero-in-flight network quiet window for network_idle; default 500 ms.') }), readOnlyLive, browserHandlers.browser_wait, ['browser_cdp']),
560
560
  define('browser_evaluate', 'Evaluate browser JavaScript', 'Evaluate JavaScript in a selected debuggable browser page and return its serializable value. This is a powerful escape hatch for page-specific automation.', o({ ...browserTarget, expression:s('JavaScript expression.'), await_promise:b('Await a returned Promise; default true.') }, ['expression']), openMutating, browserHandlers.browser_evaluate, ['browser_cdp']),
561
561
 
@@ -1063,6 +1063,9 @@ export async function scroll(args = {}) {
1063
1063
  }
1064
1064
 
1065
1065
  export async function cursorPosition() {
1066
+ if (isWaylandSession()) {
1067
+ unavailable('Cursor position', 'native Wayland does not expose an authoritative global cursor position; XWayland xdotool coordinates may be stale');
1068
+ }
1066
1069
  if (!commandExists('xdotool')) unavailable('Cursor position', 'install xdotool');
1067
1070
  const result = await runFile('xdotool', ['getmouselocation','--shell'], { label:'cursor position', allowFailure:true, timeout:2000 });
1068
1071
  const x = Number(result.stdout.match(/^X=(-?\d+)$/m)?.[1]);