chromeflow 0.1.46 → 0.1.48

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 CHANGED
@@ -43,6 +43,7 @@ Do NOT ask "should I open the browser?" — just do it. The user expects seamles
43
43
  get_page_text() or wait_for_selector(".success") — ALWAYS confirm after click; click_element returns after 600ms regardless of outcome
44
44
  fill_form([{label, value}, ...]) — fill multiple fields in one call; prefer over repeated fill_input
45
45
  fill_input("Product name", "Pro") — fill a single field (works on React, CodeMirror, and contenteditable)
46
+ type_text("hello world") — type via trusted keyboard events (use when fill_input fails isTrusted checks)
46
47
  set_file_input("Upload", "/abs/path/to/file.zip") — upload a file to a file input (even hidden inputs)
47
48
  clear_overlays() — call this immediately after fill_input/fill_form succeeds
48
49
  scroll_to_element("label text") — jump directly to a known field; prefer this over scroll_page when the target is known
@@ -155,13 +156,17 @@ screenshot to check what happened.
155
156
  **Multiple elements with the same label** (e.g. many "Remove" buttons):
156
157
  `click_element("Remove", nth=3)` — use `nth` (1-based) to target the specific one by order top-to-bottom. Check `get_form_fields` or `get_page_text` first to determine which index corresponds to the right section.
157
158
 
158
- **`fill_input` not found:**
159
+ **`fill_input` not found or rejected by the page:**
159
160
  1. `click_element(hint)` to focus the field, then retry `fill_input`
160
- 2. `find_and_highlight(hint, "Click here I'll fill it in")` (no `valueToType`) then
161
+ 2. If the site rejects programmatic input (isTrusted check, shadow DOM, custom editors):
162
+ - `click_element(hint)` to focus the field
163
+ - `execute_script("document.execCommand('selectAll')")` to clear existing content
164
+ - `type_text("new value")` — uses CDP trusted keyboard events that pass isTrusted checks
165
+ 3. `find_and_highlight(hint, "Click here — I'll fill it in")` (no `valueToType`) then
161
166
  `wait_for_click()` — the user's click focuses the field and `fill_input`'s active-element
162
167
  fallback fills it automatically
163
- 3. Call `clear_overlays()` after `fill_input` succeeds
164
- 4. Only use `valueToType` when the user must personally type the value (password, personal data)
168
+ 4. Call `clear_overlays()` after `fill_input` succeeds
169
+ 5. Only use `valueToType` when the user must personally type the value (password, personal data)
165
170
 
166
171
  **Waiting for async results** (build, save, deploy): `wait_for_selector(selector, timeout)` — never poll with screenshots.
167
172
 
package/dist/setup.js CHANGED
@@ -175,7 +175,9 @@ const CHROMEFLOW_TOOLS = [
175
175
  // v0.1.40+
176
176
  "capture_terminal",
177
177
  // v0.1.42+
178
- "set_dialog_response"
178
+ "set_dialog_response",
179
+ // v0.1.46+
180
+ "type_text"
179
181
  ].map((t) => `mcp__chromeflow__${t}`);
180
182
  function patchSettingsLocalJson(cwd) {
181
183
  const claudeDir = join(cwd, ".claude");
@@ -252,6 +252,27 @@ ${lines.join("\n")}${r.warning ?? ""}` }]
252
252
  };
253
253
  }
254
254
  );
255
+ server.tool(
256
+ "type_text",
257
+ `Type text into the currently focused element using trusted keyboard events via Chrome DevTools Protocol.
258
+ Unlike fill_input (which sets .value programmatically), this produces real keystrokes that pass isTrusted checks. Use this when:
259
+ - fill_input fails because the site validates event.isTrusted (e.g. Outlier, DataAnnotation code editors)
260
+ - The target is a shadow DOM input, custom web component, or heavily guarded editor
261
+ - You need to type into a CodeMirror/Monaco/Ace editor that rejects programmatic value changes
262
+
263
+ Usage: first click_element or execute_script to focus the target field, then call type_text with the content.
264
+ To clear existing content before typing, use execute_script("document.execCommand('selectAll')") first.`,
265
+ {
266
+ text: z.string().describe("The text to type into the focused element")
267
+ },
268
+ async ({ text }) => {
269
+ const response = await bridge.request({ type: "type_text", text });
270
+ const r = response;
271
+ return {
272
+ content: [{ type: "text", text: r.message ?? (r.success ? "Text typed successfully" : "Failed to type text") }]
273
+ };
274
+ }
275
+ );
255
276
  server.tool(
256
277
  "set_file_input",
257
278
  `Upload a file to a file input field. Works even when the input is visually hidden behind a custom drag-and-drop zone.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chromeflow",
3
- "version": "0.1.46",
3
+ "version": "0.1.48",
4
4
  "description": "Browser guidance MCP server for Claude Code — highlights, clicks, fills, and captures from the web so you don't have to.",
5
5
  "type": "module",
6
6
  "bin": {