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