Adom Chip Fetcher
Public Made by Adomby adom
Your whole parts library — manufacturer-grade chip CAD (symbol, footprint, 3D) one tap from your EDA tool.
adom-desktop v1.4.10 follow-ups — two remaining v1.4.9 issues
Paste into Claude on the desktop. v1.4.9 ships smart-pick refinement + browser_fetch_url saveTo split + tab_not_found error. Verified on container side:
- ✅
browser_fetch_urlsaveTo:container works perfectly (TI INA226 datasheet, 1.5 MB, valid PDF, lands at the path stated,savedToFilesystem:"container"flag set). 🎉 - ⚠️ modal-scoped smart-pick has a false-positive on Vue-Toastification toast containers
- ❌
tab_not_founderror is not actually implemented —browser_evalstill silently falls back to the active tab
Concrete repros for both below.
Item 1 — modal detection false-positives on Vue-Toastification (and similar empty toast containers)
The bug
WAGO's product page (https://www.wago.com/global/p/2601-3105) ships Vue-Toastification. Even with no toast active, four full-page-height toast containers exist in DOM, each <div class="Vue-Toastification__container ..."> with position:fixed; z-index:9999; height:100vh. They cover >25% viewport, beat the v1.4.9 modal-detection heuristic, and become the "modal root."
The actual Generate-Datasheet modal is a sibling <div> rendered by Vue Teleport at body > div, with no [role=dialog], no aria-modal, lower z-index than the toast container. So smart-pick scopes to the wrong "modal" and the Generate button matches outside it.
adom-desktop browser_input_dispatch '{
"sessionId":"chip-fetcher",
"type":"click",
"selector":"button.wg-button--primary"
}'
# → matchedCount: 3
# modalDetected: true
# insideModal: false
# pickStrategy: "visible-text-largest-no-modal-match"
# clickedText: "Add to shopping cart" ← wrong; Generate is in the real modal
DOM proof:
// Run in pup eval against an open WAGO modal
JSON.stringify({
fixedOver25pct: Array.from(document.querySelectorAll('*'))
.filter(el => {
const cs = getComputedStyle(el);
if (!['fixed','absolute'].includes(cs.position)) return false;
const r = el.getBoundingClientRect();
return r.width * r.height / (innerWidth * innerHeight) > 0.25;
})
.map(el => ({
tag: el.tagName,
cls: (el.className || '').toString().slice(0,40),
z: getComputedStyle(el).zIndex,
hasInteractiveChild: !!el.querySelector('button, input, a, [role=button]'),
childTextLen: (el.textContent || '').trim().length
}))
});
// Returns 5 entries:
// - wg-nav-overlay (z=-1, hidden behind page)
// - 4× Vue-Toastification__container (z=9999, hasInteractiveChild=false, childTextLen=0)
// The actual Generate modal is missed because it's a body-level <div> not in
// the >25%-viewport-fixed-or-absolute set.
What I want
The detection heuristic should require the candidate to contain at least one visible interactive element with non-empty text. Empty toast containers fail that filter. The actual modal (which has the Generate button + cancel link + checkbox grid) passes it.
// In pickElementForInputDispatch's modal-root detection:
const isPlausibleModal = (el) => {
// Must contain at least one visible button/link/input with non-empty text
const interactives = Array.from(el.querySelectorAll('button, a, input, [role=button]'));
return interactives.some(child => {
const cs = getComputedStyle(child);
if (cs.display === 'none' || cs.visibility === 'hidden') return false;
if ((child.textContent || '').trim().length === 0 && child.tagName !== 'INPUT') return false;
return true;
});
};
const candidates = fixedOver25pct.filter(isPlausibleModal);
This change should be small — fixedOver25pct list is already computed; just add the post-filter.
Add a modalRootInfo debug field to the response so callers can see what got picked (or didn't):
{
"modalDetected": true,
"modalRoot": { "tag": "DIV", "cls": "datasheet-modal", "z": "1000" },
"insideModal": true,
"pickStrategy": "modal-scoped-largest"
}
Acceptance test
After fix, the WAGO recipe with selector:"button.wg-button--primary" should return clickedText:"Generate data sheet", pickStrategy:"modal-scoped-largest", insideModal:true, with modalRoot referencing a div that actually contains the modal contents (not a Vue-Toastification container).
Workaround for now
Same as before v1.4.9: compute the button's bounding rect via browser_eval and pass {x, y} coords. Defeats the smart-pick value-add for modals.
Item 2 — tab_not_found error path is not implemented (regression / missing implementation)
The bug
The v1.4.9 release notes promised:
When you pass tabId:"tab-2" but the popup has auto-closed, you no longer silently get the active tab's response.
But it still does:
adom-desktop browser_eval '{
"sessionId":"chip-fetcher",
"tabId":"tab-999",
"expr":"location.href"
}'
{
"ok": true,
"result": "https://www.wago.com/global/p/2601-3105",
"sessionId": "chip-fetcher",
"tabId": "tab-1"
}
tab-999 doesn't exist (only tab-1 is open). Eval routed to tab-1 and reported tabId:"tab-1" in the response. No errorCode, no currentTabs, no _hint. Same silent-fallback as v1.4.7.
The bridge-side code path that was supposed to land in v1.4.9 didn't (or got reverted, or didn't make it into the build). v1.4.10 should ship it.
What I want
The promised v1.4.9 behavior:
{
"ok": false,
"error": "Tab \"tab-999\" not found in session \"chip-fetcher\".",
"errorCode": "tab_not_found",
"currentTabs": ["tab-1"],
"_hint": "Most likely the popup auto-closed (Chrome PDF viewer with Content-Disposition: attachment closes after download). Use browser_list_tabs IMMEDIATELY after the click to capture the popup URL, then browser_fetch_url with that URL — never eval-against-popup-then-fetch."
}
This applies to all tab-aware verbs: browser_eval, browser_screenshot, browser_errors, browser_reload, browser_navigate, browser_close_tab. Each should hard-error on missing tabId rather than fall back to active.
Acceptance test
# After fix
adom-desktop browser_eval '{"sessionId":"x","tabId":"tab-bogus","expr":"1"}'
# → {"ok":false,"errorCode":"tab_not_found",...}
adom-desktop browser_screenshot '{"sessionId":"x","tabId":"tab-bogus"}'
# → {"ok":false,"errorCode":"tab_not_found",...}
adom-desktop browser_navigate '{"sessionId":"x","tabId":"tab-bogus","url":"https://example.com"}'
# → {"ok":false,"errorCode":"tab_not_found",...}
Workaround for now
Always check browser_list_tabs for the tab's existence before eval-ing against it. Or trust that browser_eval tabId arg silently falls back to active and never assume it actually targeted the tab you passed. Both are bad — please ship v1.4.9's promised behavior in v1.4.10.
Suggested PR shape
- Item 1 —
pickElementForInputDispatch.detectModalRootadds theisPlausibleModalfilter (interactive + non-empty text child required). ReturnsmodalRootdebug field. Test: WAGO scenario should land on the real modal. - Item 2 — for each tab-aware verb in the bridge dispatch, look up the
tabIdand return the structuredtab_not_founderror before falling back. Add the listed_hint. Add an integration test that opens a session, closes a tab, then attempts eval against the closed tabId and assertserrorCode:"tab_not_found".
Also worth considering: after Item 2, when the bridge gets tab_not_found for a popup tabId that was just listed as opener:"popup" (auto-closed mid-flow), include the popup's last-known URL in the error: lastKnownUrl: "...", so the caller can immediately call browser_fetch_url with it instead of needing to re-list_tabs (which by definition won't show the gone tab).
Container-side update flow
curl -L -o /tmp/cli-fresh \
https://wiki-ufypy5dpx93o.adom.cloud/static/apps/adom-desktop/adom-desktop-linux
sudo install -m 755 /tmp/cli-fresh /usr/local/bin/adom-desktop
adom-desktop --version
# Need 1.4.10 or newer
Plus the taskkill //f //im node.exe reminder on the desktop side (we still have to do that manually after every release; if there's a way to trigger that automatically from adom-desktop install, please do).
— sent from john's container running chip-fetcher v0.1.x against adom-desktop v1.4.9
# adom-desktop v1.4.10 follow-ups — two remaining v1.4.9 issues
Paste into Claude on the desktop. v1.4.9 ships smart-pick refinement + `browser_fetch_url` saveTo split + tab_not_found error. Verified on container side:
- ✅ **`browser_fetch_url` saveTo:container** works perfectly (TI INA226 datasheet, 1.5 MB, valid PDF, lands at the path stated, `savedToFilesystem:"container"` flag set). 🎉
- ⚠️ **modal-scoped smart-pick** has a false-positive on Vue-Toastification toast containers
- ❌ **`tab_not_found` error** is not actually implemented — `browser_eval` still silently falls back to the active tab
Concrete repros for both below.
---
## Item 1 — modal detection false-positives on Vue-Toastification (and similar empty toast containers)
### The bug
WAGO's product page (`https://www.wago.com/global/p/2601-3105`) ships Vue-Toastification. Even with no toast active, four full-page-height toast containers exist in DOM, each `<div class="Vue-Toastification__container ...">` with `position:fixed; z-index:9999; height:100vh`. They cover >25% viewport, beat the v1.4.9 modal-detection heuristic, and become the "modal root."
The actual Generate-Datasheet modal is a sibling `<div>` rendered by Vue Teleport at `body > div`, with no `[role=dialog]`, no `aria-modal`, lower z-index than the toast container. So smart-pick scopes to the wrong "modal" and the Generate button matches **outside** it.
```bash
adom-desktop browser_input_dispatch '{
"sessionId":"chip-fetcher",
"type":"click",
"selector":"button.wg-button--primary"
}'
# → matchedCount: 3
# modalDetected: true
# insideModal: false
# pickStrategy: "visible-text-largest-no-modal-match"
# clickedText: "Add to shopping cart" ← wrong; Generate is in the real modal
```
DOM proof:
```js
// Run in pup eval against an open WAGO modal
JSON.stringify({
fixedOver25pct: Array.from(document.querySelectorAll('*'))
.filter(el => {
const cs = getComputedStyle(el);
if (!['fixed','absolute'].includes(cs.position)) return false;
const r = el.getBoundingClientRect();
return r.width * r.height / (innerWidth * innerHeight) > 0.25;
})
.map(el => ({
tag: el.tagName,
cls: (el.className || '').toString().slice(0,40),
z: getComputedStyle(el).zIndex,
hasInteractiveChild: !!el.querySelector('button, input, a, [role=button]'),
childTextLen: (el.textContent || '').trim().length
}))
});
// Returns 5 entries:
// - wg-nav-overlay (z=-1, hidden behind page)
// - 4× Vue-Toastification__container (z=9999, hasInteractiveChild=false, childTextLen=0)
// The actual Generate modal is missed because it's a body-level <div> not in
// the >25%-viewport-fixed-or-absolute set.
```
### What I want
The detection heuristic should require the candidate to **contain at least one visible interactive element with non-empty text**. Empty toast containers fail that filter. The actual modal (which has the Generate button + cancel link + checkbox grid) passes it.
```js
// In pickElementForInputDispatch's modal-root detection:
const isPlausibleModal = (el) => {
// Must contain at least one visible button/link/input with non-empty text
const interactives = Array.from(el.querySelectorAll('button, a, input, [role=button]'));
return interactives.some(child => {
const cs = getComputedStyle(child);
if (cs.display === 'none' || cs.visibility === 'hidden') return false;
if ((child.textContent || '').trim().length === 0 && child.tagName !== 'INPUT') return false;
return true;
});
};
const candidates = fixedOver25pct.filter(isPlausibleModal);
```
This change should be small — fixedOver25pct list is already computed; just add the post-filter.
Add a `modalRootInfo` debug field to the response so callers can see what got picked (or didn't):
```json
{
"modalDetected": true,
"modalRoot": { "tag": "DIV", "cls": "datasheet-modal", "z": "1000" },
"insideModal": true,
"pickStrategy": "modal-scoped-largest"
}
```
### Acceptance test
After fix, the WAGO recipe with `selector:"button.wg-button--primary"` should return `clickedText:"Generate data sheet"`, `pickStrategy:"modal-scoped-largest"`, `insideModal:true`, with `modalRoot` referencing a div that actually contains the modal contents (not a Vue-Toastification container).
### Workaround for now
Same as before v1.4.9: compute the button's bounding rect via `browser_eval` and pass `{x, y}` coords. Defeats the smart-pick value-add for modals.
---
## Item 2 — `tab_not_found` error path is not implemented (regression / missing implementation)
### The bug
The v1.4.9 release notes promised:
> When you pass tabId:"tab-2" but the popup has auto-closed, you no longer silently get the active tab's response.
But it still does:
```bash
adom-desktop browser_eval '{
"sessionId":"chip-fetcher",
"tabId":"tab-999",
"expr":"location.href"
}'
```
```json
{
"ok": true,
"result": "https://www.wago.com/global/p/2601-3105",
"sessionId": "chip-fetcher",
"tabId": "tab-1"
}
```
`tab-999` doesn't exist (only `tab-1` is open). Eval routed to `tab-1` and reported `tabId:"tab-1"` in the response. No `errorCode`, no `currentTabs`, no `_hint`. Same silent-fallback as v1.4.7.
The bridge-side code path that was supposed to land in v1.4.9 didn't (or got reverted, or didn't make it into the build). v1.4.10 should ship it.
### What I want
The promised v1.4.9 behavior:
```json
{
"ok": false,
"error": "Tab \"tab-999\" not found in session \"chip-fetcher\".",
"errorCode": "tab_not_found",
"currentTabs": ["tab-1"],
"_hint": "Most likely the popup auto-closed (Chrome PDF viewer with Content-Disposition: attachment closes after download). Use browser_list_tabs IMMEDIATELY after the click to capture the popup URL, then browser_fetch_url with that URL — never eval-against-popup-then-fetch."
}
```
This applies to **all** tab-aware verbs: `browser_eval`, `browser_screenshot`, `browser_errors`, `browser_reload`, `browser_navigate`, `browser_close_tab`. Each should hard-error on missing tabId rather than fall back to active.
### Acceptance test
```bash
# After fix
adom-desktop browser_eval '{"sessionId":"x","tabId":"tab-bogus","expr":"1"}'
# → {"ok":false,"errorCode":"tab_not_found",...}
adom-desktop browser_screenshot '{"sessionId":"x","tabId":"tab-bogus"}'
# → {"ok":false,"errorCode":"tab_not_found",...}
adom-desktop browser_navigate '{"sessionId":"x","tabId":"tab-bogus","url":"https://example.com"}'
# → {"ok":false,"errorCode":"tab_not_found",...}
```
### Workaround for now
Always check `browser_list_tabs` for the tab's existence before eval-ing against it. Or trust that `browser_eval` `tabId` arg silently falls back to active and never assume it actually targeted the tab you passed. Both are bad — please ship v1.4.9's promised behavior in v1.4.10.
---
## Suggested PR shape
- **Item 1** — `pickElementForInputDispatch.detectModalRoot` adds the `isPlausibleModal` filter (interactive + non-empty text child required). Returns `modalRoot` debug field. Test: WAGO scenario should land on the real modal.
- **Item 2** — for each tab-aware verb in the bridge dispatch, look up the `tabId` and return the structured `tab_not_found` error before falling back. Add the listed `_hint`. Add an integration test that opens a session, closes a tab, then attempts eval against the closed tabId and asserts `errorCode:"tab_not_found"`.
Also worth considering: **after Item 2, when the bridge gets `tab_not_found` for a popup tabId that was just listed as `opener:"popup"` (auto-closed mid-flow), include the popup's last-known URL in the error**: `lastKnownUrl: "..."`, so the caller can immediately call `browser_fetch_url` with it instead of needing to re-list_tabs (which by definition won't show the gone tab).
---
## Container-side update flow
```bash
curl -L -o /tmp/cli-fresh \
https://wiki-ufypy5dpx93o.adom.cloud/static/apps/adom-desktop/adom-desktop-linux
sudo install -m 755 /tmp/cli-fresh /usr/local/bin/adom-desktop
adom-desktop --version
# Need 1.4.10 or newer
```
Plus the `taskkill //f //im node.exe` reminder on the desktop side (we still have to do that manually after every release; if there's a way to trigger that automatically from `adom-desktop install`, please do).
— sent from john's container running chip-fetcher v0.1.x against adom-desktop v1.4.9