@kritchoff/agent-browser 0.9.2 → 0.9.4

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.
@@ -0,0 +1,287 @@
1
+ export async function getDualModeSnapshot(page, options = {}) {
2
+ const session = await page.context().newCDPSession(page);
3
+ let nodes = [];
4
+ let isDualMode = false;
5
+ try {
6
+ const result = (await session.send('Accessibility.getDualModeAXTree'));
7
+ nodes = result.nodes;
8
+ isDualMode = true;
9
+ }
10
+ catch (e) {
11
+ try {
12
+ const result = (await session.send('Accessibility.getFullAXTree'));
13
+ nodes = result.nodes;
14
+ }
15
+ catch (e2) {
16
+ console.warn('Failed to fetch AXTree via CDP:', e2);
17
+ return { tree: '(accessibility tree unavailable)', refs: {} };
18
+ }
19
+ }
20
+ finally {
21
+ await session.detach();
22
+ }
23
+ const refs = {};
24
+ let tree = '';
25
+ resetRefs();
26
+ if (isDualMode) {
27
+ const rootNodes = buildTreeFromFlatNodes(nodes);
28
+ tree = processDualModeTree(rootNodes, refs, options.interactive ?? false);
29
+ }
30
+ else {
31
+ const rootNodes = buildStandardTree(nodes);
32
+ tree = processStandardTree(rootNodes, refs, options.interactive ?? false);
33
+ }
34
+ return { tree, refs };
35
+ }
36
+ function buildTreeFromFlatNodes(nodes) {
37
+ const nodeMap = new Map();
38
+ nodes.forEach((n) => nodeMap.set(n.core.nodeId, n));
39
+ const roots = [];
40
+ nodes.forEach((node) => {
41
+ if (node.core.childrenIds) {
42
+ node.children = node.core.childrenIds
43
+ .map((id) => nodeMap.get(id))
44
+ .filter((n) => !!n);
45
+ }
46
+ const parentId = node.core.parentId;
47
+ if (parentId === undefined || !nodeMap.has(parentId)) {
48
+ roots.push(node);
49
+ }
50
+ });
51
+ return roots;
52
+ }
53
+ function buildStandardTree(nodes) {
54
+ const nodeMap = new Map();
55
+ // Initialize with empty children array
56
+ nodes.forEach((n) => nodeMap.set(n.nodeId, { ...n, children: [] }));
57
+ const roots = [];
58
+ const childrenIdsSet = new Set();
59
+ nodes.forEach((node) => {
60
+ if (node.childIds) {
61
+ const parent = nodeMap.get(node.nodeId);
62
+ if (parent) {
63
+ node.childIds.forEach((childId) => {
64
+ const child = nodeMap.get(childId);
65
+ if (child) {
66
+ parent.children.push(child);
67
+ childrenIdsSet.add(childId);
68
+ }
69
+ });
70
+ }
71
+ }
72
+ });
73
+ nodes.forEach((node) => {
74
+ if (!childrenIdsSet.has(node.nodeId)) {
75
+ const root = nodeMap.get(node.nodeId);
76
+ if (root)
77
+ roots.push(root);
78
+ }
79
+ });
80
+ return roots;
81
+ }
82
+ let refCounter = 0;
83
+ function resetRefs() {
84
+ refCounter = 0;
85
+ }
86
+ function nextRef() {
87
+ return `e${++refCounter}`;
88
+ }
89
+ const INTERACTIVE_ROLES = new Set([
90
+ 'button',
91
+ 'link',
92
+ 'textbox',
93
+ 'checkbox',
94
+ 'radio',
95
+ 'combobox',
96
+ 'listbox',
97
+ 'menuitem',
98
+ 'option',
99
+ 'searchbox',
100
+ 'slider',
101
+ 'spinbutton',
102
+ 'switch',
103
+ 'tab',
104
+ 'treeitem',
105
+ ]);
106
+ function processDualModeTree(nodes, refs, interactiveOnly = false, depth = 0) {
107
+ const lines = [];
108
+ for (const node of nodes) {
109
+ const core = node.core;
110
+ if (!core.visible)
111
+ continue;
112
+ const semantics = node.xrayMode?.semantics || {};
113
+ const interaction = node.xrayMode?.interaction || {};
114
+ const design = node.designMode || {};
115
+ const role = (semantics.role || core.className || 'unknown').toLowerCase();
116
+ let name = semantics.name || core.text || core.contentDescription || '';
117
+ name = name.replace(/\s+/g, ' ').trim();
118
+ // Smart Merge: Use child text if name is empty
119
+ if (name === '' && node.children && node.children.length > 0) {
120
+ const textChild = node.children.find((c) => c.core.className === '#text.StaticText');
121
+ if (textChild) {
122
+ name = (textChild.core.text || '').trim();
123
+ }
124
+ }
125
+ const isInteractive = core.clickable ||
126
+ INTERACTIVE_ROLES.has(role) ||
127
+ semantics.intentTags?.includes('interactive');
128
+ if (interactiveOnly && !isInteractive && (!node.children || node.children.length === 0)) {
129
+ continue;
130
+ }
131
+ let line = `${' '.repeat(depth)}- ${role}`;
132
+ if (name)
133
+ line += ` "${name.replace(/"/g, '\\"')}"`;
134
+ if (isInteractive || (name && !['unknown', 'generic', 'group'].includes(role))) {
135
+ const ref = nextRef();
136
+ line += ` [ref=${ref}]`;
137
+ const safeNameDouble = name.replace(/"/g, '\\"');
138
+ let selector = '';
139
+ if (['button', 'link', 'textbox', 'checkbox', 'radio'].includes(role)) {
140
+ if (name)
141
+ selector = `getByRole('${role}', { name: "${safeNameDouble}" })`;
142
+ else
143
+ selector = `getByRole('${role}')`;
144
+ }
145
+ else if (name) {
146
+ selector = `getByText("${safeNameDouble}")`;
147
+ }
148
+ else {
149
+ selector = `locator('.${core.className || role}')`;
150
+ }
151
+ refs[ref] = {
152
+ selector,
153
+ role,
154
+ name,
155
+ bounds: core.bounds,
156
+ nodeId: core.nodeId,
157
+ };
158
+ }
159
+ // --- FULL METADATA OUTPUT ---
160
+ // 1. Core Info (filtered to interesting flags)
161
+ const coreInfo = {};
162
+ if (core.clickable)
163
+ coreInfo.clickable = true;
164
+ if (core.longClickable)
165
+ coreInfo.longClickable = true;
166
+ if (core.scrollable)
167
+ coreInfo.scrollable = true;
168
+ if (core.focusable)
169
+ coreInfo.focusable = true;
170
+ if (core.editable)
171
+ coreInfo.editable = true;
172
+ if (core.checkable)
173
+ coreInfo.checkable = true;
174
+ if (core.checked)
175
+ coreInfo.checked = true;
176
+ if (core.selected)
177
+ coreInfo.selected = true;
178
+ if (core.focused)
179
+ coreInfo.focused = true;
180
+ if (!core.enabled)
181
+ coreInfo.disabled = true;
182
+ // 2. Xray Info (semantics + interaction)
183
+ const xrayInfo = {};
184
+ if (semantics.importanceScore)
185
+ xrayInfo.importance = semantics.importanceScore;
186
+ if (semantics.intentTags?.length)
187
+ xrayInfo.intent = semantics.intentTags;
188
+ if (interaction.availableActions?.length)
189
+ xrayInfo.actions = interaction.availableActions;
190
+ if (interaction.affordanceScore)
191
+ xrayInfo.affordance = interaction.affordanceScore;
192
+ // 3. Design Info (visual + layout + spatial)
193
+ // Only include if non-default/interesting
194
+ const designInfo = {};
195
+ if (design.visual) {
196
+ if (design.visual.backgroundColor)
197
+ designInfo.bg = design.visual.backgroundColor;
198
+ if (design.visual.foregroundColor)
199
+ designInfo.fg = design.visual.foregroundColor;
200
+ if (design.visual.fontSize)
201
+ designInfo.fontSize = design.visual.fontSize;
202
+ if (design.visual.fontWeight && design.visual.fontWeight !== 400)
203
+ designInfo.weight = design.visual.fontWeight;
204
+ if (design.visual.opacity !== 1)
205
+ designInfo.opacity = design.visual.opacity;
206
+ }
207
+ if (design.layout) {
208
+ if (design.layout.zIndex !== 0)
209
+ designInfo.zIndex = design.layout.zIndex;
210
+ if (design.layout.isFixedPosition)
211
+ designInfo.fixed = true;
212
+ if (design.layout.isSticky)
213
+ designInfo.sticky = true;
214
+ }
215
+ if (design.spatial) {
216
+ if (!design.spatial.isAboveFold)
217
+ designInfo.belowFold = true;
218
+ if (design.spatial.visualProminenceScore)
219
+ designInfo.prominence = design.spatial.visualProminenceScore;
220
+ }
221
+ // Append JSON objects to line, indented
222
+ const indent = ' '.repeat(depth + 1);
223
+ if (Object.keys(coreInfo).length > 0) {
224
+ line += `\n${indent}core: ${JSON.stringify(coreInfo)}`;
225
+ }
226
+ if (Object.keys(xrayInfo).length > 0) {
227
+ line += `\n${indent}xray: ${JSON.stringify(xrayInfo)}`;
228
+ }
229
+ if (Object.keys(designInfo).length > 0) {
230
+ line += `\n${indent}design: ${JSON.stringify(designInfo)}`;
231
+ }
232
+ lines.push(line);
233
+ if (node.children) {
234
+ const filteredChildren = node.children.filter((c) => c.core.className !== '#text.StaticText');
235
+ if (filteredChildren.length > 0) {
236
+ const childrenStr = processDualModeTree(filteredChildren, refs, interactiveOnly, depth + 1);
237
+ if (childrenStr)
238
+ lines.push(childrenStr);
239
+ }
240
+ }
241
+ }
242
+ return lines.join('\n');
243
+ }
244
+ function processStandardTree(nodes, refs, interactiveOnly, depth = 0) {
245
+ const lines = [];
246
+ for (const node of nodes) {
247
+ const role = (node.role?.value || 'unknown').toLowerCase();
248
+ let name = node.name?.value || '';
249
+ name = name.replace(/\s+/g, ' ').trim();
250
+ const isInteractive = INTERACTIVE_ROLES.has(role);
251
+ let line = `${' '.repeat(depth)}- ${role}`;
252
+ if (name) {
253
+ line += ` "${name.replace(/"/g, '\\"')}"`;
254
+ }
255
+ if (isInteractive || (name && role !== 'unknown')) {
256
+ const ref = nextRef();
257
+ line += ` [ref=${ref}]`;
258
+ const safeNameDouble = name.replace(/"/g, '\\"');
259
+ let selector = '';
260
+ if (isInteractive) {
261
+ if (name)
262
+ selector = `getByRole('${role}', { name: "${safeNameDouble}" })`;
263
+ else
264
+ selector = `getByRole('${role}')`;
265
+ }
266
+ else if (name) {
267
+ selector = `getByText("${safeNameDouble}")`;
268
+ }
269
+ else {
270
+ selector = `locator('${role}')`;
271
+ }
272
+ refs[ref] = {
273
+ selector: selector,
274
+ role: role,
275
+ name: name,
276
+ };
277
+ }
278
+ lines.push(line);
279
+ if (node.children && node.children.length > 0) {
280
+ const childrenTree = processStandardTree(node.children, refs, interactiveOnly, depth + 1);
281
+ if (childrenTree)
282
+ lines.push(childrenTree);
283
+ }
284
+ }
285
+ return lines.join('\n');
286
+ }
287
+ //# sourceMappingURL=taxtree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taxtree.js","sourceRoot":"","sources":["../src/taxtree.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kritchoff/agent-browser",
3
- "version": "0.9.2",
3
+ "version": "0.9.4",
4
4
  "description": "Headless browser automation CLI for AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -11,6 +11,7 @@
11
11
  "scripts",
12
12
  "skills",
13
13
  "sdk.sh",
14
+ "start.sh",
14
15
  "docker-compose.sdk.yml"
15
16
  ],
16
17
  "bin": {
@@ -31,6 +32,7 @@
31
32
  "fast-reset": "./scripts/fast_reset.sh",
32
33
  "sdk": "./sdk.sh",
33
34
  "release": "npm run version:sync && npm run build && npm run build:all-platforms && npm publish",
35
+ "prepublishOnly": "npm run build",
34
36
  "start": "node dist/daemon.js",
35
37
  "dev": "tsx src/daemon.ts",
36
38
  "typecheck": "tsc --noEmit",
package/start.sh ADDED
@@ -0,0 +1,117 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # Colors
5
+ GREEN='\033[0;32m'
6
+ BLUE='\033[0;34m'
7
+ YELLOW='\033[1;33m'
8
+ RED='\033[0;31m'
9
+ NC='\033[0m' # No Color
10
+
11
+ echo -e "${BLUE}=================================================${NC}"
12
+ echo -e "${BLUE} Agent Browser - Android Environment Setup ${NC}"
13
+ echo -e "${BLUE}=================================================${NC}"
14
+
15
+ SNAPSHOT_PATH=""
16
+ while [[ $# -gt 0 ]]; do
17
+ case $1 in
18
+ --snapshot)
19
+ SNAPSHOT_PATH="$2"
20
+ shift 2
21
+ ;;
22
+ *)
23
+ echo "Unknown option: $1"
24
+ exit 1
25
+ ;;
26
+ esac
27
+ done
28
+
29
+ # 1. Pre-flight Checks
30
+ echo -e "\n${YELLOW}[1/4] Checking System Requirements...${NC}"
31
+
32
+ if ! command -v docker &> /dev/null; then
33
+ echo -e "${RED}Error: Docker is not installed.${NC}"
34
+ exit 1
35
+ fi
36
+
37
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
38
+ if [ -e /dev/kvm ]; then
39
+ echo -e "${GREEN}✓ KVM Acceleration detected (/dev/kvm)${NC}"
40
+ else
41
+ echo -e "${YELLOW}⚠ Warning: No KVM detected. Emulator will be slow.${NC}"
42
+ fi
43
+ fi
44
+
45
+ # 2. Start Services
46
+ echo -e "\n${YELLOW}[2/4] Starting Docker Stack...${NC}"
47
+ echo " (First run may take a few minutes to download images)"
48
+
49
+ docker compose -f "${COMPOSE_FILE:-docker-compose.prod.yml}" up -d --build --remove-orphans > /dev/null 2>&1
50
+
51
+ # Find actual container names
52
+ ANDROID_CONTAINER=$(docker compose -f "${COMPOSE_FILE:-docker-compose.prod.yml}" ps -q android-service)
53
+ AGENT_CONTAINER=$(docker compose -f "${COMPOSE_FILE:-docker-compose.prod.yml}" ps -q agent-service)
54
+
55
+ # 2b. Import Snapshot (if requested)
56
+ if [ -n "$SNAPSHOT_PATH" ]; then
57
+ echo -e "\n${YELLOW}[2.5/4] Importing Snapshot: $SNAPSHOT_PATH...${NC}"
58
+
59
+ # Wait for container to be responsive
60
+ echo -n " Waiting for container to be ready for import... "
61
+ until docker exec "$ANDROID_CONTAINER" echo "ready" &>/dev/null; do
62
+ sleep 1
63
+ done
64
+ echo -e "${GREEN}OK${NC}"
65
+
66
+ # Import
67
+ if ./scripts/snapshot_manager.sh import "$SNAPSHOT_PATH" "w8rl_imported"; then
68
+ echo -e "${GREEN} Snapshot imported successfully.${NC}"
69
+
70
+ # Configure emulator to load this snapshot
71
+ # We set the env var in the container for the next boot
72
+ # (This assumes the entrypoint script respects EMULATOR_SNAPSHOT_NAME)
73
+ # For now, we'll rely on the default behavior or standard AVD loading
74
+
75
+ echo " Restarting Android service to load snapshot..."
76
+ docker compose -f "${COMPOSE_FILE:-docker-compose.prod.yml}" restart android-service
77
+
78
+ # Update container ID after restart
79
+ ANDROID_CONTAINER=$(docker compose -f "${COMPOSE_FILE:-docker-compose.prod.yml}" ps -q android-service)
80
+ else
81
+ echo -e "${RED}Error: Failed to import snapshot.${NC}"
82
+ exit 1
83
+ fi
84
+ fi
85
+
86
+ # 3. Wait for Readiness
87
+ echo -e "\n${YELLOW}[3/4] Waiting for Initialization...${NC}"
88
+
89
+ wait_for_log() {
90
+ local container=$1
91
+ local pattern=$2
92
+ local label=$3
93
+
94
+ echo -n " Waiting for $label... "
95
+ until docker logs "$container" 2>&1 | grep -q "$pattern"; do
96
+ sleep 2
97
+ done
98
+ echo -e "${GREEN}Done!${NC}"
99
+ }
100
+
101
+ wait_for_log "$ANDROID_CONTAINER" "Emulator boot complete" "Android Emulator Boot"
102
+ wait_for_log "$ANDROID_CONTAINER" "APK installation complete" "WootzApp Installation"
103
+ wait_for_log "$ANDROID_CONTAINER" "CDP Bridge ready" "CDP Bridge"
104
+ wait_for_log "$AGENT_CONTAINER" "Ready on port 3000" "Agent Daemon Connection"
105
+
106
+ # 4. Success
107
+ echo -e "\n${GREEN}[4/4] Environment Ready!${NC}"
108
+ echo -e "${BLUE}=================================================${NC}"
109
+ echo -e "You can now control the Android browser."
110
+ echo -e ""
111
+ echo -e "Try these commands:"
112
+ echo -e " ${GREEN}./agent open https://google.com${NC}"
113
+ echo -e " ${GREEN}./agent snapshot${NC}"
114
+ echo -e " ${GREEN}./agent click @e1${NC}"
115
+ echo -e ""
116
+ echo -e "See COMMANDS.md for full reference."
117
+ echo -e "${BLUE}=================================================${NC}"