@remcp/runtime 0.2.155 → 0.2.156

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.155",
3
+ "version": "0.2.156",
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",
@@ -20,6 +20,12 @@ export const adapter = process.platform === 'win32' ? windows : process.platform
20
20
  export const UI_CACHE_TTL_MS = 5_000;
21
21
  export let latestUiSnapshot = null;
22
22
 
23
+ // ES module imports are read-only bindings. All snapshot invalidation must be
24
+ // owned by this module so wait_for_ui can request a fresh tree safely.
25
+ export function invalidateUiSnapshotCache() {
26
+ latestUiSnapshot = null;
27
+ }
28
+
23
29
  export function suggestedUiAction(node = {}) {
24
30
  const role = String(node.role || '').toLowerCase();
25
31
  const patterns = Array.isArray(node.patterns) ? node.patterns.map(value => String(value).toLowerCase()) : [];
@@ -12,7 +12,7 @@ import { browserAction, browserCapabilityAvailable, browserSnapshot } from './br
12
12
  import { findOcrText, ocrImage } from './ocr.mjs';
13
13
 
14
14
 
15
- import { adapter, cachedUiNodes, clipboard, keyboard, latestUiSnapshot, listWindows, pointer, resultValue, sleep, uiAction, uiSnapshot, windowAction, withResolvedUiLabel } from './desktop-core.mjs';
15
+ import { adapter, cachedUiNodes, clipboard, keyboard, invalidateUiSnapshotCache, listWindows, pointer, resultValue, sleep, uiAction, uiSnapshot, windowAction, withResolvedUiLabel } from './desktop-core.mjs';
16
16
 
17
17
  export function matches(node, args) {
18
18
  const id = optionalString(args.id);
@@ -151,7 +151,7 @@ export async function waitForUi(args = {}) {
151
151
  do {
152
152
  attempts += 1;
153
153
  // A wait must observe fresh state, not repeatedly query the same 5-second cache.
154
- latestUiSnapshot = null;
154
+ invalidateUiSnapshotCache();
155
155
  evaluation = await uiConditionMatches(args, condition);
156
156
  if (evaluation.matched) {
157
157
  return jsonResult({
@@ -177,13 +177,13 @@ export async function waitForUi(args = {}) {
177
177
  });
178
178
  }
179
179
 
180
- latestUiSnapshot = null;
180
+ invalidateUiSnapshotCache();
181
181
  const baseline = state === 'changed' ? await uiMatches(args) : [];
182
182
  const baselineFingerprint = state === 'changed' ? uiFingerprint(baseline) : null;
183
183
  let nodes = baseline;
184
184
  do {
185
185
  attempts += 1;
186
- latestUiSnapshot = null;
186
+ invalidateUiSnapshotCache();
187
187
  nodes = await uiMatches(args);
188
188
  const changed = state === 'changed' && uiFingerprint(nodes) !== baselineFingerprint;
189
189
  if ((state === 'present' && nodes.length) || (state === 'absent' && !nodes.length) || changed) {