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 feature request: trusted-input dispatch + popup-tab tracking
Paste this whole document into Claude on your desktop (where the adom-desktop Rust source lives) and ask it to implement the two features below.
Context
adom-desktop is the Rust CLI + WebSocket relay (default /usr/local/bin/adom-desktop) that lets container-side agents drive a real Chromium ("pup") on the user's laptop. Source layout:
Cargo.toml+src/— main Rust binary (CLI + relay)plugins/puppeteer/— Node side that actually drives Chromium via puppeteer-core- Existing browser commands:
browser_open_window,browser_open_tab,browser_navigate,browser_eval,browser_screenshot,browser_list_tabs,browser_list_windows,browser_close_tab,browser_close_window,browser_focus_window,browser_raise_os_window,browser_alert_window,browser_reload,browser_record_*,browser_switch_tab
I'm using adom-desktop from inside an Adom container to run a tool called chip-fetcher that scrapes manufacturer / distributor sites for chip CAD bundles + datasheets. I just hit two gaps that block whole classes of vendor sites. Fixing them unblocks a lot.
Feature 1 — browser_input_dispatch (trusted click / key / move)
The gap
Page-side dispatchEvent(new MouseEvent("click", {...})) produces events with isTrusted: false. Modern frameworks (React, Vue, Svelte) and most anti-automation vendor JS gate handlers on event.isTrusted === true. So my synthetic clicks fire to the DOM but the registered click handler never runs.
Repro that bit me today: WAGO's "Generate Datasheet" button. Their bundled JS does:
submit = async () => {
const url = priintGridUrl + language;
const body = new URLSearchParams({ALL_DATA: "true", language, productCode});
formSubmit({url, method: "POST", target: "_blank"}, body);
};
That handler is wrapped behind an isTrusted check by Vue/the framework. My MouseEvent, PointerEvent, focus-then-Enter — all silently no-op. I had to read the bundle, extract the API, and replay the POST manually via fetch() with credentials:"include". That works, but it's brittle (bundle hashes change every deploy) and uses no end-user UX.
The fix
Expose Puppeteer's native CDP input dispatch. Puppeteer already wraps it as page.mouse.click(x, y), page.keyboard.type(text), page.keyboard.press(key), page.mouse.move(x, y). These produce events with isTrusted: true because they go through Input.dispatchMouseEvent / Input.dispatchKeyEvent at the Chromium browser level, not from page JS.
Suggested CLI surface:
# Click at coordinates
adom-desktop browser_input_dispatch '{
"sessionId":"chip-fetcher",
"type":"click",
"x":860,"y":803
}'
# Click via selector (resolve coords from selector's bounding rect, then dispatch)
adom-desktop browser_input_dispatch '{
"sessionId":"chip-fetcher",
"type":"click",
"selector":"button.wg-button--primary"
}'
# Type into a focused input
adom-desktop browser_input_dispatch '{
"sessionId":"chip-fetcher",
"type":"type",
"text":"DMG2305UX-7"
}'
# Press a single key
adom-desktop browser_input_dispatch '{
"sessionId":"chip-fetcher",
"type":"key",
"key":"Enter"
}'
# Mouse move (for human-like trajectories before clicks)
adom-desktop browser_input_dispatch '{
"sessionId":"chip-fetcher",
"type":"move",
"x":400,"y":500
}'
Implementation hints (Node side)
In plugins/puppeteer/:
case "browser_input_dispatch": {
const { sessionId, type, x, y, selector, text, key } = args;
const page = sessions[sessionId].activePage;
if (type === "click") {
if (selector) {
const handle = await page.$(selector);
if (!handle) return { error: `selector not found: ${selector}` };
await handle.click(); // puppeteer's .click() uses Input.dispatchMouseEvent under the hood
return { ok: true };
}
await page.mouse.click(x, y);
return { ok: true };
}
if (type === "type") {
await page.keyboard.type(text);
return { ok: true };
}
if (type === "key") {
await page.keyboard.press(key);
return { ok: true };
}
if (type === "move") {
await page.mouse.move(x, y);
return { ok: true };
}
return { error: `unknown type: ${type}` };
}
Acceptance test
After implementation, this should fire the WAGO submit handler and the popup tab actually opens:
# Open the WAGO product page
adom-desktop browser_open_window '{
"sessionId":"test-trusted",
"profile":"test-trusted",
"url":"https://www.wago.com/global/p/2601-3105"
}'
# Wait for page to load, then open the modal
sleep 6
adom-desktop browser_eval '{
"sessionId":"test-trusted",
"expr":"Array.from(document.querySelectorAll(\"button, a\")).find(e => /^generate datasheet$/i.test((e.textContent||\"\").trim())).click()"
}'
# After modal opens, dispatch a TRUSTED click on the green "Generate data sheet" button
sleep 3
adom-desktop browser_input_dispatch '{
"sessionId":"test-trusted",
"type":"click",
"selector":"button.wg-button--primary"
}'
# Within ~5 seconds, browser_list_tabs should show a NEW tab on wago.priintcloud.com
sleep 5
adom-desktop browser_list_tabs '{"sessionId":"test-trusted"}'
# Expected: tabCount: 2, second tab url contains "priintcloud.com/datasheets/2601-3105"
If browser_list_tabs still shows tabCount: 1 after the trusted click, see Feature 2 — the popup is opening but isn't being tracked.
Feature 2 — auto-track popup tabs in browser_list_tabs
The gap
browser_list_tabs only returns tabs that the agent created via browser_open_tab. Tabs that the page itself spawns (via window.open(), target="_blank" form submits, <a target="_blank"> clicks) are real Chromium targets but invisible to the pup tab list. Result: even if a click does open a new tab, my container-side scraper has no way to find it, switch to it, or eval against it.
The fix
Listen for Target.targetCreated and Target.targetDestroyed events from Chromium and keep an internal table of all top-level page targets per session, keyed by tabId. Include them all in browser_list_tabs output, with a flag indicating provenance.
Suggested response shape:
{
"sessionId": "chip-fetcher",
"activeTabId": "tab-1",
"count": 2,
"tabs": [
{
"tabId": "tab-1",
"url": "https://www.wago.com/global/p/2601-3105",
"title": "PCB terminal block (2601-3105) | WAGO",
"active": true,
"opener": "user"
},
{
"tabId": "tab-popup-1",
"url": "https://wago.priintcloud.com/datasheets/2601-3105/en/abc...",
"title": "Datasheet - WAGO 2601-3105",
"active": false,
"opener": "popup",
"openerTabId": "tab-1"
}
]
}
Implementation hints (Node side)
In plugins/puppeteer/sessions/<sessionId>.js:
// After creating the browser:
browser.on("targetcreated", async (target) => {
if (target.type() !== "page") return;
const page = await target.page();
if (!page) return;
const tabId = `tab-popup-${++this.popupCounter}`;
this.tabs.set(tabId, {
page,
url: page.url(),
opener: target.opener() ? "popup" : "user",
openerTabId: target.opener() ? this.findTabIdForTarget(target.opener()) : null,
});
});
browser.on("targetdestroyed", (target) => {
// Remove from this.tabs
});
// list_tabs response builds from this.tabs.values()
Acceptance test
# After Feature 1 lands, the trusted click on WAGO's Generate button
# should produce a NEW tab visible to browser_list_tabs:
adom-desktop browser_list_tabs '{"sessionId":"chip-fetcher"}'
# Expected: tabCount: 2, with tab-popup-1 entry showing priintcloud.com URL
Then I can browser_eval against the popup tab's tabId, fetch the PDF binary via in-page fetch(), base64 it back, and save — without any API-replay reverse-engineering.
Suggested file/PR structure
Cargo.toml— bump versionsrc/cli.rs(or wherever the dispatch table lives) — registerbrowser_input_dispatchactionplugins/puppeteer/index.js(or per-session module) — implement the input handler + target-tracking listenersplugins/puppeteer/types.d.ts— extend the tab response shape withopener/openerTabId- One integration test per feature (the acceptance tests above are good shapes for those)
A single PR with both features is fine — they go together (popup tracking is most useful when you can produce trusted clicks that spawn popups in the first place).
Once it ships, please bump the version + remind me to upgrade my container's binary so the chip-fetcher skill picks up the new commands.
— sent from john's container at john-galliaapril-… running chip-fetcher v0.1.x
# adom-desktop feature request: trusted-input dispatch + popup-tab tracking
Paste this whole document into Claude on your desktop (where the `adom-desktop` Rust source lives) and ask it to implement the two features below.
---
## Context
`adom-desktop` is the Rust CLI + WebSocket relay (default `/usr/local/bin/adom-desktop`) that lets container-side agents drive a real Chromium ("pup") on the user's laptop. Source layout:
- `Cargo.toml` + `src/` — main Rust binary (CLI + relay)
- `plugins/puppeteer/` — Node side that actually drives Chromium via puppeteer-core
- Existing browser commands: `browser_open_window`, `browser_open_tab`, `browser_navigate`, `browser_eval`, `browser_screenshot`, `browser_list_tabs`, `browser_list_windows`, `browser_close_tab`, `browser_close_window`, `browser_focus_window`, `browser_raise_os_window`, `browser_alert_window`, `browser_reload`, `browser_record_*`, `browser_switch_tab`
I'm using adom-desktop from inside an Adom container to run a tool called `chip-fetcher` that scrapes manufacturer / distributor sites for chip CAD bundles + datasheets. I just hit two gaps that block whole classes of vendor sites. Fixing them unblocks a lot.
---
## Feature 1 — `browser_input_dispatch` (trusted click / key / move)
### The gap
Page-side `dispatchEvent(new MouseEvent("click", {...}))` produces events with `isTrusted: false`. Modern frameworks (React, Vue, Svelte) and most anti-automation vendor JS gate handlers on `event.isTrusted === true`. So my synthetic clicks fire to the DOM but the registered click handler **never runs**.
Repro that bit me today: WAGO's "Generate Datasheet" button. Their bundled JS does:
```js
submit = async () => {
const url = priintGridUrl + language;
const body = new URLSearchParams({ALL_DATA: "true", language, productCode});
formSubmit({url, method: "POST", target: "_blank"}, body);
};
```
That handler is wrapped behind an `isTrusted` check by Vue/the framework. My `MouseEvent`, `PointerEvent`, focus-then-Enter — all silently no-op. I had to read the bundle, extract the API, and replay the POST manually via `fetch()` with `credentials:"include"`. That works, but it's brittle (bundle hashes change every deploy) and uses no end-user UX.
### The fix
Expose Puppeteer's native CDP input dispatch. Puppeteer already wraps it as `page.mouse.click(x, y)`, `page.keyboard.type(text)`, `page.keyboard.press(key)`, `page.mouse.move(x, y)`. These produce events with `isTrusted: true` because they go through `Input.dispatchMouseEvent` / `Input.dispatchKeyEvent` at the Chromium browser level, not from page JS.
Suggested CLI surface:
```bash
# Click at coordinates
adom-desktop browser_input_dispatch '{
"sessionId":"chip-fetcher",
"type":"click",
"x":860,"y":803
}'
# Click via selector (resolve coords from selector's bounding rect, then dispatch)
adom-desktop browser_input_dispatch '{
"sessionId":"chip-fetcher",
"type":"click",
"selector":"button.wg-button--primary"
}'
# Type into a focused input
adom-desktop browser_input_dispatch '{
"sessionId":"chip-fetcher",
"type":"type",
"text":"DMG2305UX-7"
}'
# Press a single key
adom-desktop browser_input_dispatch '{
"sessionId":"chip-fetcher",
"type":"key",
"key":"Enter"
}'
# Mouse move (for human-like trajectories before clicks)
adom-desktop browser_input_dispatch '{
"sessionId":"chip-fetcher",
"type":"move",
"x":400,"y":500
}'
```
### Implementation hints (Node side)
In `plugins/puppeteer/`:
```js
case "browser_input_dispatch": {
const { sessionId, type, x, y, selector, text, key } = args;
const page = sessions[sessionId].activePage;
if (type === "click") {
if (selector) {
const handle = await page.$(selector);
if (!handle) return { error: `selector not found: ${selector}` };
await handle.click(); // puppeteer's .click() uses Input.dispatchMouseEvent under the hood
return { ok: true };
}
await page.mouse.click(x, y);
return { ok: true };
}
if (type === "type") {
await page.keyboard.type(text);
return { ok: true };
}
if (type === "key") {
await page.keyboard.press(key);
return { ok: true };
}
if (type === "move") {
await page.mouse.move(x, y);
return { ok: true };
}
return { error: `unknown type: ${type}` };
}
```
### Acceptance test
After implementation, this should fire the WAGO submit handler and the popup tab actually opens:
```bash
# Open the WAGO product page
adom-desktop browser_open_window '{
"sessionId":"test-trusted",
"profile":"test-trusted",
"url":"https://www.wago.com/global/p/2601-3105"
}'
# Wait for page to load, then open the modal
sleep 6
adom-desktop browser_eval '{
"sessionId":"test-trusted",
"expr":"Array.from(document.querySelectorAll(\"button, a\")).find(e => /^generate datasheet$/i.test((e.textContent||\"\").trim())).click()"
}'
# After modal opens, dispatch a TRUSTED click on the green "Generate data sheet" button
sleep 3
adom-desktop browser_input_dispatch '{
"sessionId":"test-trusted",
"type":"click",
"selector":"button.wg-button--primary"
}'
# Within ~5 seconds, browser_list_tabs should show a NEW tab on wago.priintcloud.com
sleep 5
adom-desktop browser_list_tabs '{"sessionId":"test-trusted"}'
# Expected: tabCount: 2, second tab url contains "priintcloud.com/datasheets/2601-3105"
```
If browser_list_tabs still shows tabCount: 1 after the trusted click, **see Feature 2** — the popup is opening but isn't being tracked.
---
## Feature 2 — auto-track popup tabs in `browser_list_tabs`
### The gap
`browser_list_tabs` only returns tabs that the agent created via `browser_open_tab`. Tabs that the page itself spawns (via `window.open()`, `target="_blank"` form submits, `<a target="_blank">` clicks) are real Chromium targets but invisible to the pup tab list. Result: even if a click does open a new tab, my container-side scraper has no way to find it, switch to it, or eval against it.
### The fix
Listen for `Target.targetCreated` and `Target.targetDestroyed` events from Chromium and keep an internal table of all top-level page targets per session, keyed by tabId. Include them all in `browser_list_tabs` output, with a flag indicating provenance.
Suggested response shape:
```json
{
"sessionId": "chip-fetcher",
"activeTabId": "tab-1",
"count": 2,
"tabs": [
{
"tabId": "tab-1",
"url": "https://www.wago.com/global/p/2601-3105",
"title": "PCB terminal block (2601-3105) | WAGO",
"active": true,
"opener": "user"
},
{
"tabId": "tab-popup-1",
"url": "https://wago.priintcloud.com/datasheets/2601-3105/en/abc...",
"title": "Datasheet - WAGO 2601-3105",
"active": false,
"opener": "popup",
"openerTabId": "tab-1"
}
]
}
```
### Implementation hints (Node side)
In `plugins/puppeteer/sessions/<sessionId>.js`:
```js
// After creating the browser:
browser.on("targetcreated", async (target) => {
if (target.type() !== "page") return;
const page = await target.page();
if (!page) return;
const tabId = `tab-popup-${++this.popupCounter}`;
this.tabs.set(tabId, {
page,
url: page.url(),
opener: target.opener() ? "popup" : "user",
openerTabId: target.opener() ? this.findTabIdForTarget(target.opener()) : null,
});
});
browser.on("targetdestroyed", (target) => {
// Remove from this.tabs
});
// list_tabs response builds from this.tabs.values()
```
### Acceptance test
```bash
# After Feature 1 lands, the trusted click on WAGO's Generate button
# should produce a NEW tab visible to browser_list_tabs:
adom-desktop browser_list_tabs '{"sessionId":"chip-fetcher"}'
# Expected: tabCount: 2, with tab-popup-1 entry showing priintcloud.com URL
```
Then I can `browser_eval` against the popup tab's tabId, fetch the PDF binary via in-page `fetch()`, base64 it back, and save — without any API-replay reverse-engineering.
---
## Suggested file/PR structure
- `Cargo.toml` — bump version
- `src/cli.rs` (or wherever the dispatch table lives) — register `browser_input_dispatch` action
- `plugins/puppeteer/index.js` (or per-session module) — implement the input handler + target-tracking listeners
- `plugins/puppeteer/types.d.ts` — extend the tab response shape with `opener` / `openerTabId`
- One integration test per feature (the acceptance tests above are good shapes for those)
A single PR with both features is fine — they go together (popup tracking is most useful when you can produce trusted clicks that spawn popups in the first place).
Once it ships, please bump the version + remind me to upgrade my container's binary so the chip-fetcher skill picks up the new commands.
— sent from john's container at john-galliaapril-… running chip-fetcher v0.1.x