@agimon-ai/browse-tool 0.2.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.
Files changed (38) hide show
  1. package/LICENSE +52 -0
  2. package/README.md +375 -0
  3. package/dist/cli.cjs +674 -0
  4. package/dist/cli.d.cts +1 -0
  5. package/dist/cli.d.mts +2 -0
  6. package/dist/cli.mjs +434 -0
  7. package/dist/cli.mjs.map +1 -0
  8. package/dist/extension/background.js +7248 -0
  9. package/dist/extension/background.js.map +1 -0
  10. package/dist/extension/content.js +446 -0
  11. package/dist/extension/content.js.map +1 -0
  12. package/dist/extension/manifest.json +36 -0
  13. package/dist/extension/offscreen.html +9 -0
  14. package/dist/extension/offscreen.js +137 -0
  15. package/dist/extension/offscreen.js.map +1 -0
  16. package/dist/extension/popup.html +195 -0
  17. package/dist/extension/popup.js +132 -0
  18. package/dist/extension/popup.js.map +1 -0
  19. package/dist/index.cjs +1 -0
  20. package/dist/index.d.cts +309 -0
  21. package/dist/index.d.cts.map +1 -0
  22. package/dist/index.d.mts +310 -0
  23. package/dist/index.d.mts.map +1 -0
  24. package/dist/index.mjs +2 -0
  25. package/dist/index.mjs.map +1 -0
  26. package/dist/playwright-test-BwI7HgW7.mjs +253 -0
  27. package/dist/playwright-test-BwI7HgW7.mjs.map +1 -0
  28. package/dist/playwright-test-CnsuVfC9.cjs +252 -0
  29. package/dist/stdio-BP3yiSxK.mjs +9 -0
  30. package/dist/stdio-BP3yiSxK.mjs.map +1 -0
  31. package/dist/stdio-ynNFGBY4.cjs +9 -0
  32. package/dist/stubs/playwright-test.cjs +1 -0
  33. package/dist/stubs/playwright-test.d.cts +111 -0
  34. package/dist/stubs/playwright-test.d.cts.map +1 -0
  35. package/dist/stubs/playwright-test.d.mts +111 -0
  36. package/dist/stubs/playwright-test.d.mts.map +1 -0
  37. package/dist/stubs/playwright-test.mjs +1 -0
  38. package/package.json +77 -0
