@ulpi/browse 0.7.1 → 0.7.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.
- package/package.json +1 -1
- package/skill/SKILL.md +4 -2
- package/src/cli.ts +3 -2
- package/src/snapshot.ts +45 -7
package/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: browse
|
|
3
|
-
version: 2.5.
|
|
3
|
+
version: 2.5.1
|
|
4
4
|
description: |
|
|
5
5
|
Fast web browsing for AI coding agents via persistent headless Chromium daemon. Navigate to any URL,
|
|
6
6
|
read page content, click elements, fill forms, run JavaScript, take screenshots,
|
|
@@ -261,7 +261,8 @@ browse accessibility Accessibility tree snapshot (ARIA)
|
|
|
261
261
|
```
|
|
262
262
|
browse snapshot Full accessibility tree with @refs
|
|
263
263
|
browse snapshot -i Interactive elements only — terse flat list (minimal tokens)
|
|
264
|
-
browse snapshot -i -
|
|
264
|
+
browse snapshot -i -f Interactive elements — full indented tree with props
|
|
265
|
+
browse snapshot -i -V Interactive elements — viewport only (skip below-fold)
|
|
265
266
|
browse snapshot -c Compact (no empty structural elements)
|
|
266
267
|
browse snapshot -C Cursor-interactive (detect divs with cursor:pointer/onclick/tabindex)
|
|
267
268
|
browse snapshot -d <N> Limit depth to N levels
|
|
@@ -420,6 +421,7 @@ browse video status Check if recording is active
|
|
|
420
421
|
```
|
|
421
422
|
browse status Server health, uptime, session count
|
|
422
423
|
browse instances List all running browse servers (instance, PID, port, status)
|
|
424
|
+
browse version Print CLI version
|
|
423
425
|
browse stop Shutdown server
|
|
424
426
|
browse restart Kill + restart server
|
|
425
427
|
browse inspect Open DevTools (requires BROWSE_DEBUG_PORT)
|
package/src/cli.ts
CHANGED
|
@@ -612,7 +612,7 @@ Inspection: js <expr> | eval <file> | css <sel> <prop> | attrs <sel>
|
|
|
612
612
|
cookies | storage [set <k> <v>] | perf
|
|
613
613
|
value <sel> | count <sel> | clipboard [write <text>]
|
|
614
614
|
Visual: screenshot [path] | pdf [path] | responsive [prefix]
|
|
615
|
-
Snapshot: snapshot [-i] [-
|
|
615
|
+
Snapshot: snapshot [-i] [-f] [-V] [-c] [-C] [-d N] [-s sel]
|
|
616
616
|
Find: find role|text|label|placeholder|testid <query> [name]
|
|
617
617
|
Compare: diff <url1> <url2> | screenshot-diff <baseline> [current]
|
|
618
618
|
Multi-step: chain (reads JSON from stdin)
|
|
@@ -639,7 +639,8 @@ Options:
|
|
|
639
639
|
|
|
640
640
|
Snapshot flags:
|
|
641
641
|
-i Interactive elements only (terse flat list by default)
|
|
642
|
-
-
|
|
642
|
+
-f Full — indented tree with props and children (use with -i)
|
|
643
|
+
-V Viewport — only elements visible in current viewport
|
|
643
644
|
-c Compact — remove empty structural elements
|
|
644
645
|
-C Cursor-interactive — detect divs with cursor:pointer,
|
|
645
646
|
onclick, tabindex, data-action (missed by ARIA tree)
|
package/src/snapshot.ts
CHANGED
|
@@ -31,8 +31,9 @@ const INTERACTIVE_ROLES = new Set([
|
|
|
31
31
|
|
|
32
32
|
interface SnapshotOptions {
|
|
33
33
|
interactive?: boolean; // -i: only interactive elements (terse flat list by default)
|
|
34
|
-
|
|
34
|
+
full?: boolean; // -f: full indented ARIA tree with props/children (overrides -i terse default)
|
|
35
35
|
compact?: boolean; // -c: remove empty structural elements
|
|
36
|
+
viewport?: boolean; // -V: only elements visible in current viewport
|
|
36
37
|
depth?: number; // -d N: limit tree depth
|
|
37
38
|
selector?: string; // -s SEL: scope to CSS selector
|
|
38
39
|
cursor?: boolean; // -C: detect cursor-interactive elements (divs with cursor:pointer, onclick, tabindex)
|
|
@@ -73,9 +74,13 @@ export function parseSnapshotArgs(args: string[]): SnapshotOptions {
|
|
|
73
74
|
case '--compact':
|
|
74
75
|
opts.compact = true;
|
|
75
76
|
break;
|
|
76
|
-
case '-
|
|
77
|
-
case '--
|
|
78
|
-
opts.
|
|
77
|
+
case '-f':
|
|
78
|
+
case '--full':
|
|
79
|
+
opts.full = true;
|
|
80
|
+
break;
|
|
81
|
+
case '-V':
|
|
82
|
+
case '--viewport':
|
|
83
|
+
opts.viewport = true;
|
|
79
84
|
break;
|
|
80
85
|
case '-C':
|
|
81
86
|
case '--cursor':
|
|
@@ -422,12 +427,15 @@ export async function handleSnapshot(
|
|
|
422
427
|
refMap.set(ref, locator);
|
|
423
428
|
|
|
424
429
|
// Format output line
|
|
425
|
-
// -i without -
|
|
426
|
-
const terse = opts.interactive && !opts.
|
|
430
|
+
// -i without -f: terse flat list (no indent, no props, no children)
|
|
431
|
+
const terse = opts.interactive && !opts.full;
|
|
427
432
|
let outputLine: string;
|
|
428
433
|
if (terse) {
|
|
429
434
|
outputLine = `@${ref} [${node.role}]`;
|
|
430
|
-
if (node.name)
|
|
435
|
+
if (node.name) {
|
|
436
|
+
const name = node.name.length > 30 ? node.name.slice(0, 30) + '...' : node.name;
|
|
437
|
+
outputLine += ` "${name}"`;
|
|
438
|
+
}
|
|
431
439
|
} else {
|
|
432
440
|
outputLine = `${indent}@${ref} [${node.role}]`;
|
|
433
441
|
if (node.name) outputLine += ` "${node.name}"`;
|
|
@@ -438,6 +446,36 @@ export async function handleSnapshot(
|
|
|
438
446
|
output.push(outputLine);
|
|
439
447
|
}
|
|
440
448
|
|
|
449
|
+
// Viewport filter: remove elements below the visible viewport
|
|
450
|
+
if (opts.viewport) {
|
|
451
|
+
const vp = page.viewportSize();
|
|
452
|
+
if (vp) {
|
|
453
|
+
const toRemove = new Set<string>();
|
|
454
|
+
await Promise.all(
|
|
455
|
+
Array.from(refMap.entries()).map(async ([ref, loc]) => {
|
|
456
|
+
try {
|
|
457
|
+
const box = await loc.boundingBox({ timeout: 500 });
|
|
458
|
+
if (!box || box.y >= vp.height || box.y + box.height <= 0) {
|
|
459
|
+
toRemove.add(ref);
|
|
460
|
+
}
|
|
461
|
+
} catch {
|
|
462
|
+
toRemove.add(ref);
|
|
463
|
+
}
|
|
464
|
+
})
|
|
465
|
+
);
|
|
466
|
+
for (const ref of toRemove) {
|
|
467
|
+
refMap.delete(ref);
|
|
468
|
+
}
|
|
469
|
+
// Remove output lines for filtered refs
|
|
470
|
+
for (let i = output.length - 1; i >= 0; i--) {
|
|
471
|
+
const match = output[i].match(/@(e\d+)/);
|
|
472
|
+
if (match && toRemove.has(match[1])) {
|
|
473
|
+
output.splice(i, 1);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
441
479
|
// Cursor-interactive detection: supplement ARIA tree with DOM-level scan
|
|
442
480
|
if (opts.cursor) {
|
|
443
481
|
const result = await appendCursorElements(evalCtx, locatorRoot, opts, output, refMap, refCounter, bm);
|