cbrowser 18.82.1 → 19.0.0
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/README.md +42 -3
- package/dist/analysis/accessibility-empathy.d.ts +43 -0
- package/dist/analysis/accessibility-empathy.d.ts.map +1 -1
- package/dist/analysis/accessibility-empathy.js +65 -0
- package/dist/analysis/accessibility-empathy.js.map +1 -1
- package/dist/analysis/agent-ready-audit.d.ts +44 -1
- package/dist/analysis/agent-ready-audit.d.ts.map +1 -1
- package/dist/analysis/agent-ready-audit.js +100 -40
- package/dist/analysis/agent-ready-audit.js.map +1 -1
- package/dist/analysis/bug-hunter.d.ts +11 -1
- package/dist/analysis/bug-hunter.d.ts.map +1 -1
- package/dist/analysis/bug-hunter.js +44 -6
- package/dist/analysis/bug-hunter.js.map +1 -1
- package/dist/analysis/competitive-benchmark.d.ts +49 -1
- package/dist/analysis/competitive-benchmark.d.ts.map +1 -1
- package/dist/analysis/competitive-benchmark.js +138 -14
- package/dist/analysis/competitive-benchmark.js.map +1 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +5 -2
- package/dist/browser.js.map +1 -1
- package/dist/cli.js +5 -5
- package/dist/cli.js.map +1 -1
- package/dist/cognitive/goal-decomposer.d.ts +41 -7
- package/dist/cognitive/goal-decomposer.d.ts.map +1 -1
- package/dist/cognitive/goal-decomposer.js +21 -2
- package/dist/cognitive/goal-decomposer.js.map +1 -1
- package/dist/mcp-tools/base/analysis-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/analysis-tools.js +7 -1
- package/dist/mcp-tools/base/analysis-tools.js.map +1 -1
- package/dist/mcp-tools/base/audit-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/audit-tools.js +10 -0
- package/dist/mcp-tools/base/audit-tools.js.map +1 -1
- package/dist/mcp-tools/base/site-knowledge-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/site-knowledge-tools.js +65 -8
- package/dist/mcp-tools/base/site-knowledge-tools.js.map +1 -1
- package/dist/mcp-tools/base/visual-testing-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/visual-testing-tools.js +53 -1
- package/dist/mcp-tools/base/visual-testing-tools.js.map +1 -1
- package/dist/mcp-tools/widget-kit.d.ts.map +1 -1
- package/dist/mcp-tools/widget-kit.js +29 -8
- package/dist/mcp-tools/widget-kit.js.map +1 -1
- package/dist/remediation/patch-generator.js +2 -2
- package/dist/remediation/patch-generator.js.map +1 -1
- package/dist/types.d.ts +80 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/visual/attention-quality.d.ts +38 -0
- package/dist/visual/attention-quality.d.ts.map +1 -1
- package/dist/visual/attention-quality.js +166 -51
- package/dist/visual/attention-quality.js.map +1 -1
- package/dist/visual/attention-transport.d.ts.map +1 -1
- package/dist/visual/attention-transport.js +46 -4
- package/dist/visual/attention-transport.js.map +1 -1
- package/dist/visual/freeze-animations.d.ts +71 -0
- package/dist/visual/freeze-animations.d.ts.map +1 -0
- package/dist/visual/freeze-animations.js +111 -0
- package/dist/visual/freeze-animations.js.map +1 -0
- package/dist/visual/llm-relevance.d.ts +6 -0
- package/dist/visual/llm-relevance.d.ts.map +1 -1
- package/dist/visual/llm-relevance.js +42 -1
- package/dist/visual/llm-relevance.js.map +1 -1
- package/dist/visual/narrative-reconcile.d.ts +61 -0
- package/dist/visual/narrative-reconcile.d.ts.map +1 -0
- package/dist/visual/narrative-reconcile.js +91 -0
- package/dist/visual/narrative-reconcile.js.map +1 -0
- package/dist/visual/persona-context.d.ts +18 -0
- package/dist/visual/persona-context.d.ts.map +1 -1
- package/dist/visual/persona-context.js +6 -0
- package/dist/visual/persona-context.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -128,7 +128,7 @@ Five tools to make your site ready for the AI agent era:
|
|
|
128
128
|
|
|
129
129
|
| Tool | What It Does |
|
|
130
130
|
|------|-------------|
|
|
131
|
-
| `agent_ready_audit` | Score site on findability, stability,
|
|
131
|
+
| `agent_ready_audit` | Score site on findability, stability, agent-perceivability, semantics (A-F grade) |
|
|
132
132
|
| `ai_benchmark` | Compare AI-friendliness across competitor URLs |
|
|
133
133
|
| `webmcp_ready_audit` | Audit MCP server for WebMCP compatibility |
|
|
134
134
|
| `remediation_patches` | Generate actionable code fixes for audit findings |
|
|
@@ -299,9 +299,36 @@ npx cbrowser competitive-benchmark \
|
|
|
299
299
|
|
|
300
300
|
---
|
|
301
301
|
|
|
302
|
+
## Upgrading to 19.0.0
|
|
303
|
+
|
|
304
|
+
One breaking change: the agent-ready **accessibility** axis is now
|
|
305
|
+
**agentPerceivability**, and three deprecated aliases are removed.
|
|
306
|
+
|
|
307
|
+
| removed | use instead |
|
|
308
|
+
|---|---|
|
|
309
|
+
| `score.accessibility` | `score.agentPerceivability` |
|
|
310
|
+
| `summary.dynamicContentCount` | `summary.deferredLoadingPatterns` |
|
|
311
|
+
| `comparison.bestAccessibility` | `comparison.bestAgentPerceivability` |
|
|
312
|
+
| issue `category: "accessibility"` | `category: "agentPerceivability"` |
|
|
313
|
+
|
|
314
|
+
All three replacements have carried identical values since 18.82.0, so if you
|
|
315
|
+
upgraded within that range you can switch keys before upgrading and take this
|
|
316
|
+
release with no further change.
|
|
317
|
+
|
|
318
|
+
The rename is not cosmetic. That axis measures whether a *machine* can perceive
|
|
319
|
+
your elements — ARIA present, elements carry text. It is **not** a WCAG
|
|
320
|
+
conformance score, and it returned 100 on a page where `empathy_audit` found two
|
|
321
|
+
WCAG violations. Both numbers were right; calling one of them "accessibility" was
|
|
322
|
+
not. Run `empathy_audit` for conformance, and expect the two to differ.
|
|
323
|
+
|
|
324
|
+
On input, `category: "accessibility"` is still accepted and scores identically, so
|
|
325
|
+
tools that *send* issues need not change immediately. Tools that *read* scores do.
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
302
329
|
## Geo Proxy
|
|
303
330
|
|
|
304
|
-
Test from
|
|
331
|
+
Test from 10 global regions via residential proxies:
|
|
305
332
|
|
|
306
333
|
```bash
|
|
307
334
|
npx cbrowser cognitive-journey \
|
|
@@ -311,7 +338,19 @@ npx cbrowser cognitive-journey \
|
|
|
311
338
|
--geo-region uk
|
|
312
339
|
```
|
|
313
340
|
|
|
314
|
-
**Regions:** `us-west`, `us-east`, `us-central`, `uk`, `germany`, `france`, `japan`, `australia`, `
|
|
341
|
+
**Regions:** `us-west`, `us-east`, `us-central`, `uk`, `germany`, `france`, `japan`, `australia`, `canada`, `brazil`
|
|
342
|
+
|
|
343
|
+
Geo routing needs your own residential-proxy credentials — the package ships the
|
|
344
|
+
mechanism and no keys. Set `IPROYAL_USERNAME` / `IPROYAL_PASSWORD`, or place a
|
|
345
|
+
`geo-proxy.json` at `~/.cbrowser/`. Without either, `--geo-region` fails loudly
|
|
346
|
+
rather than silently running from your own IP.
|
|
347
|
+
|
|
348
|
+
A `geo-proxy.json` may define additional regions; they merge over the ten above.
|
|
349
|
+
|
|
350
|
+
> **Corrected 2026-08-11.** This section previously advertised 12 regions
|
|
351
|
+
> including `india` and `singapore`. Those are not in the shipped defaults and
|
|
352
|
+
> resolve to nothing on a clean install — they existed only in a local config
|
|
353
|
+
> file on one machine. Advertising them was a claim the package could not keep.
|
|
315
354
|
|
|
316
355
|
---
|
|
317
356
|
|
|
@@ -4,6 +4,49 @@
|
|
|
4
4
|
* Learn more at https://cbrowser.ai - MIT License
|
|
5
5
|
*/
|
|
6
6
|
import type { EmpathyAuditResult, EmpathyAuditOptions } from "../types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Drop barriers outside the viewport when the audit is viewport-scoped.
|
|
9
|
+
*
|
|
10
|
+
* `viewportOnly` existed and had exactly ONE consumer:
|
|
11
|
+
* `detectSmallTouchTargets`. The other ten detectors scanned the whole document
|
|
12
|
+
* regardless of scope, so `scope: "viewport"` filtered touch targets and nothing
|
|
13
|
+
* else.
|
|
14
|
+
*
|
|
15
|
+
* Measured on /docs/home at 1280x800: six `sensory` barriers at y=5638, seven
|
|
16
|
+
* screens below the fold, with x up to 2029 -- 749px past the right edge. All
|
|
17
|
+
* six were counted in `affectedElements`, charged as `missing_alt: -2.2`, and
|
|
18
|
+
* folded into `barrierOnlyScore`. The response even stamped each one
|
|
19
|
+
* `outsideScreenshot: true`: the geometry was computed, published, and not
|
|
20
|
+
* acted on.
|
|
21
|
+
*
|
|
22
|
+
* So every viewport-scoped empathy score published to date may carry demand
|
|
23
|
+
* from content the persona never saw. It is the mirror of the bug
|
|
24
|
+
* `cognitive_effort`'s scopeNote documents -- that one measured too little and
|
|
25
|
+
* said so; this one measured too much and said nothing.
|
|
26
|
+
*
|
|
27
|
+
* Filtered HERE, once, after every detector and before scoring, rather than in
|
|
28
|
+
* each detector. Eleven copies of a rule is how it came to be applied in one
|
|
29
|
+
* place, and adding a twelfth detector must not be able to reintroduce this.
|
|
30
|
+
*
|
|
31
|
+
* A barrier with no rect is KEPT. Page-level findings -- navigation item count,
|
|
32
|
+
* animation presence, reading level -- have no coordinates and are properties of
|
|
33
|
+
* the page rather than of a location on it. Dropping the unlocatable would trade
|
|
34
|
+
* this bug for its opposite. (2026-08-05)
|
|
35
|
+
*/
|
|
36
|
+
export declare function filterBarriersToViewport<T extends {
|
|
37
|
+
rect?: {
|
|
38
|
+
x: number;
|
|
39
|
+
y: number;
|
|
40
|
+
width: number;
|
|
41
|
+
height: number;
|
|
42
|
+
};
|
|
43
|
+
}>(barriers: T[], viewport: {
|
|
44
|
+
width: number;
|
|
45
|
+
height: number;
|
|
46
|
+
}): {
|
|
47
|
+
kept: T[];
|
|
48
|
+
dropped: number;
|
|
49
|
+
};
|
|
7
50
|
export declare function formatEmpathyAuditReport(result: EmpathyAuditResult): string;
|
|
8
51
|
export declare function generateEmpathyAuditHtmlReport(result: EmpathyAuditResult): string;
|
|
9
52
|
export declare function runEmpathyAudit(url: string, options: EmpathyAuditOptions): Promise<EmpathyAuditResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accessibility-empathy.d.ts","sourceRoot":"","sources":["../../src/analysis/accessibility-empathy.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAmCH,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EASpB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"accessibility-empathy.d.ts","sourceRoot":"","sources":["../../src/analysis/accessibility-empathy.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAmCH,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EASpB,MAAM,aAAa,CAAC;AAwJrB;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,SAAS;IAAE,IAAI,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,EACnH,QAAQ,EAAE,CAAC,EAAE,EACb,QAAQ,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAWhC;AAy+DD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAmF3E;AAED,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAkTjF;AAqJD,wBAAsB,eAAe,CACnC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CA+Z7B"}
|
|
@@ -106,6 +106,48 @@ function adjustSeverityForLevel(severity, barrierWcagLevel, auditLevel) {
|
|
|
106
106
|
}
|
|
107
107
|
return severity;
|
|
108
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Drop barriers outside the viewport when the audit is viewport-scoped.
|
|
111
|
+
*
|
|
112
|
+
* `viewportOnly` existed and had exactly ONE consumer:
|
|
113
|
+
* `detectSmallTouchTargets`. The other ten detectors scanned the whole document
|
|
114
|
+
* regardless of scope, so `scope: "viewport"` filtered touch targets and nothing
|
|
115
|
+
* else.
|
|
116
|
+
*
|
|
117
|
+
* Measured on /docs/home at 1280x800: six `sensory` barriers at y=5638, seven
|
|
118
|
+
* screens below the fold, with x up to 2029 -- 749px past the right edge. All
|
|
119
|
+
* six were counted in `affectedElements`, charged as `missing_alt: -2.2`, and
|
|
120
|
+
* folded into `barrierOnlyScore`. The response even stamped each one
|
|
121
|
+
* `outsideScreenshot: true`: the geometry was computed, published, and not
|
|
122
|
+
* acted on.
|
|
123
|
+
*
|
|
124
|
+
* So every viewport-scoped empathy score published to date may carry demand
|
|
125
|
+
* from content the persona never saw. It is the mirror of the bug
|
|
126
|
+
* `cognitive_effort`'s scopeNote documents -- that one measured too little and
|
|
127
|
+
* said so; this one measured too much and said nothing.
|
|
128
|
+
*
|
|
129
|
+
* Filtered HERE, once, after every detector and before scoring, rather than in
|
|
130
|
+
* each detector. Eleven copies of a rule is how it came to be applied in one
|
|
131
|
+
* place, and adding a twelfth detector must not be able to reintroduce this.
|
|
132
|
+
*
|
|
133
|
+
* A barrier with no rect is KEPT. Page-level findings -- navigation item count,
|
|
134
|
+
* animation presence, reading level -- have no coordinates and are properties of
|
|
135
|
+
* the page rather than of a location on it. Dropping the unlocatable would trade
|
|
136
|
+
* this bug for its opposite. (2026-08-05)
|
|
137
|
+
*/
|
|
138
|
+
export function filterBarriersToViewport(barriers, viewport) {
|
|
139
|
+
const kept = barriers.filter((b) => {
|
|
140
|
+
if (!b.rect)
|
|
141
|
+
return true; // page-level finding, not a located one
|
|
142
|
+
const { x, y, width, height } = b.rect;
|
|
143
|
+
// Document coordinates, and a viewport-scoped audit never scrolls, so the
|
|
144
|
+
// visible band is y 0..height and x 0..width.
|
|
145
|
+
const intersectsY = y < viewport.height && y + height > 0;
|
|
146
|
+
const intersectsX = x < viewport.width && x + width > 0;
|
|
147
|
+
return intersectsY && intersectsX;
|
|
148
|
+
});
|
|
149
|
+
return { kept, dropped: barriers.length - kept.length };
|
|
150
|
+
}
|
|
109
151
|
/**
|
|
110
152
|
* Detect small touch targets that are hard for motor-impaired users
|
|
111
153
|
* v10.10.0: Always detect touch target issues regardless of persona
|
|
@@ -1300,6 +1342,20 @@ async function simulateAccessibilityJourney(page, url, goal, persona, scope = "v
|
|
|
1300
1342
|
await detectVisionBarriers(ctx);
|
|
1301
1343
|
break;
|
|
1302
1344
|
}
|
|
1345
|
+
// Scope is enforced HERE, once, rather than in each detector -- see
|
|
1346
|
+
// filterBarriersToViewport. Ten of the eleven detectors above never honoured
|
|
1347
|
+
// it, so a viewport audit was scoring content seven screens below the fold.
|
|
1348
|
+
if (ctx.viewportOnly) {
|
|
1349
|
+
const vp = await page.evaluate(() => ({
|
|
1350
|
+
width: window.innerWidth, height: window.innerHeight,
|
|
1351
|
+
})).catch(() => ({ width: 1280, height: 800 }));
|
|
1352
|
+
const { kept, dropped } = filterBarriersToViewport(ctx.barriers, vp);
|
|
1353
|
+
if (dropped > 0) {
|
|
1354
|
+
ctx.barriers.length = 0;
|
|
1355
|
+
ctx.barriers.push(...kept);
|
|
1356
|
+
ctx.outOfViewportDropped = dropped;
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1303
1359
|
// Use cognitive journey for realistic step tracking if API key available
|
|
1304
1360
|
// v18.35.0: Add hard timeout to prevent MCP proxy disconnection (~60s limit on claude.ai)
|
|
1305
1361
|
const journeyTimeoutMs = Math.min(maxTime * 1000, 45000); // Hard cap at 45s to leave margin
|
|
@@ -1599,6 +1655,10 @@ async function simulateAccessibilityJourney(page, url, goal, persona, scope = "v
|
|
|
1599
1655
|
// Deprecated alias, one release only. See EmpathyPersonaResult.
|
|
1600
1656
|
goalAchieved: noBlockingBarriers,
|
|
1601
1657
|
barriers: ctx.barriers,
|
|
1658
|
+
// Surfaced, not kept internal: a filter whose effect is invisible cannot be
|
|
1659
|
+
// told apart from a filter that never ran, and that is exactly the defect
|
|
1660
|
+
// this closes.
|
|
1661
|
+
...(ctx.outOfViewportDropped ? { outOfViewportBarriersDropped: ctx.outOfViewportDropped } : {}),
|
|
1602
1662
|
frictionPoints: ctx.frictionPoints,
|
|
1603
1663
|
// Filtered to the audit's conformance level, exactly as the top-level
|
|
1604
1664
|
// allWcagViolations is (see the filter near the end of runEmpathyAudit).
|
|
@@ -2737,6 +2797,11 @@ export async function runEmpathyAudit(url, options) {
|
|
|
2737
2797
|
topBarriers: deduplicatedBarriers, // v11.11.0: Deduplicated barriers grouped by type
|
|
2738
2798
|
combinedRemediation,
|
|
2739
2799
|
overallScore,
|
|
2800
|
+
// Summed from the per-persona audits: a filter whose effect is invisible is
|
|
2801
|
+
// indistinguishable from one that did not run.
|
|
2802
|
+
...(results.reduce((n, r) => n + (r.outOfViewportBarriersDropped ?? 0), 0) > 0
|
|
2803
|
+
? { outOfViewportBarriersDropped: results.reduce((n, r) => n + (r.outOfViewportBarriersDropped ?? 0), 0) }
|
|
2804
|
+
: {}),
|
|
2740
2805
|
duration: Date.now() - startTime,
|
|
2741
2806
|
};
|
|
2742
2807
|
}
|