barebrowse 0.4.7 → 0.5.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.1
4
+
5
+ bareagent tool parity + test fix.
6
+
7
+ ### bareagent adapter
8
+ - Added `hover`, `tabs`, `switchTab`, `pdf` tools (was 13 + assess, now 17 + assess)
9
+ - bareagent now exposes the full connect() API surface
10
+
11
+ ### Tests
12
+ - Fixed 2 snapshot URL prefix assertions (`# url` → `url: url`) to match 0.4.7 format change
13
+ - 69/69 passing
14
+
15
+ ### Version
16
+ - Package version: 0.5.1
17
+ - MCP server version string updated
18
+
19
+ ## 0.5.0
20
+
21
+ Privacy assessment via wearehere integration.
22
+
23
+ ### New: `assess` tool
24
+ - Scans any URL for privacy risks: cookies, trackers, fingerprinting, dark patterns, data brokers, form surveillance, link tracking, and toxic terms of service
25
+ - Returns compact JSON: score (0-100), risk level (low/moderate/high/critical), per-category breakdown (10 categories with score/max/summary), concerns list, and recommendation
26
+ - Available in MCP server (13th tool) and bareagent adapter (14th tool)
27
+ - Conditionally loaded: only available when `wearehere` npm package is installed
28
+ - Uses a dedicated `connect()` page per scan (isolated from the session page)
29
+
30
+ ### Integration
31
+ - `wearehere` added as optional dependency in package.json
32
+ - MCP server: dynamic `import('wearehere')` with try/catch fallback
33
+ - bareagent adapter: same dynamic import pattern
34
+ - Zero impact when wearehere is not installed — all existing tools work unchanged
35
+
36
+ ### Version
37
+ - Package version: 0.5.0
38
+ - MCP server version string updated
39
+
40
+ ## 0.4.8
41
+
42
+ - Fix: `browse()` one-shot also had `#` prefix (missed in 0.4.7)
43
+ - MCP server version string updated
44
+
3
45
  ## 0.4.7
4
46
 
5
47
  Snapshot URL prefix format changed from `# <url>` to `url: <url>`.
package/README.md CHANGED
@@ -87,11 +87,11 @@ Or manually add to your config (`claude_desktop_config.json`, `.cursor/mcp.json`
87
87
  }
88
88
  ```
89
89
 
90
- 12 tools: `browse`, `goto`, `snapshot`, `click`, `type`, `press`, `scroll`, `back`, `forward`, `drag`, `upload`, `pdf`. Session runs in hybrid mode with automatic cookie injection.
90
+ 12 tools: `browse`, `goto`, `snapshot`, `click`, `type`, `press`, `scroll`, `back`, `forward`, `drag`, `upload`, `pdf`. Plus `assess` (privacy scan) if [wearehere](https://github.com/hamr0/wearehere) is installed. Session runs in hybrid mode with automatic cookie injection.
91
91
 
92
92
  ### 3. Library -- for agentic automation
93
93
 
94
- Import barebrowse in your agent code. One-shot reads, interactive sessions, full observe-think-act loops. Works with any LLM orchestration library. Ships with a ready-made adapter for [bareagent](https://www.npmjs.com/package/bare-agent) (13 tools, auto-snapshot after every action).
94
+ Import barebrowse in your agent code. One-shot reads, interactive sessions, full observe-think-act loops. Works with any LLM orchestration library. Ships with a ready-made adapter for [bareagent](https://www.npmjs.com/package/bare-agent) (17 tools, auto-snapshot after every action).
95
95
 
96
96
  For code examples, API reference, and wiring instructions, see **[barebrowse.context.md](barebrowse.context.md)** -- the full integration guide.
97
97
 
@@ -139,6 +139,7 @@ Everything the agent can do through barebrowse:
139
139
  | **Upload** | Set files on a file input element |
140
140
  | **Screenshot** | Page capture as base64 PNG/JPEG/WebP |
141
141
  | **PDF** | Export page as PDF |
142
+ | **Assess** | Privacy scan: score (0-100), risk level, 10-category breakdown. Requires `npm install wearehere`. |
142
143
  | **Tabs** | List open tabs, switch between them |
143
144
  | **Wait for content** | Poll for text or CSS selector to appear on page |
144
145
  | **Wait for navigation** | SPA-aware: works for full page loads and pushState |
@@ -174,7 +175,7 @@ URL -> find/launch browser (chromium.js)
174
175
  -> agent-ready snapshot with [ref=N] markers
175
176
  ```
176
177
 
177
- 11 modules, 2,400 lines, zero dependencies.
178
+ 11 modules, 2,400 lines, zero required dependencies.
178
179
 
