pawbrowse 0.6.3 → 0.6.4

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.
@@ -1339,16 +1339,24 @@ async function resolveHit(tabId, ref, opts, _retries) {
1339
1339
  if(!p.hit) return {error:'element is covered by another element (dismiss the overlay/dialog first)'};
1340
1340
  return {x:p.x, y:p.y};
1341
1341
  })()`);
1342
- // A ref the page-side cache no longer recognises (its map was rebuilt, this tab's world was
1343
- // recreated, or the element is mid-re-render from a JUST-PRIOR action — e.g. switching a
1344
- // code-language combobox remounts the code block, including its own "Expand code" button, a beat
1345
- // after the click that triggered it) is not necessarily gone: a fresh scan reruns the SAME
1346
- // "gone element -> matching new element" rebind snapshot() already does for re-renders. Up to two
1347
- // free retries with a short growing delay, transparent to the caller — costs nothing on success,
1348
- // and never hides a real "no longer on page" failure.
1349
- if(result && result.error === 'unknown ref (observe again)' && _retries < 2){
1342
+ // Any "(observe again)"-flavored failure can mean the page is mid-re-render — from a just-prior
1343
+ // action, or from something async and independent of us entirely (a sidebar widget that hydrates
1344
+ // on its own timer) — rather than the target being truly gone. Up to two free retries with a short
1345
+ // growing delay, transparent to the caller: costs nothing on success, and still surfaces a real
1346
+ // failure once retries run out.
1347
+ //
1348
+ // 'unknown ref' means byId[ref] itself is missing — there is no fingerprint left to match against,
1349
+ // so only a fresh full snapshot() (which runs the "gone element -> matching new element" rebind for
1350
+ // EVERY ref) has any chance of reviving it. For every other case (element/row disconnected or
1351
+ // changed), byId[ref]'s fingerprint is still intact, and c.get()'s own live-DOM fallback (above)
1352
+ // already re-scans the page fresh on every call — so we must NOT call snapshot() here: a full
1353
+ // rebuild resets byId/guards/fps for ALL refs from whatever's on the page at that instant, and if it
1354
+ // happens to land while our target is still absent (e.g. mid-hydration), it erases the very
1355
+ // fingerprint a LATER, successful retry would need — permanently orphaning a ref that would
1356
+ // otherwise have recovered on its own.
1357
+ if(result && result.error && /observe again/i.test(result.error) && _retries < 2){
1350
1358
  await sleep(_retries === 0 ? 120 : 300);
1351
- try { await snapshot(tabId, 1); } catch {}
1359
+ if(result.error === 'unknown ref (observe again)'){ try { await snapshot(tabId, 1); } catch {} }
1352
1360
  return resolveHit(tabId, ref, opts, _retries + 1);
1353
1361
  }
1354
1362
  return result;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "PawBrowse",
4
- "version": "0.6.3",
4
+ "version": "0.6.4",
5
5
  "description": "Let your AI agent (Claude Code) drive your real Chrome. Fast element-table control. Open source, no keys.",
6
6
  "minimum_chrome_version": "125",
7
7
  "permissions": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pawbrowse",
3
- "version": "0.6.3",
3
+ "version": "0.6.4",
4
4
  "description": "Let Claude Code drive your real, logged-in Chrome. A zero-dependency MCP server + a Chrome MV3 extension that uses element-table perception over CDP. The calling agent is the policy: no second model, no API keys, page snapshots never leave for a third party.",
5
5
  "type": "module",
6
6
  "bin": {