@@ -0,0 +1,446 @@
1
+ const uidToElement = /* @__PURE__ */ new Map();
2
+ let uidCounter = 0;
3
+ function assignUid(element) {
4
+ const uid = `e${++uidCounter}`;
5
+ uidToElement.set(uid, new WeakRef(element));
6
+ return uid;
7
+ }
8
+ function getElementByUid(uid) {
9
+ const ref = uidToElement.get(uid);
10
+ return ref?.deref() || null;
11
+ }
12
+ function clearUidMap() {
13
+ uidToElement.clear();
14
+ uidCounter = 0;
15
+ }
16
+ async function locateElement(locator) {
17
+ if (locator.uid) {
18
+ const element = getElementByUid(locator.uid);
19
+ if (element) return element;
20
+ }
21
+ if (locator.selector) {
22
+ const element = document.querySelector(locator.selector);
23
+ if (element) return element;
24
+ }
25
+ if (locator.xpath) {
26
+ const result = document.evaluate(locator.xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
27
+ if (result.singleNodeValue instanceof Element) {
28
+ return result.singleNodeValue;
29
+ }
30
+ }
31
+ if (locator.text) {
32
+ const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, {
33
+ acceptNode(node2) {
34
+ const el = node2;
35
+ if (el.textContent?.includes(locator.text)) {
36
+ return NodeFilter.FILTER_ACCEPT;
37
+ }
38
+ return NodeFilter.FILTER_SKIP;
39
+ }
40
+ });
41
+ const node = walker.nextNode();
42
+ if (node instanceof Element) {
43
+ return node;
44
+ }
45
+ }
46
+ if (locator.role) {
47
+ const element = document.querySelector(`[role="${locator.role}"]`);
48
+ if (element) return element;
49
+ }
50
+ return null;
51
+ }
52
+
53
+ function buildAccessibilityTree() {
54
+ clearUidMap();
55
+ const root = buildNode(document.body);
56
+ return root || { uid: "root", role: "none", name: "Empty page" };
57
+ }
58
+ function buildNode(element, depth) {
59
+ const style = getComputedStyle(element);
60
+ if (style.display === "none" || style.visibility === "hidden") {
61
+ return null;
62
+ }
63
+ const role = getRole(element);
64
+ const name = getAccessibleName(element);
65
+ const uid = assignUid(element);
66
+ const children = [];
67
+ for (const child of element.children) {
68
+ const childNode = buildNode(child);
69
+ if (childNode) {
70
+ children.push(childNode);
71
+ }
72
+ }
73
+ if (role === "none" && !name && children.length === 1) {
74
+ return children[0];
75
+ }
76
+ const node = {
77
+ uid,
78
+ role
79
+ };
80
+ if (name) node.name = name;
81
+ if (children.length > 0) node.children = children;
82
+ addStateProperties(element, node);
83
+ return node;
84
+ }
85
+ function getRole(element) {
86
+ const ariaRole = element.getAttribute("role");
87
+ if (ariaRole) return ariaRole;
88
+ const tagName = element.tagName.toLowerCase();
89
+ const roleMap = {
90
+ a: element.hasAttribute("href") ? "link" : "none",
91
+ article: "article",
92
+ aside: "complementary",
93
+ button: "button",
94
+ footer: "contentinfo",
95
+ form: "form",
96
+ h1: "heading",
97
+ h2: "heading",
98
+ h3: "heading",
99
+ h4: "heading",
100
+ h5: "heading",
101
+ h6: "heading",
102
+ header: "banner",
103
+ img: "img",
104
+ input: getInputRole(element),
105
+ li: "listitem",
106
+ main: "main",
107
+ nav: "navigation",
108
+ ol: "list",
109
+ option: "option",
110
+ progress: "progressbar",
111
+ section: element.hasAttribute("aria-label") ? "region" : "none",
112
+ select: "combobox",
113
+ table: "table",
114
+ tbody: "rowgroup",
115
+ td: "cell",
116
+ textarea: "textbox",
117
+ th: "columnheader",
118
+ tr: "row",
119
+ ul: "list"
120
+ };
121
+ return roleMap[tagName] || "none";
122
+ }
123
+ function getInputRole(input) {
124
+ const type = (input.type || "text").toLowerCase();
125
+ const inputRoles = {
126
+ button: "button",
127
+ checkbox: "checkbox",
128
+ email: "textbox",
129
+ number: "spinbutton",
130
+ password: "textbox",
131
+ radio: "radio",
132
+ range: "slider",
133
+ search: "searchbox",
134
+ submit: "button",
135
+ tel: "textbox",
136
+ text: "textbox",
137
+ url: "textbox"
138
+ };
139
+ return inputRoles[type] || "textbox";
140
+ }
141
+ function getAccessibleName(element) {
142
+ const ariaLabel = element.getAttribute("aria-label");
143
+ if (ariaLabel) return ariaLabel;
144
+ const labelledBy = element.getAttribute("aria-labelledby");
145
+ if (labelledBy) {
146
+ const labels = labelledBy.split(" ").map((id) => document.getElementById(id)?.textContent).filter(Boolean).join(" ");
147
+ if (labels) return labels;
148
+ }
149
+ if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {
150
+ const id = element.id;
151
+ if (id) {
152
+ const label = document.querySelector(`label[for="${id}"]`);
153
+ if (label?.textContent) return label.textContent.trim();
154
+ }
155
+ }
156
+ const tagName = element.tagName.toLowerCase();
157
+ if (["button", "a", "h1", "h2", "h3", "h4", "h5", "h6", "label", "option"].includes(tagName)) {
158
+ const text = element.textContent?.trim();
159
+ if (text && text.length < 100) return text;
160
+ }
161
+ if (element instanceof HTMLImageElement && element.alt) {
162
+ return element.alt;
163
+ }
164
+ if (element instanceof HTMLInputElement && element.placeholder) {
165
+ return element.placeholder;
166
+ }
167
+ return void 0;
168
+ }
169
+ function addStateProperties(element, node) {
170
+ if (document.activeElement === element) {
171
+ node.focused = true;
172
+ }
173
+ if (element.disabled) {
174
+ node.disabled = true;
175
+ }
176
+ if (element instanceof HTMLInputElement) {
177
+ if (element.type === "checkbox" || element.type === "radio") {
178
+ node.checked = element.indeterminate ? "mixed" : element.checked;
179
+ }
180
+ }
181
+ if (element instanceof HTMLOptionElement) {
182
+ node.selected = element.selected;
183
+ }
184
+ const ariaExpanded = element.getAttribute("aria-expanded");
185
+ if (ariaExpanded) {
186
+ node.expanded = ariaExpanded === "true";
187
+ }
188
+ const headingMatch = element.tagName.match(/^H([1-6])$/);
189
+ if (headingMatch) {
190
+ node.level = Number.parseInt(headingMatch[1], 10);
191
+ }
192
+ const ariaPressed = element.getAttribute("aria-pressed");
193
+ if (ariaPressed) {
194
+ node.pressed = ariaPressed === "mixed" ? "mixed" : ariaPressed === "true";
195
+ }
196
+ }
197
+
198
+ const ContentAction = {
199
+ CLICK: "click",
200
+ FILL: "fill",
201
+ TYPE: "type",
202
+ GET_SNAPSHOT: "getSnapshot",
203
+ EVALUATE_SCRIPT: "evaluateScript",
204
+ GET_ELEMENT_INFO: "getElementInfo",
205
+ HOVER: "hover",
206
+ SELECT: "select",
207
+ DRAG: "drag",
208
+ PRESS_KEY: "pressKey",
209
+ WAIT_FOR: "waitFor"
210
+ };
211
+ const VALID_ACTIONS = new Set(Object.values(ContentAction));
212
+ function validateMessage(message) {
213
+ if (!message || typeof message !== "object") return null;
214
+ const msg = message;
215
+ if (typeof msg.action !== "string" || !VALID_ACTIONS.has(msg.action)) return null;
216
+ if (msg.params !== void 0 && (typeof msg.params !== "object" || msg.params === null)) return null;
217
+ return {
218
+ action: msg.action,
219
+ params: msg.params || {}
220
+ };
221
+ }
222
+ chrome.runtime.onMessage.addListener(
223
+ (message, _sender, sendResponse) => {
224
+ const validated = validateMessage(message);
225
+ if (!validated) {
226
+ sendResponse({
227
+ success: false,
228
+ error: "Invalid message format: missing or invalid action"
229
+ });
230
+ return true;
231
+ }
232
+ handleContentAction(validated).then((result) => sendResponse({ success: true, result })).catch((error) => sendResponse({ success: false, error: error.message }));
233
+ return true;
234
+ }
235
+ );
236
+ async function handleContentAction(message) {
237
+ const { action, params } = message;
238
+ switch (action) {
239
+ case ContentAction.CLICK:
240
+ return handleClick(params);
241
+ case ContentAction.FILL:
242
+ return handleFill(params);
243
+ case ContentAction.TYPE:
244
+ return handleType(params);
245
+ case ContentAction.GET_SNAPSHOT:
246
+ return buildAccessibilityTree();
247
+ case ContentAction.EVALUATE_SCRIPT:
248
+ return handleEvaluateScript(params);
249
+ case ContentAction.GET_ELEMENT_INFO:
250
+ return handleGetElementInfo(params);
251
+ case ContentAction.HOVER:
252
+ return handleHover(params);
253
+ case ContentAction.SELECT:
254
+ return handleSelect(params);
255
+ case ContentAction.DRAG:
256
+ return handleDrag(params);
257
+ case ContentAction.PRESS_KEY:
258
+ return handlePressKey(params);
259
+ case ContentAction.WAIT_FOR:
260
+ return handleWaitFor(params);
261
+ }
262
+ }
263
+ async function handleClick(params) {
264
+ const locator = params;
265
+ const element = await locateElement(locator);
266
+ if (!element) {
267
+ throw new Error("Element not found");
268
+ }
269
+ element.scrollIntoView({ behavior: "smooth", block: "center" });
270
+ const rect = element.getBoundingClientRect();
271
+ const x = rect.left + rect.width / 2;
272
+ const y = rect.top + rect.height / 2;
273
+ element.dispatchEvent(new MouseEvent("mousedown", { bubbles: true, clientX: x, clientY: y }));
274
+ element.dispatchEvent(new MouseEvent("mouseup", { bubbles: true, clientX: x, clientY: y }));
275
+ element.dispatchEvent(new MouseEvent("click", { bubbles: true, clientX: x, clientY: y }));
276
+ }
277
+ async function handleFill(params) {
278
+ const locator = params;
279
+ const value = params.value;
280
+ const element = await locateElement(locator);
281
+ if (!element) {
282
+ throw new Error("Element not found");
283
+ }
284
+ if (!(element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement)) {
285
+ throw new Error("Element is not an input or textarea");
286
+ }
287
+ element.focus();
288
+ element.value = "";
289
+ element.value = value;
290
+ element.dispatchEvent(new Event("input", { bubbles: true }));
291
+ element.dispatchEvent(new Event("change", { bubbles: true }));
292
+ }
293
+ async function handleType(params) {
294
+ const locator = params;
295
+ const text = params.text;
296
+ const element = await locateElement(locator);
297
+ if (!element) {
298
+ throw new Error("Element not found");
299
+ }
300
+ if (element instanceof HTMLElement) {
301
+ element.focus();
302
+ }
303
+ for (const char of text) {
304
+ element.dispatchEvent(new KeyboardEvent("keydown", { key: char, bubbles: true }));
305
+ element.dispatchEvent(new KeyboardEvent("keypress", { key: char, bubbles: true }));
306
+ if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {
307
+ element.value += char;
308
+ element.dispatchEvent(new Event("input", { bubbles: true }));
309
+ }
310
+ element.dispatchEvent(new KeyboardEvent("keyup", { key: char, bubbles: true }));
311
+ }
312
+ }
313
+ async function handleEvaluateScript(params) {
314
+ const script = params.script;
315
+ const fn = new Function(script);
316
+ return fn();
317
+ }
318
+ async function handleGetElementInfo(params) {
319
+ const locator = params;
320
+ const element = await locateElement(locator);
321
+ if (!element) {
322
+ return null;
323
+ }
324
+ const rect = element.getBoundingClientRect();
325
+ return {
326
+ tagName: element.tagName.toLowerCase(),
327
+ id: element.id,
328
+ className: element.className,
329
+ textContent: element.textContent?.substring(0, 100),
330
+ rect: {
331
+ x: rect.x,
332
+ y: rect.y,
333
+ width: rect.width,
334
+ height: rect.height
335
+ }
336
+ };
337
+ }
338
+ async function handleHover(params) {
339
+ const locator = params;
340
+ const element = await locateElement(locator);
341
+ if (!element) {
342
+ throw new Error("Element not found");
343
+ }
344
+ element.scrollIntoView({ behavior: "smooth", block: "center" });
345
+ const rect = element.getBoundingClientRect();
346
+ const x = rect.left + rect.width / 2;
347
+ const y = rect.top + rect.height / 2;
348
+ element.dispatchEvent(new MouseEvent("mouseenter", { bubbles: true, clientX: x, clientY: y }));
349
+ element.dispatchEvent(new MouseEvent("mouseover", { bubbles: true, clientX: x, clientY: y }));
350
+ element.dispatchEvent(new MouseEvent("mousemove", { bubbles: true, clientX: x, clientY: y }));
351
+ }
352
+ async function handleSelect(params) {
353
+ const locator = params;
354
+ const value = params.value;
355
+ const element = await locateElement(locator);
356
+ if (!element) {
357
+ throw new Error("Element not found");
358
+ }
359
+ if (!(element instanceof HTMLSelectElement)) {
360
+ throw new Error("Element is not a select element");
361
+ }
362
+ const values = Array.isArray(value) ? value : [value];
363
+ for (const option of element.options) {
364
+ option.selected = values.includes(option.value) || values.includes(option.text);
365
+ }
366
+ element.dispatchEvent(new Event("input", { bubbles: true }));
367
+ element.dispatchEvent(new Event("change", { bubbles: true }));
368
+ }
369
+ async function handleDrag(params) {
370
+ const sourceLocator = params.source;
371
+ const targetLocator = params.target;
372
+ const sourceElement = await locateElement(sourceLocator);
373
+ const targetElement = await locateElement(targetLocator);
374
+ if (!sourceElement) {
375
+ throw new Error("Source element not found");
376
+ }
377
+ if (!targetElement) {
378
+ throw new Error("Target element not found");
379
+ }
380
+ const sourceRect = sourceElement.getBoundingClientRect();
381
+ const targetRect = targetElement.getBoundingClientRect();
382
+ const sourceX = sourceRect.left + sourceRect.width / 2;
383
+ const sourceY = sourceRect.top + sourceRect.height / 2;
384
+ const targetX = targetRect.left + targetRect.width / 2;
385
+ const targetY = targetRect.top + targetRect.height / 2;
386
+ sourceElement.dispatchEvent(new MouseEvent("mousedown", { bubbles: true, clientX: sourceX, clientY: sourceY }));
387
+ sourceElement.dispatchEvent(new MouseEvent("dragstart", { bubbles: true, clientX: sourceX, clientY: sourceY }));
388
+ targetElement.dispatchEvent(new MouseEvent("dragenter", { bubbles: true, clientX: targetX, clientY: targetY }));
389
+ targetElement.dispatchEvent(new MouseEvent("dragover", { bubbles: true, clientX: targetX, clientY: targetY }));
390
+ targetElement.dispatchEvent(new MouseEvent("drop", { bubbles: true, clientX: targetX, clientY: targetY }));
391
+ sourceElement.dispatchEvent(new MouseEvent("dragend", { bubbles: true, clientX: targetX, clientY: targetY }));
392
+ targetElement.dispatchEvent(new MouseEvent("mouseup", { bubbles: true, clientX: targetX, clientY: targetY }));
393
+ }
394
+ async function handlePressKey(params) {
395
+ const key = params.key;
396
+ const modifiers = params.modifiers;
397
+ const eventInit = {
398
+ key,
399
+ bubbles: true,
400
+ ctrlKey: modifiers?.includes("Control") || modifiers?.includes("Ctrl"),
401
+ shiftKey: modifiers?.includes("Shift"),
402
+ altKey: modifiers?.includes("Alt"),
403
+ metaKey: modifiers?.includes("Meta") || modifiers?.includes("Command")
404
+ };
405
+ const activeElement = document.activeElement || document.body;
406
+ activeElement.dispatchEvent(new KeyboardEvent("keydown", eventInit));
407
+ activeElement.dispatchEvent(new KeyboardEvent("keypress", eventInit));
408
+ activeElement.dispatchEvent(new KeyboardEvent("keyup", eventInit));
409
+ }
410
+ async function handleWaitFor(params) {
411
+ const selector = params.selector;
412
+ const text = params.text;
413
+ const state = params.state || "visible";
414
+ const timeout = params.timeout || 3e4;
415
+ const startTime = Date.now();
416
+ while (Date.now() - startTime < timeout) {
417
+ if (selector) {
418
+ const element = document.querySelector(selector);
419
+ if (state === "visible" && element && isVisible(element)) {
420
+ return;
421
+ }
422
+ if (state === "hidden" && (!element || !isVisible(element))) {
423
+ return;
424
+ }
425
+ if (state === "attached" && element) {
426
+ return;
427
+ }
428
+ if (state === "detached" && !element) {
429
+ return;
430
+ }
431
+ }
432
+ if (text) {
433
+ const found = document.body.textContent?.includes(text);
434
+ if (found) {
435
+ return;
436
+ }
437
+ }
438
+ await new Promise((resolve) => setTimeout(resolve, 100));
439
+ }
440
+ throw new Error(`Wait condition not met within ${timeout}ms`);
441
+ }
442
+ function isVisible(element) {
443
+ const style = window.getComputedStyle(element);
444
+ return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0";
445
+ }
446
+ //# sourceMappingURL=content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.js","sources":["../../src/extension/content/element-locator.ts","../../src/extension/content/accessibility-tree.ts","../../src/extension/content/index.ts"],"sourcesContent":["/**\n * Element Locator - Strategies for finding elements in the DOM\n *\n * Supports multiple location strategies:\n * - CSS selector\n * - XPath\n * - Text content\n * - Accessibility UID (from snapshot)\n */\n\nexport interface ElementLocator {\n selector?: string;\n xpath?: string;\n text?: string;\n uid?: string;\n role?: string;\n}\n\nconst uidToElement = new Map<string, WeakRef<Element>>();\nlet uidCounter = 0;\n\nexport function assignUid(element: Element): string {\n const uid = `e${++uidCounter}`;\n uidToElement.set(uid, new WeakRef(element));\n return uid;\n}\n\nexport function getElementByUid(uid: string): Element | null {\n const ref = uidToElement.get(uid);\n return ref?.deref() || null;\n}\n\nexport function clearUidMap(): void {\n uidToElement.clear();\n uidCounter = 0;\n}\n\nexport async function locateElement(locator: ElementLocator): Promise<Element | null> {\n // Try UID first (most precise)\n if (locator.uid) {\n const element = getElementByUid(locator.uid);\n if (element) return element;\n }\n\n // Try CSS selector\n if (locator.selector) {\n const element = document.querySelector(locator.selector);\n if (element) return element;\n }\n\n // Try XPath\n if (locator.xpath) {\n const result = document.evaluate(locator.xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);\n if (result.singleNodeValue instanceof Element) {\n return result.singleNodeValue;\n }\n }\n\n // Try text content\n if (locator.text) {\n const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, {\n acceptNode(node) {\n const el = node as Element;\n if (el.textContent?.includes(locator.text!)) {\n return NodeFilter.FILTER_ACCEPT;\n }\n return NodeFilter.FILTER_SKIP;\n },\n });\n const node = walker.nextNode();\n if (node instanceof Element) {\n return node;\n }\n }\n\n // Try role-based (ARIA)\n if (locator.role) {\n const element = document.querySelector(`[role=\"${locator.role}\"]`);\n if (element) return element;\n }\n\n return null;\n}\n","/**\n * Accessibility Tree Builder\n *\n * Generates an accessibility snapshot of the page,\n * similar to Playwright's accessibility tree format.\n */\n\nimport { assignUid, clearUidMap } from './element-locator.js';\n\nexport interface AccessibilityNode {\n uid: string;\n role: string;\n name?: string;\n value?: string;\n description?: string;\n children?: AccessibilityNode[];\n focused?: boolean;\n disabled?: boolean;\n checked?: boolean | 'mixed';\n selected?: boolean;\n expanded?: boolean;\n level?: number;\n pressed?: boolean | 'mixed';\n}\n\nexport function buildAccessibilityTree(): AccessibilityNode {\n // Clear previous UID assignments\n clearUidMap();\n\n const root = buildNode(document.body, 0);\n return root || { uid: 'root', role: 'none', name: 'Empty page' };\n}\n\nfunction buildNode(element: Element, depth: number): AccessibilityNode | null {\n // Skip hidden elements\n const style = getComputedStyle(element);\n if (style.display === 'none' || style.visibility === 'hidden') {\n return null;\n }\n\n const role = getRole(element);\n const name = getAccessibleName(element);\n const uid = assignUid(element);\n\n // Build children\n const children: AccessibilityNode[] = [];\n for (const child of element.children) {\n const childNode = buildNode(child, depth + 1);\n if (childNode) {\n children.push(childNode);\n }\n }\n\n // Skip non-semantic containers with no accessible name\n if (role === 'none' && !name && children.length === 1) {\n return children[0];\n }\n\n const node: AccessibilityNode = {\n uid,\n role,\n };\n\n if (name) node.name = name;\n if (children.length > 0) node.children = children;\n\n // Add state properties\n addStateProperties(element, node);\n\n return node;\n}\n\nfunction getRole(element: Element): string {\n // Explicit ARIA role\n const ariaRole = element.getAttribute('role');\n if (ariaRole) return ariaRole;\n\n // Implicit roles based on tag name\n const tagName = element.tagName.toLowerCase();\n const roleMap: Record<string, string> = {\n a: element.hasAttribute('href') ? 'link' : 'none',\n article: 'article',\n aside: 'complementary',\n button: 'button',\n footer: 'contentinfo',\n form: 'form',\n h1: 'heading',\n h2: 'heading',\n h3: 'heading',\n h4: 'heading',\n h5: 'heading',\n h6: 'heading',\n header: 'banner',\n img: 'img',\n input: getInputRole(element as HTMLInputElement),\n li: 'listitem',\n main: 'main',\n nav: 'navigation',\n ol: 'list',\n option: 'option',\n progress: 'progressbar',\n section: element.hasAttribute('aria-label') ? 'region' : 'none',\n select: 'combobox',\n table: 'table',\n tbody: 'rowgroup',\n td: 'cell',\n textarea: 'textbox',\n th: 'columnheader',\n tr: 'row',\n ul: 'list',\n };\n\n return roleMap[tagName] || 'none';\n}\n\nfunction getInputRole(input: HTMLInputElement): string {\n const type = (input.type || 'text').toLowerCase();\n const inputRoles: Record<string, string> = {\n button: 'button',\n checkbox: 'checkbox',\n email: 'textbox',\n number: 'spinbutton',\n password: 'textbox',\n radio: 'radio',\n range: 'slider',\n search: 'searchbox',\n submit: 'button',\n tel: 'textbox',\n text: 'textbox',\n url: 'textbox',\n };\n return inputRoles[type] || 'textbox';\n}\n\nfunction getAccessibleName(element: Element): string | undefined {\n // aria-label\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel) return ariaLabel;\n\n // aria-labelledby\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy) {\n const labels = labelledBy\n .split(' ')\n .map((id) => document.getElementById(id)?.textContent)\n .filter(Boolean)\n .join(' ');\n if (labels) return labels;\n }\n\n // For inputs, check associated label\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {\n const id = element.id;\n if (id) {\n const label = document.querySelector(`label[for=\"${id}\"]`);\n if (label?.textContent) return label.textContent.trim();\n }\n }\n\n // Text content for certain elements\n const tagName = element.tagName.toLowerCase();\n if (['button', 'a', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'label', 'option'].includes(tagName)) {\n const text = element.textContent?.trim();\n if (text && text.length < 100) return text;\n }\n\n // Alt text for images\n if (element instanceof HTMLImageElement && element.alt) {\n return element.alt;\n }\n\n // Placeholder for inputs\n if (element instanceof HTMLInputElement && element.placeholder) {\n return element.placeholder;\n }\n\n return undefined;\n}\n\nfunction addStateProperties(element: Element, node: AccessibilityNode): void {\n // Focus state\n if (document.activeElement === element) {\n node.focused = true;\n }\n\n // Disabled state\n if ((element as HTMLInputElement).disabled) {\n node.disabled = true;\n }\n\n // Checked state\n if (element instanceof HTMLInputElement) {\n if (element.type === 'checkbox' || element.type === 'radio') {\n node.checked = element.indeterminate ? 'mixed' : element.checked;\n }\n }\n\n // Selected state\n if (element instanceof HTMLOptionElement) {\n node.selected = element.selected;\n }\n\n // Expanded state\n const ariaExpanded = element.getAttribute('aria-expanded');\n if (ariaExpanded) {\n node.expanded = ariaExpanded === 'true';\n }\n\n // Heading level\n const headingMatch = element.tagName.match(/^H([1-6])$/);\n if (headingMatch) {\n node.level = Number.parseInt(headingMatch[1], 10);\n }\n\n // Pressed state\n const ariaPressed = element.getAttribute('aria-pressed');\n if (ariaPressed) {\n node.pressed = ariaPressed === 'mixed' ? 'mixed' : ariaPressed === 'true';\n }\n}\n","/**\n * Content Script - DOM Interaction Layer\n *\n * Runs in the context of web pages and provides DOM manipulation\n * capabilities for browser automation tools.\n *\n * NOTE: This file must be self-contained (no imports from shared modules)\n * because Chrome content scripts cannot use ES modules.\n */\n\nimport { buildAccessibilityTree } from './accessibility-tree.js';\nimport { type ElementLocator, locateElement } from './element-locator.js';\n\n/**\n * Content action constants - inlined to avoid shared module imports\n */\nconst ContentAction = {\n CLICK: 'click',\n FILL: 'fill',\n TYPE: 'type',\n GET_SNAPSHOT: 'getSnapshot',\n EVALUATE_SCRIPT: 'evaluateScript',\n GET_ELEMENT_INFO: 'getElementInfo',\n HOVER: 'hover',\n SELECT: 'select',\n DRAG: 'drag',\n PRESS_KEY: 'pressKey',\n WAIT_FOR: 'waitFor',\n} as const;\n\ntype ContentActionType = (typeof ContentAction)[keyof typeof ContentAction];\n\ninterface ContentMessage {\n action: ContentActionType;\n params: Record<string, unknown>;\n}\n\ninterface ContentResponse {\n success: boolean;\n result?: unknown;\n error?: string;\n}\n\nconst VALID_ACTIONS = new Set(Object.values(ContentAction));\n\nfunction validateMessage(message: unknown): ContentMessage | null {\n if (!message || typeof message !== 'object') return null;\n const msg = message as Record<string, unknown>;\n if (typeof msg.action !== 'string' || !VALID_ACTIONS.has(msg.action as ContentActionType)) return null;\n if (msg.params !== undefined && (typeof msg.params !== 'object' || msg.params === null)) return null;\n return {\n action: msg.action as ContentActionType,\n params: (msg.params as Record<string, unknown>) || {},\n };\n}\n\nchrome.runtime.onMessage.addListener(\n (message: unknown, _sender: chrome.runtime.MessageSender, sendResponse: (response: ContentResponse) => void) => {\n const validated = validateMessage(message);\n if (!validated) {\n sendResponse({\n success: false,\n error: 'Invalid message format: missing or invalid action',\n });\n return true;\n }\n\n handleContentAction(validated)\n .then((result) => sendResponse({ success: true, result }))\n .catch((error: Error) => sendResponse({ success: false, error: error.message }));\n return true; // Async response\n },\n);\n\nasync function handleContentAction(message: ContentMessage): Promise<unknown> {\n const { action, params } = message;\n\n switch (action) {\n case ContentAction.CLICK:\n return handleClick(params);\n case ContentAction.FILL:\n return handleFill(params);\n case ContentAction.TYPE:\n return handleType(params);\n case ContentAction.GET_SNAPSHOT:\n return buildAccessibilityTree();\n case ContentAction.EVALUATE_SCRIPT:\n return handleEvaluateScript(params);\n case ContentAction.GET_ELEMENT_INFO:\n return handleGetElementInfo(params);\n case ContentAction.HOVER:\n return handleHover(params);\n case ContentAction.SELECT:\n return handleSelect(params);\n case ContentAction.DRAG:\n return handleDrag(params);\n case ContentAction.PRESS_KEY:\n return handlePressKey(params);\n case ContentAction.WAIT_FOR:\n return handleWaitFor(params);\n }\n}\n\nasync function handleClick(params: Record<string, unknown>): Promise<void> {\n const locator = params as ElementLocator;\n const element = await locateElement(locator);\n\n if (!element) {\n throw new Error('Element not found');\n }\n\n // Scroll element into view\n element.scrollIntoView({ behavior: 'smooth', block: 'center' });\n\n // Simulate mouse events for realistic click\n const rect = element.getBoundingClientRect();\n const x = rect.left + rect.width / 2;\n const y = rect.top + rect.height / 2;\n\n element.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, clientX: x, clientY: y }));\n element.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, clientX: x, clientY: y }));\n element.dispatchEvent(new MouseEvent('click', { bubbles: true, clientX: x, clientY: y }));\n}\n\nasync function handleFill(params: Record<string, unknown>): Promise<void> {\n const locator = params as ElementLocator;\n const value = params.value as string;\n const element = await locateElement(locator);\n\n if (!element) {\n throw new Error('Element not found');\n }\n\n if (!(element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement)) {\n throw new Error('Element is not an input or textarea');\n }\n\n // Focus and clear\n element.focus();\n element.value = '';\n\n // Set value and dispatch events\n element.value = value;\n element.dispatchEvent(new Event('input', { bubbles: true }));\n element.dispatchEvent(new Event('change', { bubbles: true }));\n}\n\nasync function handleType(params: Record<string, unknown>): Promise<void> {\n const locator = params as ElementLocator;\n const text = params.text as string;\n const element = await locateElement(locator);\n\n if (!element) {\n throw new Error('Element not found');\n }\n\n if (element instanceof HTMLElement) {\n element.focus();\n }\n\n // Type character by character\n for (const char of text) {\n element.dispatchEvent(new KeyboardEvent('keydown', { key: char, bubbles: true }));\n element.dispatchEvent(new KeyboardEvent('keypress', { key: char, bubbles: true }));\n\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {\n element.value += char;\n element.dispatchEvent(new Event('input', { bubbles: true }));\n }\n\n element.dispatchEvent(new KeyboardEvent('keyup', { key: char, bubbles: true }));\n }\n}\n\nasync function handleEvaluateScript(params: Record<string, unknown>): Promise<unknown> {\n const script = params.script as string;\n // Use Function constructor to evaluate script in page context\n const fn = new Function(script);\n return fn();\n}\n\nasync function handleGetElementInfo(params: Record<string, unknown>): Promise<unknown> {\n const locator = params as ElementLocator;\n const element = await locateElement(locator);\n\n if (!element) {\n return null;\n }\n\n const rect = element.getBoundingClientRect();\n return {\n tagName: element.tagName.toLowerCase(),\n id: element.id,\n className: element.className,\n textContent: element.textContent?.substring(0, 100),\n rect: {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n },\n };\n}\n\nasync function handleHover(params: Record<string, unknown>): Promise<void> {\n const locator = params as ElementLocator;\n const element = await locateElement(locator);\n\n if (!element) {\n throw new Error('Element not found');\n }\n\n element.scrollIntoView({ behavior: 'smooth', block: 'center' });\n\n const rect = element.getBoundingClientRect();\n const x = rect.left + rect.width / 2;\n const y = rect.top + rect.height / 2;\n\n element.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true, clientX: x, clientY: y }));\n element.dispatchEvent(new MouseEvent('mouseover', { bubbles: true, clientX: x, clientY: y }));\n element.dispatchEvent(new MouseEvent('mousemove', { bubbles: true, clientX: x, clientY: y }));\n}\n\nasync function handleSelect(params: Record<string, unknown>): Promise<void> {\n const locator = params as ElementLocator;\n const value = params.value as string | string[];\n const element = await locateElement(locator);\n\n if (!element) {\n throw new Error('Element not found');\n }\n\n if (!(element instanceof HTMLSelectElement)) {\n throw new Error('Element is not a select element');\n }\n\n const values = Array.isArray(value) ? value : [value];\n\n for (const option of element.options) {\n option.selected = values.includes(option.value) || values.includes(option.text);\n }\n\n element.dispatchEvent(new Event('input', { bubbles: true }));\n element.dispatchEvent(new Event('change', { bubbles: true }));\n}\n\nasync function handleDrag(params: Record<string, unknown>): Promise<void> {\n const sourceLocator = params.source as ElementLocator;\n const targetLocator = params.target as ElementLocator;\n\n const sourceElement = await locateElement(sourceLocator);\n const targetElement = await locateElement(targetLocator);\n\n if (!sourceElement) {\n throw new Error('Source element not found');\n }\n\n if (!targetElement) {\n throw new Error('Target element not found');\n }\n\n const sourceRect = sourceElement.getBoundingClientRect();\n const targetRect = targetElement.getBoundingClientRect();\n\n const sourceX = sourceRect.left + sourceRect.width / 2;\n const sourceY = sourceRect.top + sourceRect.height / 2;\n const targetX = targetRect.left + targetRect.width / 2;\n const targetY = targetRect.top + targetRect.height / 2;\n\n sourceElement.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, clientX: sourceX, clientY: sourceY }));\n sourceElement.dispatchEvent(new MouseEvent('dragstart', { bubbles: true, clientX: sourceX, clientY: sourceY }));\n\n targetElement.dispatchEvent(new MouseEvent('dragenter', { bubbles: true, clientX: targetX, clientY: targetY }));\n targetElement.dispatchEvent(new MouseEvent('dragover', { bubbles: true, clientX: targetX, clientY: targetY }));\n targetElement.dispatchEvent(new MouseEvent('drop', { bubbles: true, clientX: targetX, clientY: targetY }));\n\n sourceElement.dispatchEvent(new MouseEvent('dragend', { bubbles: true, clientX: targetX, clientY: targetY }));\n targetElement.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, clientX: targetX, clientY: targetY }));\n}\n\nasync function handlePressKey(params: Record<string, unknown>): Promise<void> {\n const key = params.key as string;\n const modifiers = params.modifiers as string[] | undefined;\n\n const eventInit: KeyboardEventInit = {\n key,\n bubbles: true,\n ctrlKey: modifiers?.includes('Control') || modifiers?.includes('Ctrl'),\n shiftKey: modifiers?.includes('Shift'),\n altKey: modifiers?.includes('Alt'),\n metaKey: modifiers?.includes('Meta') || modifiers?.includes('Command'),\n };\n\n const activeElement = document.activeElement || document.body;\n activeElement.dispatchEvent(new KeyboardEvent('keydown', eventInit));\n activeElement.dispatchEvent(new KeyboardEvent('keypress', eventInit));\n activeElement.dispatchEvent(new KeyboardEvent('keyup', eventInit));\n}\n\nasync function handleWaitFor(params: Record<string, unknown>): Promise<void> {\n const selector = params.selector as string | undefined;\n const text = params.text as string | undefined;\n const state = (params.state as string) || 'visible';\n const timeout = (params.timeout as number) || 30000;\n\n const startTime = Date.now();\n\n while (Date.now() - startTime < timeout) {\n if (selector) {\n const element = document.querySelector(selector);\n if (state === 'visible' && element && isVisible(element)) {\n return;\n }\n if (state === 'hidden' && (!element || !isVisible(element))) {\n return;\n }\n if (state === 'attached' && element) {\n return;\n }\n if (state === 'detached' && !element) {\n return;\n }\n }\n\n if (text) {\n const found = document.body.textContent?.includes(text);\n if (found) {\n return;\n }\n }\n\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n throw new Error(`Wait condition not met within ${timeout}ms`);\n}\n\nfunction isVisible(element: Element): boolean {\n const style = window.getComputedStyle(element);\n return style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0';\n}\n"],"names":["node"],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ {
2
+ "manifest_version": 3,
3
+ "name": "Playwright MCP Extension",
4
+ "version": "0.1.0",
5
+ "description": "Chrome extension providing bot-detection-free browser automation for browse-tool",
6
+ "permissions": [
7
+ "tabs",
8
+ "scripting",
9
+ "webRequest",
10
+ "offscreen",
11
+ "debugger",
12
+ "cookies",
13
+ "browsingData",
14
+ "storage",
15
+ "activeTab",
16
+ "alarms",
17
+ "windows",
18
+ "tabCapture"
19
+ ],
20
+ "host_permissions": ["<all_urls>"],
21
+ "background": {
22
+ "service_worker": "background.js",
23
+ "type": "module"
24
+ },
25
+ "action": {
26
+ "default_popup": "popup.html",
27
+ "default_title": "Playwright MCP"
28
+ },
29
+ "content_scripts": [
30
+ {
31
+ "matches": ["<all_urls>"],
32
+ "js": ["content.js"],
33
+ "run_at": "document_start"
34
+ }
35
+ ]
36
+ }
@@ -0,0 +1,9 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Playwright MCP Offscreen</title>
5
+ </head>
6
+ <body>
7
+ <script type="module" src="offscreen.js"></script>
8
+ </body>
9
+ </html>