179
180
  ## Requirements
180
181
 
@@ -1,7 +1,7 @@
1
1
  # barebrowse -- Integration Guide
2
2
 
3
3
  > For AI assistants and developers wiring barebrowse into a project.
4
- > v0.4.2 | Node.js >= 22 | 0 required deps | MIT
4
+ > v0.5.1 | Node.js >= 22 | 0 required deps | MIT
5
5
 
6
6
  ## What this is
7
7
 
@@ -90,7 +90,7 @@ const snapshot = await browse('https://example.com', {
90
90
  The snapshot is a YAML-like ARIA tree. First line is the page URL, second is pruning stats, then the tree:
91
91
 
92
92
  ```
93
- # https://example.com/
93
+ url: https://example.com/
94
94
  # 379 chars → 45 chars (88% pruned)
95
95
  - heading "Example Domain" [level=1] [ref=3]
96
96
  - link "More information..." [ref=8]
@@ -184,10 +184,10 @@ try {
184
184
  ```
185
185
 
186
186
  `createBrowseTools(opts)` returns:
187
- - `tools` -- array of bareagent-compatible tool objects (browse, goto, snapshot, click, type, press, scroll, select, back, forward, drag, upload, screenshot)
187
+ - `tools` -- array of bareagent-compatible tool objects (browse, goto, snapshot, click, type, press, scroll, select, hover, back, forward, drag, upload, tabs, switchTab, pdf, screenshot, plus assess if wearehere installed)
188
188
  - `close()` -- cleanup function, call when done
189
189
 
190
- Action tools (click, type, press, scroll, goto) auto-return a fresh snapshot so the LLM always sees the result. 300ms settle delay after actions for DOM updates.
190
+ Action tools (click, type, press, scroll, hover, goto, back, forward, drag, upload, select, switchTab) auto-return a fresh snapshot so the LLM always sees the result. 300ms settle delay after actions for DOM updates.
191
191
 
192
192
  ## CLI session mode
193
193
 
@@ -233,7 +233,7 @@ barebrowse ships an MCP server for direct use with Claude Desktop, Cursor, or an
233
233
  }
234
234
  ```
235
235
 
236
- 12 tools exposed: `browse` (one-shot), `goto`, `snapshot`, `click`, `type`, `press`, `scroll`, `back`, `forward`, `drag`, `upload`, `pdf`.
236
+ 12 core tools: `browse` (one-shot), `goto`, `snapshot`, `click`, `type`, `press`, `scroll`, `back`, `forward`, `drag`, `upload`, `pdf`. Plus `assess` (privacy scan) if `wearehere` is installed (`npm install wearehere`).
237
237
 
238
238
  Action tools return `'ok'` -- the agent calls `snapshot` explicitly to observe. This avoids double-token output since MCP tool calls are cheap to chain.
239
239
 
@@ -270,9 +270,37 @@ URL -> chromium.js (find/launch browser, permission flags)
270
270
  | `src/interact.js` | ~170 | Click, type, press, scroll, hover, select |
271
271
  | `src/consent.js` | 200 | Auto-dismiss cookie consent dialogs across languages |
272
272
  | `src/stealth.js` | ~40 | Navigator patches for headless anti-detection |
273
- | `src/bareagent.js` | ~120 | Tool adapter for bareagent Loop |
273
+ | `src/bareagent.js` | ~250 | Tool adapter for bareagent Loop |
274
274
  | `mcp-server.js` | ~170 | MCP server (JSON-RPC over stdio) |
275
275
 
276
+ ## Privacy assessment (optional)
277
+
278
+ Install `wearehere` to add an `assess` tool to both the MCP server and bareagent adapter:
279
+
280
+ ```bash
281
+ npm install wearehere
282
+ ```
283
+
284
+ The `assess` tool navigates to a URL in an isolated browser page, scans for 10 privacy categories (cookies, trackers, fingerprinting, dark patterns, data brokers, form surveillance, link tracking, toxic terms, stored data, network traffic), and returns a compact JSON assessment:
285
+
286
+ ```json
287
+ {
288
+ "site": "example.com",
289
+ "score": 62,
290
+ "risk": "high",
291
+ "recommendation": "Significant privacy risks. Avoid sharing personal info here.",
292
+ "concerns": ["Heavy hidden tracking", "Aggressive device fingerprinting"],
293
+ "categories": {
294
+ "cookies": { "score": 10, "max": 15, "summary": "7 third-party cookies" },
295
+ "trackers": { "score": 20, "max": 20, "summary": "14 hidden elements" },
296
+ "profiling": { "score": 10, "max": 20, "summary": "Canvas + WebGL" },
297
+ "terms": { "score": 15, "max": 15, "summary": "Binding arbitration" }
298
+ }
299
+ }
300
+ ```
301
+
302
+ Useful for agent threshold decisions: "skip sites above score 40", "warn if terms score >= 10", etc. When wearehere is not installed, the tool simply doesn't appear — no errors, no impact.
303
+
276
304
  ## Gotchas
277
305
 
278
306
  1. **Refs are ephemeral.** Every `snapshot()` call generates new refs. Always snapshot before interacting. Never cache refs across snapshots.
package/mcp-server.js CHANGED
@@ -13,6 +13,13 @@ import { browse, connect } from './src/index.js';
13
13
  import { mkdirSync, writeFileSync } from 'node:fs';
14
14
  import { join } from 'node:path';
15
15
 
16
+ // Optional: privacy assessment via wearehere
17
+ let assessFn = null;
18
+ try {
19
+ ({ assess: assessFn } = await import('wearehere'));
20
+ } catch {}
21
+
22
+
16
23
  const MAX_CHARS_DEFAULT = 30000;
17
24
  const OUTPUT_DIR = join(process.cwd(), '.barebrowse');
18
25
 
@@ -158,6 +165,23 @@ const TOOLS = [
158
165
  },
159
166
  ];
160
167
 
168
+ // Add assess tool if wearehere is installed
169
+ if (assessFn) {
170
+ TOOLS.push({
171
+ name: 'assess',
172
+ description: 'Privacy assessment of any website. Navigates to the URL, scans for cookies, trackers, fingerprinting, dark patterns, data brokers, form surveillance, link tracking, and toxic terms. Returns a compact JSON with risk score (0-100), per-category breakdown, and recommendation. Powered by wearehere.',
173
+ inputSchema: {
174
+ type: 'object',
175
+ properties: {
176
+ url: { type: 'string', description: 'URL to assess (e.g. "https://example.com")' },
177
+ timeout: { type: 'number', description: 'Navigation timeout in ms (default: 30000)' },
178
+ settle: { type: 'number', description: 'Time to wait for trackers to load after page load, in ms (default: 3000)' },
179
+ },
180
+ required: ['url'],
181
+ },
182
+ });
183
+ }
184
+
161
185
  async function handleToolCall(name, args) {
162
186
  switch (name) {
163
187
  case 'browse': {
@@ -229,6 +253,19 @@ async function handleToolCall(name, args) {
229
253
  const page = await getPage();
230
254
  return await page.pdf({ landscape: args.landscape });
231
255
  }
256
+ case 'assess': {
257
+ if (!assessFn) throw new Error('wearehere is not installed. Run: npm install wearehere');
258
+ const page = await connect({ mode: 'hybrid' });
259
+ try {
260
+ const result = await assessFn(page, args.url, {
261
+ timeout: args.timeout,
262
+ settle: args.settle,
263
+ });
264
+ return JSON.stringify(result, null, 2);
265
+ } finally {
266
+ await page.close().catch(() => {});
267
+ }
268
+ }
232
269
  default:
233
270
  throw new Error(`Unknown tool: ${name}`);
234
271
  }
@@ -249,7 +286,7 @@ async function handleMessage(msg) {
249
286
  return jsonrpcResponse(id, {
250
287
  protocolVersion: '2024-11-05',
251
288
  capabilities: { tools: {} },
252
- serverInfo: { name: 'barebrowse', version: '0.4.6' },
289
+ serverInfo: { name: 'barebrowse', version: '0.5.1' },
253
290
  });
254
291
  }
255
292
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "barebrowse",
3
- "version": "0.4.7",
3
+ "version": "0.5.1",
4
4
  "description": "Authenticated web browsing for autonomous agents via CDP. URL in, pruned ARIA snapshot out.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -28,5 +28,8 @@
28
28
  "mcp",
29
29
  "headless"
30
30
  ],
31
+ "optionalDependencies": {
32
+ "wearehere": "^1.0.0"
33
+ },
31
34
  "license": "MIT"
32
35
  }
package/src/bareagent.js CHANGED
@@ -13,6 +13,12 @@
13
13
 
14
14
  import { browse, connect } from './index.js';
15
15
 
16
+ // Optional: privacy assessment via wearehere
17
+ let assessFn = null;
18
+ try {
19
+ ({ assess: assessFn } = await import('wearehere'));
20
+ } catch {}
21
+
16
22
  const SETTLE_MS = 300;
17
23
  const settle = () => new Promise((r) => setTimeout(r, SETTLE_MS));
18
24
 
@@ -133,6 +139,18 @@ export function createBrowseTools(opts = {}) {
133
139
  },
134
140
  execute: async ({ ref, value }) => actionAndSnapshot((page) => page.select(ref, value)),
135
141
  },
142
+ {
143
+ name: 'hover',
144
+ description: 'Hover over an element by its ref. Returns the updated snapshot.',
145
+ parameters: {
146
+ type: 'object',
147
+ properties: {
148
+ ref: { type: 'string', description: 'Element ref from snapshot' },
149
+ },
150
+ required: ['ref'],
151
+ },
152
+ execute: async ({ ref }) => actionAndSnapshot((page) => page.hover(ref)),
153
+ },
136
154
  {
137
155
  name: 'back',
138
156
  description: 'Go back in browser history. Returns the updated snapshot.',
@@ -171,6 +189,42 @@ export function createBrowseTools(opts = {}) {
171
189
  },
172
190
  execute: async ({ ref, files }) => actionAndSnapshot((page) => page.upload(ref, files)),
173
191
  },
192
+ {
193
+ name: 'tabs',
194
+ description: 'List all open tabs. Returns JSON array of { index, url, title }.',
195
+ parameters: { type: 'object', properties: {} },
196
+ execute: async () => {
197
+ const page = await getPage();
198
+ const tabList = await page.tabs();
199
+ return JSON.stringify(tabList, null, 2);
200
+ },
201
+ },
202
+ {
203
+ name: 'switchTab',
204
+ description: 'Switch to a tab by index. Returns the updated snapshot.',
205
+ parameters: {
206
+ type: 'object',
207
+ properties: {
208
+ index: { type: 'number', description: 'Tab index (from tabs tool output)' },
209
+ },
210
+ required: ['index'],
211
+ },
212
+ execute: async ({ index }) => actionAndSnapshot((page) => page.switchTab(index)),
213
+ },
214
+ {
215
+ name: 'pdf',
216
+ description: 'Export current page as PDF. Returns base64-encoded PDF data.',
217
+ parameters: {
218
+ type: 'object',
219
+ properties: {
220
+ landscape: { type: 'boolean', description: 'Landscape orientation (default: false)' },
221
+ },
222
+ },
223
+ execute: async ({ landscape } = {}) => {
224
+ const page = await getPage();
225
+ return await page.pdf({ landscape });
226
+ },
227
+ },
174
228
  {
175
229
  name: 'screenshot',
176
230
  description: 'Take a screenshot of the current page. Returns base64-encoded image.',
@@ -187,6 +241,32 @@ export function createBrowseTools(opts = {}) {
187
241
  },
188
242
  ];
189
243
 
244
+ // Add assess tool if wearehere is installed
245
+ if (assessFn) {
246
+ tools.push({
247
+ name: 'assess',
248
+ description: 'Privacy assessment of a website. Returns risk score (0-100), per-category breakdown, concerns, and recommendation.',
249
+ parameters: {
250
+ type: 'object',
251
+ properties: {
252
+ url: { type: 'string', description: 'URL to assess' },
253
+ timeout: { type: 'number', description: 'Navigation timeout in ms (default: 30000)' },
254
+ settle: { type: 'number', description: 'Time to wait for trackers to load, in ms (default: 3000)' },
255
+ },
256
+ required: ['url'],
257
+ },
258
+ execute: async ({ url, timeout, settle }) => {
259
+ const page = await connect(opts);
260
+ try {
261
+ const result = await assessFn(page, url, { timeout, settle });
262
+ return JSON.stringify(result, null, 2);
263
+ } finally {
264
+ await page.close().catch(() => {});
265
+ }
266
+ },
267
+ });
268
+ }
269
+
190
270
  return {
191
271
  tools,
192
272
  async close() {
package/src/index.js CHANGED
@@ -103,7 +103,7 @@ export async function browse(url, opts = {}) {
103
103
  } else {
104
104
  snapshot = raw;
105
105
  }
106
- const stats = `# ${url}\n# ${raw.length.toLocaleString()} chars → ${snapshot.length.toLocaleString()} chars (${Math.round((1 - snapshot.length / raw.length) * 100)}% pruned)`;
106
+ const stats = `url: ${url}\n${raw.length.toLocaleString()} chars → ${snapshot.length.toLocaleString()} chars (${Math.round((1 - snapshot.length / raw.length) * 100)}% pruned)`;
107
107
  snapshot = stats + '\n' + snapshot;
108
108
 
109
109
  // Step 7: Clean up