@eko-ai/eko 1.0.2 → 1.0.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.
- package/dist/core/eko.d.ts +1 -1
- package/dist/extension/content/index.d.ts +12 -4
- package/dist/extension/script/build_dom_tree.d.ts +1 -3
- package/dist/extension/script/build_dom_tree.js +7 -3
- package/dist/extension/tools/browser.d.ts +8 -8
- package/dist/extension/tools/browser_use.d.ts +1 -0
- package/dist/extension/tools/html_script.d.ts +1 -12
- package/dist/extension.cjs.js +182 -258
- package/dist/extension.esm.js +182 -258
- package/dist/extension_content_script.js +105 -76
- package/dist/index.cjs.js +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/types/action.types.d.ts +1 -0
- package/dist/web/script/build_dom_tree.d.ts +1 -3
- package/dist/web/tools/browser.d.ts +16 -6
- package/dist/web/tools/browser_use.d.ts +1 -0
- package/dist/web/tools/html_script.d.ts +1 -12
- package/dist/web.cjs.js +314 -228
- package/dist/web.esm.js +314 -228
- package/package.json +1 -1
package/dist/web.cjs.js
CHANGED
|
@@ -8,15 +8,16 @@
|
|
|
8
8
|
* @returns { element_str, selector_map }
|
|
9
9
|
*/
|
|
10
10
|
function get_clickable_elements(doHighlightElements = true, includeAttributes) {
|
|
11
|
+
window.clickable_elements = {};
|
|
11
12
|
let page_tree = build_dom_tree(doHighlightElements);
|
|
12
13
|
let element_tree = parse_node(page_tree);
|
|
13
14
|
let selector_map = create_selector_map(element_tree);
|
|
14
15
|
let element_str = clickable_elements_to_string(element_tree, includeAttributes);
|
|
15
16
|
return { element_str, selector_map };
|
|
16
17
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
function get_highlight_element(highlightIndex) {
|
|
19
|
+
return window.clickable_elements[highlightIndex];
|
|
20
|
+
}
|
|
20
21
|
function remove_highlight() {
|
|
21
22
|
let highlight = document.getElementById('playwright-highlight-container');
|
|
22
23
|
if (highlight) {
|
|
@@ -539,6 +540,7 @@ function build_dom_tree(doHighlightElements) {
|
|
|
539
540
|
// Highlight if element meets all criteria and highlighting is enabled
|
|
540
541
|
if (isInteractive && isVisible && isTop) {
|
|
541
542
|
nodeData.highlightIndex = highlightIndex++;
|
|
543
|
+
window.clickable_elements[nodeData.highlightIndex] = node;
|
|
542
544
|
if (doHighlightElements) {
|
|
543
545
|
highlightElement(node, nodeData.highlightIndex, parentIframe);
|
|
544
546
|
}
|
|
@@ -579,198 +581,9 @@ function build_dom_tree(doHighlightElements) {
|
|
|
579
581
|
return buildDomTree(document.body);
|
|
580
582
|
}
|
|
581
583
|
window.get_clickable_elements = get_clickable_elements;
|
|
584
|
+
window.get_highlight_element = get_highlight_element;
|
|
582
585
|
window.remove_highlight = remove_highlight;
|
|
583
586
|
|
|
584
|
-
function exportFile(filename, type, content) {
|
|
585
|
-
const blob = new Blob([content], { type: type });
|
|
586
|
-
const link = document.createElement('a');
|
|
587
|
-
link.href = URL.createObjectURL(blob);
|
|
588
|
-
link.download = filename;
|
|
589
|
-
document.body.appendChild(link);
|
|
590
|
-
link.click();
|
|
591
|
-
document.body.removeChild(link);
|
|
592
|
-
URL.revokeObjectURL(link.href);
|
|
593
|
-
}
|
|
594
|
-
function xpath(element) {
|
|
595
|
-
if (element.id !== '') {
|
|
596
|
-
return '//*[@id=\"' + element.id + '\"]';
|
|
597
|
-
}
|
|
598
|
-
if (element == document.body) {
|
|
599
|
-
return '/html/' + element.tagName.toLowerCase();
|
|
600
|
-
}
|
|
601
|
-
var ix = 1, siblings = element.parentNode.childNodes;
|
|
602
|
-
for (var i = 0, l = siblings.length; i < l; i++) {
|
|
603
|
-
var sibling = siblings[i];
|
|
604
|
-
if (sibling == element) {
|
|
605
|
-
return xpath(element.parentNode) + '/' + element.tagName.toLowerCase() + '[' + ix + ']';
|
|
606
|
-
}
|
|
607
|
-
else if (sibling.nodeType == 1 && sibling.tagName == element.tagName) {
|
|
608
|
-
ix++;
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
return '';
|
|
612
|
-
}
|
|
613
|
-
function getDropdownOptions(xpath) {
|
|
614
|
-
const select = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null)
|
|
615
|
-
.singleNodeValue;
|
|
616
|
-
if (!select) {
|
|
617
|
-
return null;
|
|
618
|
-
}
|
|
619
|
-
return {
|
|
620
|
-
options: Array.from(select.options).map((opt) => ({
|
|
621
|
-
index: opt.index,
|
|
622
|
-
text: opt.text.trim(),
|
|
623
|
-
value: opt.value,
|
|
624
|
-
})),
|
|
625
|
-
id: select.id,
|
|
626
|
-
name: select.name,
|
|
627
|
-
};
|
|
628
|
-
}
|
|
629
|
-
function selectDropdownOption(xpath, text) {
|
|
630
|
-
const select = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null)
|
|
631
|
-
.singleNodeValue;
|
|
632
|
-
if (!select || select.tagName.toUpperCase() !== 'SELECT') {
|
|
633
|
-
return { success: false, error: 'Select not found or invalid element type' };
|
|
634
|
-
}
|
|
635
|
-
const option = Array.from(select.options).find((opt) => opt.text.trim() === text);
|
|
636
|
-
if (!option) {
|
|
637
|
-
return {
|
|
638
|
-
success: false,
|
|
639
|
-
error: 'Option not found',
|
|
640
|
-
availableOptions: Array.from(select.options).map((o) => o.text.trim()),
|
|
641
|
-
};
|
|
642
|
-
}
|
|
643
|
-
select.value = option.value;
|
|
644
|
-
select.dispatchEvent(new Event('change'));
|
|
645
|
-
return {
|
|
646
|
-
success: true,
|
|
647
|
-
selectedValue: option.value,
|
|
648
|
-
selectedText: option.text.trim(),
|
|
649
|
-
};
|
|
650
|
-
}
|
|
651
|
-
/**
|
|
652
|
-
* Extract the elements related to html operability and wrap them into pseudo-html code.
|
|
653
|
-
*/
|
|
654
|
-
function extractOperableElements() {
|
|
655
|
-
// visible
|
|
656
|
-
const isElementVisible = (element) => {
|
|
657
|
-
const style = window.getComputedStyle(element);
|
|
658
|
-
return (style.display !== 'none' &&
|
|
659
|
-
style.visibility !== 'hidden' &&
|
|
660
|
-
style.opacity !== '0' &&
|
|
661
|
-
element.offsetWidth > 0 &&
|
|
662
|
-
element.offsetHeight > 0);
|
|
663
|
-
};
|
|
664
|
-
// element original index
|
|
665
|
-
const getElementIndex = (element) => {
|
|
666
|
-
const xpath = document.evaluate('preceding::*', element, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
|
667
|
-
return xpath.snapshotLength;
|
|
668
|
-
};
|
|
669
|
-
// exclude
|
|
670
|
-
const addExclude = (excludes, children) => {
|
|
671
|
-
for (let i = 0; i < children.length; i++) {
|
|
672
|
-
excludes.push(children[i]);
|
|
673
|
-
if (children[i].children) {
|
|
674
|
-
addExclude(excludes, children[i].children);
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
};
|
|
678
|
-
// { pseudoId: element }
|
|
679
|
-
let elementMap = {};
|
|
680
|
-
let nextId = 1;
|
|
681
|
-
let elements = [];
|
|
682
|
-
let excludes = [];
|
|
683
|
-
// operable element
|
|
684
|
-
const operableSelectors = 'a, button, input, textarea, select';
|
|
685
|
-
document.querySelectorAll(operableSelectors).forEach((element) => {
|
|
686
|
-
if (isElementVisible(element) && excludes.indexOf(element) == -1) {
|
|
687
|
-
const id = nextId++;
|
|
688
|
-
elementMap[id.toString()] = element;
|
|
689
|
-
const tagName = element.tagName.toLowerCase();
|
|
690
|
-
const attributes = Array.from(element.attributes)
|
|
691
|
-
.filter((attr) => ['id', 'name', 'type', 'value', 'href', 'title', 'placeholder'].includes(attr.name))
|
|
692
|
-
.map((attr) => `${attr.name == 'id' ? 'target' : attr.name}="${attr.value}"`)
|
|
693
|
-
.join(' ');
|
|
694
|
-
elements.push({
|
|
695
|
-
originalIndex: getElementIndex(element),
|
|
696
|
-
id: id,
|
|
697
|
-
html: `<${tagName} id="${id}" ${attributes}>${tagName == 'select' ? element.innerHTML : element.innerText || ''}</${tagName}>`,
|
|
698
|
-
});
|
|
699
|
-
addExclude(excludes, element.children);
|
|
700
|
-
}
|
|
701
|
-
});
|
|
702
|
-
// short text element
|
|
703
|
-
const textWalker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, {
|
|
704
|
-
acceptNode: function (node) {
|
|
705
|
-
var _a;
|
|
706
|
-
if (node.matches(operableSelectors) || excludes.indexOf(node) != -1) {
|
|
707
|
-
// skip
|
|
708
|
-
return NodeFilter.FILTER_SKIP;
|
|
709
|
-
}
|
|
710
|
-
// text <= 100
|
|
711
|
-
const text = (_a = node.innerText) === null || _a === void 0 ? void 0 : _a.trim();
|
|
712
|
-
if (isElementVisible(node) &&
|
|
713
|
-
text &&
|
|
714
|
-
text.length <= 100 &&
|
|
715
|
-
text.length > 0 &&
|
|
716
|
-
node.children.length === 0) {
|
|
717
|
-
return NodeFilter.FILTER_ACCEPT;
|
|
718
|
-
}
|
|
719
|
-
// skip
|
|
720
|
-
return NodeFilter.FILTER_SKIP;
|
|
721
|
-
},
|
|
722
|
-
});
|
|
723
|
-
let currentNode;
|
|
724
|
-
while ((currentNode = textWalker.nextNode())) {
|
|
725
|
-
const id = nextId++;
|
|
726
|
-
elementMap[id.toString()] = currentNode;
|
|
727
|
-
const tagName = currentNode.tagName.toLowerCase();
|
|
728
|
-
elements.push({
|
|
729
|
-
originalIndex: getElementIndex(currentNode),
|
|
730
|
-
id: id,
|
|
731
|
-
html: `<${tagName} id="${id}">${currentNode.innerText.trim()}</${tagName}>`,
|
|
732
|
-
});
|
|
733
|
-
}
|
|
734
|
-
// element sort
|
|
735
|
-
elements.sort((a, b) => a.originalIndex - b.originalIndex);
|
|
736
|
-
// cache
|
|
737
|
-
window.operableElementMap = elementMap;
|
|
738
|
-
// pseudo html
|
|
739
|
-
return elements.map((e) => e.html).join('\n');
|
|
740
|
-
}
|
|
741
|
-
function clickOperableElement(id) {
|
|
742
|
-
let element = window.operableElementMap[id];
|
|
743
|
-
if (!element) {
|
|
744
|
-
return false;
|
|
745
|
-
}
|
|
746
|
-
if (element.click) {
|
|
747
|
-
element.click();
|
|
748
|
-
}
|
|
749
|
-
else {
|
|
750
|
-
element.dispatchEvent(new MouseEvent('click', {
|
|
751
|
-
view: window,
|
|
752
|
-
bubbles: true,
|
|
753
|
-
cancelable: true,
|
|
754
|
-
}));
|
|
755
|
-
}
|
|
756
|
-
return true;
|
|
757
|
-
}
|
|
758
|
-
function getOperableElementRect(id) {
|
|
759
|
-
let element = window.operableElementMap[id];
|
|
760
|
-
if (!element) {
|
|
761
|
-
return null;
|
|
762
|
-
}
|
|
763
|
-
const rect = element.getBoundingClientRect();
|
|
764
|
-
return {
|
|
765
|
-
left: rect.left + window.scrollX,
|
|
766
|
-
top: rect.top + window.scrollY,
|
|
767
|
-
right: rect.right + window.scrollX,
|
|
768
|
-
bottom: rect.bottom + window.scrollY,
|
|
769
|
-
width: rect.right - rect.left,
|
|
770
|
-
height: rect.bottom - rect.top,
|
|
771
|
-
};
|
|
772
|
-
}
|
|
773
|
-
|
|
774
587
|
/*!
|
|
775
588
|
* html2canvas 1.4.1 <https://html2canvas.hertzen.com>
|
|
776
589
|
* Copyright (c) 2022 Niklas von Hertzen <https://hertzen.com>
|
|
@@ -8591,20 +8404,20 @@ var parseBackgroundColor = function (context, element, backgroundColorOverride)
|
|
|
8591
8404
|
: defaultBackgroundColor;
|
|
8592
8405
|
};
|
|
8593
8406
|
|
|
8594
|
-
function type(xpath,
|
|
8595
|
-
return do_input(xpath,
|
|
8407
|
+
function type(text, xpath, highlightIndex) {
|
|
8408
|
+
return do_input(text, xpath, highlightIndex);
|
|
8596
8409
|
}
|
|
8597
|
-
function clear_input(xpath) {
|
|
8598
|
-
return do_input(xpath,
|
|
8410
|
+
function clear_input(xpath, highlightIndex) {
|
|
8411
|
+
return do_input('', xpath, highlightIndex);
|
|
8599
8412
|
}
|
|
8600
|
-
function left_click(xpath) {
|
|
8601
|
-
return simulateMouseEvent(
|
|
8413
|
+
function left_click(xpath, highlightIndex) {
|
|
8414
|
+
return simulateMouseEvent(['mousedown', 'mouseup', 'click'], 0, xpath, highlightIndex);
|
|
8602
8415
|
}
|
|
8603
|
-
function right_click(xpath) {
|
|
8604
|
-
return simulateMouseEvent(
|
|
8416
|
+
function right_click(xpath, highlightIndex) {
|
|
8417
|
+
return simulateMouseEvent(['mousedown', 'mouseup', 'contextmenu'], 2, xpath, highlightIndex);
|
|
8605
8418
|
}
|
|
8606
|
-
function double_click(xpath) {
|
|
8607
|
-
return simulateMouseEvent(
|
|
8419
|
+
function double_click(xpath, highlightIndex) {
|
|
8420
|
+
return simulateMouseEvent(['mousedown', 'mouseup', 'click', 'mousedown', 'mouseup', 'click', 'dblclick'], 0, xpath, highlightIndex);
|
|
8608
8421
|
}
|
|
8609
8422
|
async function screenshot() {
|
|
8610
8423
|
const [width, height] = size();
|
|
@@ -8634,12 +8447,72 @@ async function screenshot() {
|
|
|
8634
8447
|
},
|
|
8635
8448
|
};
|
|
8636
8449
|
}
|
|
8637
|
-
function scroll_to(xpath) {
|
|
8638
|
-
let
|
|
8639
|
-
|
|
8640
|
-
|
|
8450
|
+
function scroll_to(xpath, highlightIndex) {
|
|
8451
|
+
let element = null;
|
|
8452
|
+
if (highlightIndex != null) {
|
|
8453
|
+
element = window.get_highlight_element(highlightIndex);
|
|
8454
|
+
}
|
|
8455
|
+
else if (xpath) {
|
|
8456
|
+
element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null)
|
|
8457
|
+
.singleNodeValue;
|
|
8458
|
+
}
|
|
8459
|
+
if (!element) {
|
|
8460
|
+
return false;
|
|
8461
|
+
}
|
|
8462
|
+
element.scrollIntoView({
|
|
8641
8463
|
behavior: 'smooth',
|
|
8642
8464
|
});
|
|
8465
|
+
return true;
|
|
8466
|
+
}
|
|
8467
|
+
function get_dropdown_options(xpath, highlightIndex) {
|
|
8468
|
+
let select = null;
|
|
8469
|
+
if (highlightIndex != null) {
|
|
8470
|
+
select = window.get_highlight_element(highlightIndex);
|
|
8471
|
+
}
|
|
8472
|
+
else if (xpath) {
|
|
8473
|
+
select = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null)
|
|
8474
|
+
.singleNodeValue;
|
|
8475
|
+
}
|
|
8476
|
+
if (!select) {
|
|
8477
|
+
return null;
|
|
8478
|
+
}
|
|
8479
|
+
return {
|
|
8480
|
+
options: Array.from(select.options).map((opt) => ({
|
|
8481
|
+
index: opt.index,
|
|
8482
|
+
text: opt.text.trim(),
|
|
8483
|
+
value: opt.value,
|
|
8484
|
+
})),
|
|
8485
|
+
id: select.id,
|
|
8486
|
+
name: select.name,
|
|
8487
|
+
};
|
|
8488
|
+
}
|
|
8489
|
+
function select_dropdown_option(text, xpath, highlightIndex) {
|
|
8490
|
+
let select = null;
|
|
8491
|
+
if (highlightIndex != null) {
|
|
8492
|
+
select = window.get_highlight_element(highlightIndex);
|
|
8493
|
+
}
|
|
8494
|
+
else if (xpath) {
|
|
8495
|
+
select = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null)
|
|
8496
|
+
.singleNodeValue;
|
|
8497
|
+
}
|
|
8498
|
+
if (!select || select.tagName.toUpperCase() !== 'SELECT') {
|
|
8499
|
+
return { success: false, error: 'Select not found or invalid element type' };
|
|
8500
|
+
}
|
|
8501
|
+
const option = Array.from(select.options).find((opt) => opt.text.trim() === text);
|
|
8502
|
+
if (!option) {
|
|
8503
|
+
return {
|
|
8504
|
+
success: false,
|
|
8505
|
+
error: 'Option not found',
|
|
8506
|
+
availableOptions: Array.from(select.options).map((o) => o.text.trim()),
|
|
8507
|
+
};
|
|
8508
|
+
}
|
|
8509
|
+
select.value = option.value;
|
|
8510
|
+
select.dispatchEvent(new Event('change'));
|
|
8511
|
+
return {
|
|
8512
|
+
success: true,
|
|
8513
|
+
selectedValue: option.value,
|
|
8514
|
+
selectedText: option.text.trim(),
|
|
8515
|
+
};
|
|
8643
8516
|
}
|
|
8644
8517
|
function extractHtmlContent() {
|
|
8645
8518
|
let element = document.body;
|
|
@@ -8676,11 +8549,26 @@ function size() {
|
|
|
8676
8549
|
window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight,
|
|
8677
8550
|
];
|
|
8678
8551
|
}
|
|
8679
|
-
function do_input(xpath,
|
|
8680
|
-
let
|
|
8681
|
-
|
|
8552
|
+
function do_input(text, xpath, highlightIndex) {
|
|
8553
|
+
let element = null;
|
|
8554
|
+
if (highlightIndex != null) {
|
|
8555
|
+
element = window.get_highlight_element(highlightIndex);
|
|
8556
|
+
}
|
|
8557
|
+
else if (xpath) {
|
|
8558
|
+
element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null)
|
|
8559
|
+
.singleNodeValue;
|
|
8560
|
+
}
|
|
8682
8561
|
if (!element) {
|
|
8683
|
-
return;
|
|
8562
|
+
return false;
|
|
8563
|
+
}
|
|
8564
|
+
let enter = false;
|
|
8565
|
+
if (text.endsWith('\\n')) {
|
|
8566
|
+
enter = true;
|
|
8567
|
+
text = text.substring(0, text.length - 2);
|
|
8568
|
+
}
|
|
8569
|
+
else if (text.endsWith('\n')) {
|
|
8570
|
+
enter = true;
|
|
8571
|
+
text = text.substring(0, text.length - 1);
|
|
8684
8572
|
}
|
|
8685
8573
|
let input;
|
|
8686
8574
|
if (element.tagName == 'INPUT' ||
|
|
@@ -8699,13 +8587,33 @@ function do_input(xpath, text) {
|
|
|
8699
8587
|
input.value += text;
|
|
8700
8588
|
}
|
|
8701
8589
|
let result = input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
8590
|
+
if (enter) {
|
|
8591
|
+
['keydown', 'keypress', 'keyup'].forEach((eventType) => {
|
|
8592
|
+
const event = new KeyboardEvent(eventType, {
|
|
8593
|
+
key: 'Enter',
|
|
8594
|
+
code: 'Enter',
|
|
8595
|
+
keyCode: 13,
|
|
8596
|
+
bubbles: true,
|
|
8597
|
+
cancelable: true,
|
|
8598
|
+
});
|
|
8599
|
+
input.dispatchEvent(event);
|
|
8600
|
+
});
|
|
8601
|
+
}
|
|
8702
8602
|
console.log('type', input, result);
|
|
8703
|
-
return
|
|
8603
|
+
return true;
|
|
8704
8604
|
}
|
|
8705
|
-
function simulateMouseEvent(
|
|
8706
|
-
let
|
|
8707
|
-
|
|
8708
|
-
|
|
8605
|
+
function simulateMouseEvent(eventTypes, button, xpath, highlightIndex) {
|
|
8606
|
+
let element = null;
|
|
8607
|
+
if (highlightIndex != null) {
|
|
8608
|
+
element = window.get_highlight_element(highlightIndex);
|
|
8609
|
+
}
|
|
8610
|
+
else if (xpath) {
|
|
8611
|
+
element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null)
|
|
8612
|
+
.singleNodeValue;
|
|
8613
|
+
}
|
|
8614
|
+
if (!element) {
|
|
8615
|
+
return false;
|
|
8616
|
+
}
|
|
8709
8617
|
for (let i = 0; i < eventTypes.length; i++) {
|
|
8710
8618
|
const event = new MouseEvent(eventTypes[i], {
|
|
8711
8619
|
view: window,
|
|
@@ -8713,10 +8621,10 @@ function simulateMouseEvent(xpath, eventTypes, button) {
|
|
|
8713
8621
|
cancelable: true,
|
|
8714
8622
|
button, // 0 left; 2 right
|
|
8715
8623
|
});
|
|
8716
|
-
result = element.dispatchEvent(event);
|
|
8624
|
+
let result = element.dispatchEvent(event);
|
|
8717
8625
|
console.log('simulateMouse', element, { xpath, eventTypes, button }, result);
|
|
8718
8626
|
}
|
|
8719
|
-
return
|
|
8627
|
+
return true;
|
|
8720
8628
|
}
|
|
8721
8629
|
|
|
8722
8630
|
var browser = /*#__PURE__*/Object.freeze({
|
|
@@ -8724,10 +8632,12 @@ var browser = /*#__PURE__*/Object.freeze({
|
|
|
8724
8632
|
clear_input: clear_input,
|
|
8725
8633
|
double_click: double_click,
|
|
8726
8634
|
extractHtmlContent: extractHtmlContent,
|
|
8635
|
+
get_dropdown_options: get_dropdown_options,
|
|
8727
8636
|
left_click: left_click,
|
|
8728
8637
|
right_click: right_click,
|
|
8729
8638
|
screenshot: screenshot,
|
|
8730
8639
|
scroll_to: scroll_to,
|
|
8640
|
+
select_dropdown_option: select_dropdown_option,
|
|
8731
8641
|
size: size,
|
|
8732
8642
|
type: type
|
|
8733
8643
|
});
|
|
@@ -8817,7 +8727,7 @@ class BrowserUse {
|
|
|
8817
8727
|
if (params === null || !params.action) {
|
|
8818
8728
|
throw new Error('Invalid parameters. Expected an object with a "action" property.');
|
|
8819
8729
|
}
|
|
8820
|
-
let selector_map = context.
|
|
8730
|
+
let selector_map = context.selector_map;
|
|
8821
8731
|
let selector_xpath;
|
|
8822
8732
|
if (params.index != null && selector_map) {
|
|
8823
8733
|
selector_xpath = (_a = selector_map[params.index]) === null || _a === void 0 ? void 0 : _a.xpath;
|
|
@@ -8834,42 +8744,42 @@ class BrowserUse {
|
|
|
8834
8744
|
if (params.text == null) {
|
|
8835
8745
|
throw new Error('text parameter is required');
|
|
8836
8746
|
}
|
|
8837
|
-
result = await type(selector_xpath, params.
|
|
8747
|
+
result = await type(params.text, selector_xpath, params.index);
|
|
8838
8748
|
await sleep(200);
|
|
8839
8749
|
break;
|
|
8840
8750
|
case 'clear_text':
|
|
8841
8751
|
if (params.index == null) {
|
|
8842
8752
|
throw new Error('index parameter is required');
|
|
8843
8753
|
}
|
|
8844
|
-
result = await clear_input(selector_xpath);
|
|
8754
|
+
result = await clear_input(selector_xpath, params.index);
|
|
8845
8755
|
await sleep(100);
|
|
8846
8756
|
break;
|
|
8847
8757
|
case 'click':
|
|
8848
8758
|
if (params.index == null) {
|
|
8849
8759
|
throw new Error('index parameter is required');
|
|
8850
8760
|
}
|
|
8851
|
-
result = await left_click(selector_xpath);
|
|
8761
|
+
result = await left_click(selector_xpath, params.index);
|
|
8852
8762
|
await sleep(100);
|
|
8853
8763
|
break;
|
|
8854
8764
|
case 'right_click':
|
|
8855
8765
|
if (params.index == null) {
|
|
8856
8766
|
throw new Error('index parameter is required');
|
|
8857
8767
|
}
|
|
8858
|
-
result = await right_click(selector_xpath);
|
|
8768
|
+
result = await right_click(selector_xpath, params.index);
|
|
8859
8769
|
await sleep(100);
|
|
8860
8770
|
break;
|
|
8861
8771
|
case 'double_click':
|
|
8862
8772
|
if (params.index == null) {
|
|
8863
8773
|
throw new Error('index parameter is required');
|
|
8864
8774
|
}
|
|
8865
|
-
result = await double_click(selector_xpath);
|
|
8775
|
+
result = await double_click(selector_xpath, params.index);
|
|
8866
8776
|
await sleep(100);
|
|
8867
8777
|
break;
|
|
8868
8778
|
case 'scroll_to':
|
|
8869
8779
|
if (params.index == null) {
|
|
8870
8780
|
throw new Error('index parameter is required');
|
|
8871
8781
|
}
|
|
8872
|
-
result = await scroll_to(selector_xpath);
|
|
8782
|
+
result = await scroll_to(selector_xpath, params.index);
|
|
8873
8783
|
await sleep(500);
|
|
8874
8784
|
break;
|
|
8875
8785
|
case 'extract_content':
|
|
@@ -8884,7 +8794,7 @@ class BrowserUse {
|
|
|
8884
8794
|
if (params.index == null) {
|
|
8885
8795
|
throw new Error('index parameter is required');
|
|
8886
8796
|
}
|
|
8887
|
-
result =
|
|
8797
|
+
result = get_dropdown_options(selector_xpath, params.index);
|
|
8888
8798
|
break;
|
|
8889
8799
|
case 'select_dropdown_option':
|
|
8890
8800
|
if (params.index == null) {
|
|
@@ -8893,12 +8803,12 @@ class BrowserUse {
|
|
|
8893
8803
|
if (params.text == null) {
|
|
8894
8804
|
throw new Error('text parameter is required');
|
|
8895
8805
|
}
|
|
8896
|
-
result =
|
|
8806
|
+
result = select_dropdown_option(params.text, selector_xpath, params.index);
|
|
8897
8807
|
break;
|
|
8898
8808
|
case 'screenshot_extract_element':
|
|
8899
8809
|
await sleep(100);
|
|
8900
8810
|
let element_result = get_clickable_elements(true, null);
|
|
8901
|
-
context.
|
|
8811
|
+
context.selector_map = element_result.selector_map;
|
|
8902
8812
|
let screenshot$1 = await screenshot();
|
|
8903
8813
|
remove_highlight();
|
|
8904
8814
|
result = { image: screenshot$1.image, text: element_result.element_str };
|
|
@@ -8917,11 +8827,187 @@ class BrowserUse {
|
|
|
8917
8827
|
return { success: false, error: e === null || e === void 0 ? void 0 : e.message };
|
|
8918
8828
|
}
|
|
8919
8829
|
}
|
|
8830
|
+
destroy(context) {
|
|
8831
|
+
delete context.selector_map;
|
|
8832
|
+
}
|
|
8920
8833
|
}
|
|
8921
8834
|
function sleep(time) {
|
|
8922
8835
|
return new Promise((resolve) => setTimeout(() => resolve(), time));
|
|
8923
8836
|
}
|
|
8924
8837
|
|
|
8838
|
+
function exportFile(filename, type, content) {
|
|
8839
|
+
const blob = new Blob([content], { type: type });
|
|
8840
|
+
const link = document.createElement('a');
|
|
8841
|
+
link.href = URL.createObjectURL(blob);
|
|
8842
|
+
link.download = filename;
|
|
8843
|
+
document.body.appendChild(link);
|
|
8844
|
+
link.click();
|
|
8845
|
+
document.body.removeChild(link);
|
|
8846
|
+
URL.revokeObjectURL(link.href);
|
|
8847
|
+
}
|
|
8848
|
+
function xpath(element) {
|
|
8849
|
+
if (element == document.body) {
|
|
8850
|
+
return '/html/' + element.tagName.toLowerCase();
|
|
8851
|
+
}
|
|
8852
|
+
if (element.parentNode instanceof ShadowRoot) {
|
|
8853
|
+
let shadowRoot = element.parentNode;
|
|
8854
|
+
let parent = shadowRoot.getRootNode().host;
|
|
8855
|
+
return xpath(parent) + '//' + element.tagName.toLowerCase();
|
|
8856
|
+
}
|
|
8857
|
+
else {
|
|
8858
|
+
let sp;
|
|
8859
|
+
let parent;
|
|
8860
|
+
if (element.parentNode instanceof ShadowRoot) {
|
|
8861
|
+
sp = '//';
|
|
8862
|
+
let shadowRoot = element.parentNode;
|
|
8863
|
+
parent = shadowRoot.getRootNode().host;
|
|
8864
|
+
}
|
|
8865
|
+
else {
|
|
8866
|
+
sp = '/';
|
|
8867
|
+
parent = element.parentNode;
|
|
8868
|
+
}
|
|
8869
|
+
let siblings = parent.childNodes;
|
|
8870
|
+
if (siblings.length == 1) {
|
|
8871
|
+
return xpath(parent) + sp + element.tagName.toLowerCase();
|
|
8872
|
+
}
|
|
8873
|
+
else {
|
|
8874
|
+
let ix = 1;
|
|
8875
|
+
for (let i = 0, l = siblings.length; i < l; i++) {
|
|
8876
|
+
let sibling = siblings[i];
|
|
8877
|
+
if (sibling == element) {
|
|
8878
|
+
return xpath(parent) + sp + element.tagName.toLowerCase() + '[' + ix + ']';
|
|
8879
|
+
}
|
|
8880
|
+
else if (sibling.nodeType == 1 && sibling.tagName == element.tagName) {
|
|
8881
|
+
ix++;
|
|
8882
|
+
}
|
|
8883
|
+
}
|
|
8884
|
+
return '';
|
|
8885
|
+
}
|
|
8886
|
+
}
|
|
8887
|
+
}
|
|
8888
|
+
/**
|
|
8889
|
+
* Extract the elements related to html operability and wrap them into pseudo-html code.
|
|
8890
|
+
*/
|
|
8891
|
+
function extractOperableElements() {
|
|
8892
|
+
// visible
|
|
8893
|
+
const isElementVisible = (element) => {
|
|
8894
|
+
const style = window.getComputedStyle(element);
|
|
8895
|
+
return (style.display !== 'none' &&
|
|
8896
|
+
style.visibility !== 'hidden' &&
|
|
8897
|
+
style.opacity !== '0' &&
|
|
8898
|
+
element.offsetWidth > 0 &&
|
|
8899
|
+
element.offsetHeight > 0);
|
|
8900
|
+
};
|
|
8901
|
+
// element original index
|
|
8902
|
+
const getElementIndex = (element) => {
|
|
8903
|
+
const xpath = document.evaluate('preceding::*', element, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
|
8904
|
+
return xpath.snapshotLength;
|
|
8905
|
+
};
|
|
8906
|
+
// exclude
|
|
8907
|
+
const addExclude = (excludes, children) => {
|
|
8908
|
+
for (let i = 0; i < children.length; i++) {
|
|
8909
|
+
excludes.push(children[i]);
|
|
8910
|
+
if (children[i].children) {
|
|
8911
|
+
addExclude(excludes, children[i].children);
|
|
8912
|
+
}
|
|
8913
|
+
}
|
|
8914
|
+
};
|
|
8915
|
+
// { pseudoId: element }
|
|
8916
|
+
let elementMap = {};
|
|
8917
|
+
let nextId = 1;
|
|
8918
|
+
let elements = [];
|
|
8919
|
+
let excludes = [];
|
|
8920
|
+
// operable element
|
|
8921
|
+
const operableSelectors = 'a, button, input, textarea, select';
|
|
8922
|
+
document.querySelectorAll(operableSelectors).forEach((element) => {
|
|
8923
|
+
if (isElementVisible(element) && excludes.indexOf(element) == -1) {
|
|
8924
|
+
const id = nextId++;
|
|
8925
|
+
elementMap[id.toString()] = element;
|
|
8926
|
+
const tagName = element.tagName.toLowerCase();
|
|
8927
|
+
const attributes = Array.from(element.attributes)
|
|
8928
|
+
.filter((attr) => ['id', 'name', 'type', 'value', 'href', 'title', 'placeholder'].includes(attr.name))
|
|
8929
|
+
.map((attr) => `${attr.name == 'id' ? 'target' : attr.name}="${attr.value}"`)
|
|
8930
|
+
.join(' ');
|
|
8931
|
+
elements.push({
|
|
8932
|
+
originalIndex: getElementIndex(element),
|
|
8933
|
+
id: id,
|
|
8934
|
+
html: `<${tagName} id="${id}" ${attributes}>${tagName == 'select' ? element.innerHTML : element.innerText || ''}</${tagName}>`,
|
|
8935
|
+
});
|
|
8936
|
+
addExclude(excludes, element.children);
|
|
8937
|
+
}
|
|
8938
|
+
});
|
|
8939
|
+
// short text element
|
|
8940
|
+
const textWalker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, {
|
|
8941
|
+
acceptNode: function (node) {
|
|
8942
|
+
var _a;
|
|
8943
|
+
if (node.matches(operableSelectors) || excludes.indexOf(node) != -1) {
|
|
8944
|
+
// skip
|
|
8945
|
+
return NodeFilter.FILTER_SKIP;
|
|
8946
|
+
}
|
|
8947
|
+
// text <= 100
|
|
8948
|
+
const text = (_a = node.innerText) === null || _a === void 0 ? void 0 : _a.trim();
|
|
8949
|
+
if (isElementVisible(node) &&
|
|
8950
|
+
text &&
|
|
8951
|
+
text.length <= 100 &&
|
|
8952
|
+
text.length > 0 &&
|
|
8953
|
+
node.children.length === 0) {
|
|
8954
|
+
return NodeFilter.FILTER_ACCEPT;
|
|
8955
|
+
}
|
|
8956
|
+
// skip
|
|
8957
|
+
return NodeFilter.FILTER_SKIP;
|
|
8958
|
+
},
|
|
8959
|
+
});
|
|
8960
|
+
let currentNode;
|
|
8961
|
+
while ((currentNode = textWalker.nextNode())) {
|
|
8962
|
+
const id = nextId++;
|
|
8963
|
+
elementMap[id.toString()] = currentNode;
|
|
8964
|
+
const tagName = currentNode.tagName.toLowerCase();
|
|
8965
|
+
elements.push({
|
|
8966
|
+
originalIndex: getElementIndex(currentNode),
|
|
8967
|
+
id: id,
|
|
8968
|
+
html: `<${tagName} id="${id}">${currentNode.innerText.trim()}</${tagName}>`,
|
|
8969
|
+
});
|
|
8970
|
+
}
|
|
8971
|
+
// element sort
|
|
8972
|
+
elements.sort((a, b) => a.originalIndex - b.originalIndex);
|
|
8973
|
+
// cache
|
|
8974
|
+
window.operableElementMap = elementMap;
|
|
8975
|
+
// pseudo html
|
|
8976
|
+
return elements.map((e) => e.html).join('\n');
|
|
8977
|
+
}
|
|
8978
|
+
function clickOperableElement(id) {
|
|
8979
|
+
let element = window.operableElementMap[id];
|
|
8980
|
+
if (!element) {
|
|
8981
|
+
return false;
|
|
8982
|
+
}
|
|
8983
|
+
if (element.click) {
|
|
8984
|
+
element.click();
|
|
8985
|
+
}
|
|
8986
|
+
else {
|
|
8987
|
+
element.dispatchEvent(new MouseEvent('click', {
|
|
8988
|
+
view: window,
|
|
8989
|
+
bubbles: true,
|
|
8990
|
+
cancelable: true,
|
|
8991
|
+
}));
|
|
8992
|
+
}
|
|
8993
|
+
return true;
|
|
8994
|
+
}
|
|
8995
|
+
function getOperableElementRect(id) {
|
|
8996
|
+
let element = window.operableElementMap[id];
|
|
8997
|
+
if (!element) {
|
|
8998
|
+
return null;
|
|
8999
|
+
}
|
|
9000
|
+
const rect = element.getBoundingClientRect();
|
|
9001
|
+
return {
|
|
9002
|
+
left: rect.left + window.scrollX,
|
|
9003
|
+
top: rect.top + window.scrollY,
|
|
9004
|
+
right: rect.right + window.scrollX,
|
|
9005
|
+
bottom: rect.bottom + window.scrollY,
|
|
9006
|
+
width: rect.right - rect.left,
|
|
9007
|
+
height: rect.bottom - rect.top,
|
|
9008
|
+
};
|
|
9009
|
+
}
|
|
9010
|
+
|
|
8925
9011
|
/**
|
|
8926
9012
|
* Element click
|
|
8927
9013
|
*/
|