crawlio-browser 1.5.2 → 1.5.3

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.
@@ -1,7 +1,7 @@
1
1
  // src/shared/constants.ts
2
2
  import { homedir } from "os";
3
3
  import { join } from "path";
4
- var PKG_VERSION = "1.5.2";
4
+ var PKG_VERSION = "1.5.3";
5
5
  var WS_PORT = 9333;
6
6
  var WS_PORT_MAX = 9342;
7
7
  var WS_HOST = "127.0.0.1";
@@ -9,7 +9,7 @@ import {
9
9
  WS_PORT_MAX,
10
10
  WS_RECONNECT_GRACE,
11
11
  WS_STALE_THRESHOLD
12
- } from "./chunk-BKBNDFXW.js";
12
+ } from "./chunk-OCCTLY6F.js";
13
13
 
14
14
  // src/mcp-server/index.ts
15
15
  import { randomBytes as randomBytes2 } from "crypto";
@@ -3709,17 +3709,37 @@ function createTools(bridge2, crawlio2) {
3709
3709
  }
3710
3710
  ];
3711
3711
  }
3712
+ function parseSnapshotRef(selector) {
3713
+ const m = /^\[ref=([a-zA-Z0-9]+)\]$/.exec(selector.trim());
3714
+ return m ? m[1] : null;
3715
+ }
3712
3716
  async function buildSmartObject(bridge2) {
3713
- const evaluate = (expression) => bridge2.send({ type: "browser_evaluate", expression }, 5e3);
3717
+ const evaluate = (expression) => {
3718
+ const hasReturn = /(?:^|[;\n{])\s*return\s/m.test(expression);
3719
+ const expr = hasReturn ? `(async () => { ${expression} })()` : expression;
3720
+ return bridge2.send({ type: "browser_evaluate", expression: expr }, 5e3);
3721
+ };
3714
3722
  const smart = {
3715
3723
  evaluate,
3716
3724
  click: async (selector, opts) => {
3725
+ const ref = parseSnapshotRef(selector);
3726
+ if (ref) {
3727
+ const result2 = await bridge2.send({ type: "browser_click", ref, button: "left", modifiers: {} }, 1e4);
3728
+ await new Promise((r) => setTimeout(r, opts?.settle ?? 500));
3729
+ return result2;
3730
+ }
3717
3731
  await pollActionability(bridge2, selector);
3718
3732
  const result = await bridge2.send({ type: "browser_click", selector, button: "left", modifiers: {} }, 1e4);
3719
3733
  await new Promise((r) => setTimeout(r, opts?.settle ?? 500));
3720
3734
  return result;
3721
3735
  },
3722
3736
  type: async (selector, text, opts) => {
3737
+ const ref = parseSnapshotRef(selector);
3738
+ if (ref) {
3739
+ const result2 = await bridge2.send({ type: "browser_type", ref, text, clearFirst: opts?.clearFirst ?? false, modifiers: {} }, 1e4);
3740
+ await new Promise((r) => setTimeout(r, opts?.settle ?? 300));
3741
+ return result2;
3742
+ }
3723
3743
  await pollActionability(bridge2, selector);
3724
3744
  const result = await bridge2.send({ type: "browser_type", selector, text, clearFirst: opts?.clearFirst ?? false, modifiers: {} }, 1e4);
3725
3745
  await new Promise((r) => setTimeout(r, opts?.settle ?? 300));
@@ -3732,6 +3752,11 @@ async function buildSmartObject(bridge2) {
3732
3752
  return result;
3733
3753
  },
3734
3754
  waitFor: async (selector, timeout) => {
3755
+ const ref = parseSnapshotRef(selector);
3756
+ if (ref) {
3757
+ await bridge2.send({ type: "browser_hover", ref }, timeout ?? 5e3);
3758
+ return { found: true, selector };
3759
+ }
3735
3760
  await pollActionability(bridge2, selector, timeout ?? 5e3);
3736
3761
  return { found: true, selector };
3737
3762
  },
@@ -4002,8 +4027,8 @@ function createCodeModeTools(bridge2, crawlio2) {
4002
4027
  "- compileRecording(session, { name, description? }) \u2014 compile RecordingSession to SKILL.md",
4003
4028
  " Returns { skillMarkdown, name, pageCount, interactionCount }",
4004
4029
  "- smart \u2014 auto-waiting wrappers and framework-specific data accessors:",
4005
- " smart.evaluate(expr) \u2014 raw JS evaluation via CDP",
4006
- " smart.click(selector, opts?) \u2014 poll + click + 500ms settle",
4030
+ " smart.evaluate(expr) \u2014 JS eval via CDP (auto-wraps if expr contains `return`)",
4031
+ " smart.click(selector, opts?) \u2014 poll + click + 500ms settle (accepts CSS or snapshot [ref=X])",
4007
4032
  " smart.type(selector, text, opts?) \u2014 poll + type + 300ms settle",
4008
4033
  " smart.navigate(url, opts?) \u2014 navigate + 1000ms settle",
4009
4034
  " smart.waitFor(selector, timeout?) \u2014 poll until actionable",
@@ -4112,7 +4137,7 @@ function createCodeModeTools(bridge2, crawlio2) {
4112
4137
  process.title = "Crawlio Agent";
4113
4138
  var initMode = process.argv.includes("init") || process.argv.includes("--setup") || process.argv.includes("setup");
4114
4139
  if (initMode) {
4115
- const { runInit } = await import("./init-5MP7GP7G.js");
4140
+ const { runInit } = await import("./init-NEXLUHXC.js");
4116
4141
  await runInit(process.argv.slice(2));
4117
4142
  process.exit(0);
4118
4143
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  PKG_VERSION
3
- } from "./chunk-BKBNDFXW.js";
3
+ } from "./chunk-OCCTLY6F.js";
4
4
 
5
5
  // src/mcp-server/init.ts
6
6
  import { execFileSync, spawn } from "child_process";
@@ -311,7 +311,7 @@ function isAlreadyConfigured(config) {
311
311
  function buildCloudflareEntry(accountId, apiToken) {
312
312
  return {
313
313
  command: "npx",
314
- args: ["-y", "@cloudflare/mcp-server-cloudflare@0.2.0", "run", accountId],
314
+ args: ["-y", "@cloudflare/mcp-server-cloudflare", "run", accountId],
315
315
  env: { CLOUDFLARE_API_TOKEN: apiToken }
316
316
  };
317
317
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "crawlio-browser",
3
- "version": "1.5.2",
3
+ "version": "1.5.3",
4
4
  "description": "MCP server with 96 CDP-backed tools for browser automation — screenshots, DOM, network capture, framework detection, cookies, storage, session recording, performance metrics via Chrome",
5
5
  "type": "module",
6
6
  "main": "dist/mcp-server/index.js",
@@ -112,7 +112,17 @@ return await smart.snapshot()
112
112
  return await smart.snapshot()
113
113
  ```
114
114
 
115
- Returns `{ snapshot: string }` — the a11y tree text. Use this to discover available elements when selectors fail.
115
+ Returns `{ snapshot: string }` — the a11y tree text with `[ref=X]` labels on interactive elements. Use this to discover available elements when selectors fail.
116
+
117
+ Snapshot refs like `[ref=e3]` work directly with `smart.click`, `smart.type`, and `smart.waitFor`:
118
+
119
+ ```js
120
+ const snap = await smart.snapshot()
121
+ // snap.snapshot contains: [ref=e3] button "Platform" ...
122
+ await smart.click('[ref=e3]') // clicks via the snapshot ref system (not CSS)
123
+ ```
124
+
125
+ These refs are resolved from the cached snapshot — they are NOT CSS selectors. They bypass `document.querySelector` and use CDP node resolution instead.
116
126
 
117
127
  ### Evaluate JavaScript
118
128
 
@@ -120,6 +130,15 @@ Returns `{ snapshot: string }` — the a11y tree text. Use this to discover avai
120
130
  return await smart.evaluate("document.title")
121
131
  ```
122
132
 
133
+ For multi-statement evaluation, just use `return` — it auto-wraps in an IIFE:
134
+
135
+ ```js
136
+ return await smart.evaluate(`
137
+ const links = Array.from(document.querySelectorAll('a[href]'));
138
+ return links.map(a => ({ text: a.textContent.trim(), href: a.href }));
139
+ `)
140
+ ```
141
+
123
142
  ### Framework Detection
124
143
 
125
144
  ```js
@@ -232,9 +232,9 @@ The `smart` object provides auto-waiting wrappers and framework-specific data:
232
232
 
233
233
  | Method | Description |
234
234
  |--------|-------------|
235
- | `smart.evaluate(expr)` | Raw JS evaluation via CDP |
236
- | `smart.click(selector, opts?)` | Poll + click + 500ms settle |
237
- | `smart.type(selector, text, opts?)` | Poll + type + 300ms settle |
235
+ | `smart.evaluate(expr)` | JS evaluation via CDP. Auto-wraps in IIFE if `return` is used. |
236
+ | `smart.click(selector, opts?)` | Poll + click + 500ms settle. Accepts CSS selectors or snapshot refs (`[ref=e3]`). |
237
+ | `smart.type(selector, text, opts?)` | Poll + type + 300ms settle. Accepts CSS selectors or snapshot refs. |
238
238
  | `smart.navigate(url, opts?)` | Navigate + 1000ms settle |
239
239
  | `smart.waitFor(selector, timeout?)` | Poll until element is actionable |
240
240
  | `smart.snapshot()` | Capture accessibility snapshot |