@vexralabs/zerodom 0.0.1 → 0.0.2
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 +60 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
# zerodom
|
|
1
|
+
# @vexralabs/zerodom
|
|
2
|
+
|
|
3
|
+
**The visual action layer for AI web agents — TypeScript edition.**
|
|
4
|
+
|
|
5
|
+
See the page. Know exactly what to click.
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@vexralabs/zerodom)
|
|
8
|
+
[](../LICENSE)
|
|
2
9
|
|
|
3
10
|
TypeScript port of [ZeroDOM](https://github.com/DevHusnainAi/zerodom)'s core engine —
|
|
4
11
|
same interaction graph, same selector guarantees, for the Node/TS agent stack
|
|
5
12
|
(LangChain.js, the Vercel AI SDK, Playwright for Node).
|
|
6
13
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
`graph.toCompactText()`), not the whole toolchain. See the root
|
|
11
|
-
[README](../README.md) for the full feature set and design rationale; the logic
|
|
12
|
-
here is a line-for-line port of `../zerodom/parser.py` and `../zerodom/label_linker.py`,
|
|
13
|
-
so the same design notes (selector priority, label priority, escaping rules) apply.
|
|
14
|
+
When Hacker News has 30 identical `link "upvote"` pairs, accessibility trees fail.
|
|
15
|
+
ZeroDOM assigns 1:1 deterministic handles, resolving `[45]` to the exact DOM
|
|
16
|
+
element while keeping CSS selectors entirely out of the context window.
|
|
14
17
|
|
|
15
18
|
## Install
|
|
16
19
|
|
|
@@ -23,7 +26,7 @@ npm install @vexralabs/zerodom
|
|
|
23
26
|
```ts
|
|
24
27
|
import { ZeroDOM } from "@vexralabs/zerodom";
|
|
25
28
|
|
|
26
|
-
const graph = await ZeroDOM.fromPage(page); // any
|
|
29
|
+
const graph = await ZeroDOM.fromPage(page); // any Playwright Page
|
|
27
30
|
console.log(graph.toCompactText()); // what you send the model
|
|
28
31
|
const selectors = graph.selectorMap(); // { node_01: "#email-input", ... } — stays your side
|
|
29
32
|
```
|
|
@@ -34,6 +37,50 @@ import { parseHtml } from "@vexralabs/zerodom";
|
|
|
34
37
|
const graph = parseHtml(html, url); // parse HTML you already have, no browser needed
|
|
35
38
|
```
|
|
36
39
|
|
|
40
|
+
Real output, 11,882 tokens of Hacker News → 2,326:
|
|
41
|
+
|
|
42
|
+
```text
|
|
43
|
+
PAGE: Hacker News | https://news.ycombinator.com
|
|
44
|
+
[01] a 'Show HN: ZeroDOM — agents only need to know what they can click'
|
|
45
|
+
[02] a 'dev'
|
|
46
|
+
[03] a '214 comments'
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Core features
|
|
50
|
+
|
|
51
|
+
- **Deterministic parse, no LLM in the loop.** lxml-equivalent engine on linkedom,
|
|
52
|
+
identical output every run. Sub-50ms on most pages.
|
|
53
|
+
- **Selectors never enter the context window.** The model sees `[03]`; the CSS path
|
|
54
|
+
stays in `selectorMap()` on your side.
|
|
55
|
+
- **Shadow DOM handled.** Open shadow roots are parsed and light-DOM selectors are
|
|
56
|
+
scoped with `:light(…)`. Pages with no shadow root pay nothing.
|
|
57
|
+
- **Structural action diffs.** `+` appeared, `-` gone, `~` value changed — agents
|
|
58
|
+
stop re-reading entire pages.
|
|
59
|
+
- **iframe support.** Pass `{ frames: true }` to read same- and cross-origin frames.
|
|
60
|
+
|
|
61
|
+
## API
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { ZeroDOM, parseHtml } from "@vexralabs/zerodom";
|
|
65
|
+
|
|
66
|
+
// From a Playwright page (any object with content()/url()):
|
|
67
|
+
const graph = await ZeroDOM.fromPage(page);
|
|
68
|
+
|
|
69
|
+
// From raw HTML:
|
|
70
|
+
const graph = parseHtml(html, url);
|
|
71
|
+
|
|
72
|
+
// What to send the model:
|
|
73
|
+
graph.toCompactText(); // "[01] a 'Sign In'\n[02] input 'Email'..."
|
|
74
|
+
graph.toCompactText({ selectors: true }); // includes CSS selectors
|
|
75
|
+
graph.toCompactText({ hrefs: true }); // includes link destinations
|
|
76
|
+
|
|
77
|
+
// What stays on your side:
|
|
78
|
+
graph.selectorMap(); // { node_01: "#email-input", ... }
|
|
79
|
+
|
|
80
|
+
// Metadata:
|
|
81
|
+
graph.metadata; // { page_title, url, total_interactive_nodes, parsing_latency_ms, warning? }
|
|
82
|
+
```
|
|
83
|
+
|
|
37
84
|
## Why linkedom, not jsdom
|
|
38
85
|
|
|
39
86
|
`linkedom` gives a real `querySelector`/`getElementById` DOM — needed so every
|
|
@@ -51,3 +98,7 @@ npm install
|
|
|
51
98
|
npm run build # tsc -> dist/
|
|
52
99
|
npm test # node's built-in test runner, against the built dist
|
|
53
100
|
```
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
Apache 2.0 — see [LICENSE](../LICENSE).
|