chromeflow 0.1.55 → 0.1.57
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/CLAUDE.md +29 -6
- package/README.md +1 -2
- package/dist/setup.js +6 -8
- package/dist/tools/browser.js +18 -1
- package/dist/tools/flow.js +0 -13
- package/dist/tools/highlight.js +0 -24
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -34,10 +34,8 @@ Do NOT ask "should I open the browser?" — just do it. The user expects seamles
|
|
|
34
34
|
## Guided flow pattern
|
|
35
35
|
|
|
36
36
|
```
|
|
37
|
-
1.
|
|
38
|
-
2.
|
|
39
|
-
mark_step_done(0) — ALWAYS mark step 0 done right after open_page succeeds
|
|
40
|
-
3. For each step:
|
|
37
|
+
1. open_page(url) — navigate to the right page (add new_tab=true to keep current tab open)
|
|
38
|
+
2. For each step:
|
|
41
39
|
a. Claude acts directly:
|
|
42
40
|
click_element("Save") — press buttons/links Claude can press
|
|
43
41
|
get_page_text() or wait_for_selector(".success") — ALWAYS confirm after click; click_element returns after 600ms regardless of outcome
|
|
@@ -62,8 +60,7 @@ Do NOT ask "should I open the browser?" — just do it. The user expects seamles
|
|
|
62
60
|
find_and_highlight(text, msg) — show the user what to do
|
|
63
61
|
wait_for_click() — wait for user interaction
|
|
64
62
|
[after fill_input] clear_overlays() — always clear after filling
|
|
65
|
-
|
|
66
|
-
4. clear_overlays() — clean up when done
|
|
63
|
+
3. clear_overlays() — clean up when done
|
|
67
64
|
```
|
|
68
65
|
|
|
69
66
|
**Default to automation.** Only pause for human input when the step genuinely requires
|
|
@@ -238,4 +235,30 @@ document.body.style.zoom = '1';
|
|
|
238
235
|
1. Retry the exact same `execute_script` call
|
|
239
236
|
2. If still failing, use `find_and_highlight` to show the user a download button to click manually
|
|
240
237
|
|
|
238
|
+
**Shadow DOM `[role=radio]` / custom radios silently no-op**: On sites like Outlier,
|
|
239
|
+
`element.click()` on a shadow-DOM radio often doesn't flip `aria-checked`. Two things
|
|
240
|
+
must be true: (a) the element must be scrolled into view FIRST (`scrollIntoView({block:'center'})`),
|
|
241
|
+
and (b) the full pointer-event chain must fire — not just `click()`:
|
|
242
|
+
```js
|
|
243
|
+
['pointerdown','mousedown','pointerup','mouseup','click'].forEach(t =>
|
|
244
|
+
el.dispatchEvent(new MouseEvent(t, {bubbles: true, cancelable: true}))
|
|
245
|
+
);
|
|
246
|
+
```
|
|
247
|
+
After scroll, re-query the radio list — its length may change as more content becomes
|
|
248
|
+
visible. Then verify `aria-checked === "true"` before moving on.
|
|
249
|
+
|
|
250
|
+
**Visibility-detection overlays** (e.g. Multimango's "Content Hidden" black overlay):
|
|
251
|
+
Some sites render a full-screen overlay when the tab loses focus, triggered by
|
|
252
|
+
`document.visibilityState` / `document.hidden`. Chromeflow tab-switching triggers it.
|
|
253
|
+
Workaround — remove the overlay and patch the APIs:
|
|
254
|
+
```js
|
|
255
|
+
document.querySelectorAll('[style*="z-index: 99999"]').forEach(el => el.remove());
|
|
256
|
+
Object.defineProperty(document, 'hidden', { get: () => false, configurable: true });
|
|
257
|
+
Object.defineProperty(document, 'visibilityState', { get: () => 'visible', configurable: true });
|
|
258
|
+
['visibilitychange','blur'].forEach(t =>
|
|
259
|
+
document.addEventListener(t, e => e.stopImmediatePropagation(), true)
|
|
260
|
+
);
|
|
261
|
+
```
|
|
262
|
+
Re-apply after every navigation.
|
|
263
|
+
|
|
241
264
|
**Never use Bash to work around a stuck browser interaction.**
|
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ Chromeflow works in **your actual Chrome browser**, where you're already logged
|
|
|
17
17
|
| **Browser** | Your real Chrome (sessions intact) | Fresh instance, logged out of everything |
|
|
18
18
|
| **Auth / 2FA** | Already handled — pauses when needed | Can't handle — blocks completely |
|
|
19
19
|
| **Page understanding** | DOM queries (fast, cheap, reliable) | Screenshots + vision model (slow, expensive) |
|
|
20
|
-
| **Human-in-the-loop** |
|
|
20
|
+
| **Human-in-the-loop** | Highlights, pauses on sensitive input | Fully autonomous, no interaction |
|
|
21
21
|
| **Integration** | MCP server for Claude Code | Standalone, not Claude Code aware |
|
|
22
22
|
| **Credential capture** | Reads API keys → writes to `.env` | Not designed for this |
|
|
23
23
|
|
|
@@ -90,7 +90,6 @@ Claude will navigate, highlight steps, click what it can, pause for anything sen
|
|
|
90
90
|
| Screenshot + save + copy to clipboard | `take_and_copy_screenshot` |
|
|
91
91
|
| Screenshot the terminal window | `capture_terminal` |
|
|
92
92
|
| Save/restore form state across tabs | `save_page_state`, `restore_page_state` |
|
|
93
|
-
| Show a step-by-step guide panel | `show_guide_panel`, `mark_step_done` |
|
|
94
93
|
|
|
95
94
|
### File uploads
|
|
96
95
|
|
package/dist/setup.js
CHANGED
|
@@ -53,9 +53,8 @@ Do NOT ask "should I open the browser?" \u2014 just do it. The user expects seam
|
|
|
53
53
|
## Guided flow pattern
|
|
54
54
|
|
|
55
55
|
\`\`\`
|
|
56
|
-
1.
|
|
57
|
-
2.
|
|
58
|
-
3. For each step:
|
|
56
|
+
1. open_page(url) \u2014 navigate to the right page
|
|
57
|
+
2. For each step:
|
|
59
58
|
a. [if needed] take_screenshot() \u2014 only when you need to locate something
|
|
60
59
|
b. Claude acts directly:
|
|
61
60
|
click_element("Save") \u2014 press buttons/links Claude can press
|
|
@@ -64,8 +63,7 @@ Do NOT ask "should I open the browser?" \u2014 just do it. The user expects seam
|
|
|
64
63
|
Or pause for the user:
|
|
65
64
|
find_and_highlight(text, msg) \u2014 show the user what to do
|
|
66
65
|
wait_for_click() \u2014 wait for user interaction
|
|
67
|
-
|
|
68
|
-
4. clear_overlays() \u2014 clean up when done
|
|
66
|
+
3. clear_overlays() \u2014 clean up when done
|
|
69
67
|
\`\`\`
|
|
70
68
|
|
|
71
69
|
**Default to automation.** Only pause for human input when the step genuinely requires
|
|
@@ -153,10 +151,8 @@ const CHROMEFLOW_TOOLS = [
|
|
|
153
151
|
"click_element",
|
|
154
152
|
"wait_for_click",
|
|
155
153
|
"wait_for_selector",
|
|
156
|
-
"mark_step_done",
|
|
157
154
|
"find_and_highlight",
|
|
158
155
|
"highlight_region",
|
|
159
|
-
"show_guide_panel",
|
|
160
156
|
// v0.1.23+
|
|
161
157
|
"switch_to_tab",
|
|
162
158
|
"list_tabs",
|
|
@@ -177,7 +173,9 @@ const CHROMEFLOW_TOOLS = [
|
|
|
177
173
|
// v0.1.42+
|
|
178
174
|
"set_dialog_response",
|
|
179
175
|
// v0.1.46+
|
|
180
|
-
"type_text"
|
|
176
|
+
"type_text",
|
|
177
|
+
// v0.1.57+
|
|
178
|
+
"inspect_request_headers"
|
|
181
179
|
].map((t) => `mcp__chromeflow__${t}`);
|
|
182
180
|
function patchSettingsLocalJson(cwd) {
|
|
183
181
|
const claudeDir = join(cwd, ".claude");
|
package/dist/tools/browser.js
CHANGED
|
@@ -190,7 +190,7 @@ For prompt: the value string is returned to the page. For confirm: true/false is
|
|
|
190
190
|
);
|
|
191
191
|
server.tool(
|
|
192
192
|
"clear_overlays",
|
|
193
|
-
"Remove all highlights and callout annotations from the current page.
|
|
193
|
+
"Remove all highlights and callout annotations from the current page.",
|
|
194
194
|
{},
|
|
195
195
|
async () => {
|
|
196
196
|
await bridge.request({ type: "clear" });
|
|
@@ -321,6 +321,23 @@ PAGE ALERT: "${alert}" \u2014 the page showed a dialog with this message. Read i
|
|
|
321
321
|
};
|
|
322
322
|
}
|
|
323
323
|
);
|
|
324
|
+
server.tool(
|
|
325
|
+
"inspect_request_headers",
|
|
326
|
+
`Navigate to a URL and capture the exact HTTP request headers Chrome sends for the main document request.
|
|
327
|
+
Use this to diagnose server-side bot detection \u2014 e.g. when a site returns a "mobile" or "switch devices" page despite the client reporting desktop.
|
|
328
|
+
Returns the request method, URL, and all headers including Sec-CH-UA-* client hints.
|
|
329
|
+
This tool DOES navigate the active tab to the URL.`,
|
|
330
|
+
{
|
|
331
|
+
url: z.string().url().describe("URL to navigate to and capture headers for")
|
|
332
|
+
},
|
|
333
|
+
async ({ url }) => {
|
|
334
|
+
const response = await bridge.request({ type: "inspect_request_headers", url }, 2e4);
|
|
335
|
+
const r = response;
|
|
336
|
+
return {
|
|
337
|
+
content: [{ type: "text", text: r.message ?? "(no headers captured)" }]
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
);
|
|
324
341
|
}
|
|
325
342
|
export {
|
|
326
343
|
registerBrowserTools
|
package/dist/tools/flow.js
CHANGED
|
@@ -138,19 +138,6 @@ ${lines.join("\n")}`
|
|
|
138
138
|
};
|
|
139
139
|
}
|
|
140
140
|
);
|
|
141
|
-
server.tool(
|
|
142
|
-
"mark_step_done",
|
|
143
|
-
"Mark a step in the guide panel as completed (shows a green check). Call this after any step finishes \u2014 whether Claude acted autonomously or the user completed a highlighted step via wait_for_click.",
|
|
144
|
-
{
|
|
145
|
-
stepIndex: z.number().int().describe("0-based index of the step to mark done")
|
|
146
|
-
},
|
|
147
|
-
async ({ stepIndex }) => {
|
|
148
|
-
await bridge.request({ type: "mark_step_done", stepIndex });
|
|
149
|
-
return {
|
|
150
|
-
content: [{ type: "text", text: `Step ${stepIndex + 1} marked as done.` }]
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
);
|
|
154
141
|
}
|
|
155
142
|
export {
|
|
156
143
|
registerFlowTools
|
package/dist/tools/highlight.js
CHANGED
|
@@ -64,30 +64,6 @@ Only pass x/y/width/height when you have no selector and already have fresh coor
|
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
66
|
);
|
|
67
|
-
server.tool(
|
|
68
|
-
"show_guide_panel",
|
|
69
|
-
"Show a floating step-by-step guide panel on the page to help the user understand what they need to do",
|
|
70
|
-
{
|
|
71
|
-
title: z.string().describe("Title of the guide (e.g. 'Set up Stripe API keys')"),
|
|
72
|
-
steps: z.array(
|
|
73
|
-
z.object({
|
|
74
|
-
text: z.string().describe("Step instruction text"),
|
|
75
|
-
done: z.boolean().optional().describe("Whether this step is already completed")
|
|
76
|
-
})
|
|
77
|
-
).describe("Ordered list of steps")
|
|
78
|
-
},
|
|
79
|
-
async ({ title, steps }) => {
|
|
80
|
-
await bridge.request({ type: "show_panel", title, steps });
|
|
81
|
-
return {
|
|
82
|
-
content: [
|
|
83
|
-
{
|
|
84
|
-
type: "text",
|
|
85
|
-
text: `Guide panel shown: "${title}" with ${steps.length} steps.`
|
|
86
|
-
}
|
|
87
|
-
]
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
);
|
|
91
67
|
}
|
|
92
68
|
export {
|
|
93
69
|
registerHighlightTools
|
package/package.json
CHANGED