agentcrew-ai 0.8.2__py3-none-any.whl → 0.8.3__py3-none-any.whl
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.
- AgentCrew/__init__.py +1 -1
- AgentCrew/modules/agents/local_agent.py +11 -0
- AgentCrew/modules/browser_automation/element_extractor.py +4 -3
- AgentCrew/modules/browser_automation/js/draw_element_boxes.js +200 -0
- AgentCrew/modules/browser_automation/js/extract_clickable_elements.js +57 -23
- AgentCrew/modules/browser_automation/js/extract_elements_by_text.js +21 -19
- AgentCrew/modules/browser_automation/js/extract_input_elements.js +22 -23
- AgentCrew/modules/browser_automation/js/filter_hidden_elements.js +104 -0
- AgentCrew/modules/browser_automation/js/remove_element_boxes.js +29 -0
- AgentCrew/modules/browser_automation/js_loader.py +385 -92
- AgentCrew/modules/browser_automation/service.py +118 -347
- AgentCrew/modules/browser_automation/tool.py +28 -29
- AgentCrew/modules/chat/message/conversation.py +9 -8
- AgentCrew/modules/console/input_handler.py +2 -0
- AgentCrew/modules/console/ui_effects.py +3 -4
- AgentCrew/modules/custom_llm/service.py +25 -3
- AgentCrew/modules/file_editing/tool.py +9 -11
- AgentCrew/modules/google/native_service.py +13 -0
- AgentCrew/modules/llm/constants.py +38 -1
- AgentCrew/modules/llm/model_registry.py +9 -0
- AgentCrew/modules/llm/types.py +12 -1
- AgentCrew/modules/memory/base_service.py +2 -2
- AgentCrew/modules/memory/chroma_service.py +80 -138
- AgentCrew/modules/memory/tool.py +15 -15
- AgentCrew/modules/openai/response_service.py +19 -11
- AgentCrew/modules/openai/service.py +15 -0
- AgentCrew/modules/prompts/constants.py +27 -14
- {agentcrew_ai-0.8.2.dist-info → agentcrew_ai-0.8.3.dist-info}/METADATA +2 -2
- {agentcrew_ai-0.8.2.dist-info → agentcrew_ai-0.8.3.dist-info}/RECORD +33 -30
- {agentcrew_ai-0.8.2.dist-info → agentcrew_ai-0.8.3.dist-info}/WHEEL +0 -0
- {agentcrew_ai-0.8.2.dist-info → agentcrew_ai-0.8.3.dist-info}/entry_points.txt +0 -0
- {agentcrew_ai-0.8.2.dist-info → agentcrew_ai-0.8.3.dist-info}/licenses/LICENSE +0 -0
- {agentcrew_ai-0.8.2.dist-info → agentcrew_ai-0.8.3.dist-info}/top_level.txt +0 -0
AgentCrew/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.8.
|
|
1
|
+
__version__ = "0.8.3"
|
|
@@ -634,6 +634,17 @@ Check if `when` condition in <Global_Behavior> or <Project_Behavior> matches, up
|
|
|
634
634
|
- Skip agent evaluation if user request is when...,[action]... related to adaptive behaviors call `adapt` tool instead.""",
|
|
635
635
|
},
|
|
636
636
|
)
|
|
637
|
+
if self.services.get("memory"):
|
|
638
|
+
memory_headers = self.services["memory"].list_memory_headers(
|
|
639
|
+
agent_name=self.name
|
|
640
|
+
)
|
|
641
|
+
if memory_headers:
|
|
642
|
+
adaptive_messages["content"].append(
|
|
643
|
+
{
|
|
644
|
+
"type": "text",
|
|
645
|
+
"text": f"Here are conversations that we have discussed:\n- {'\n- '.join(memory_headers)}",
|
|
646
|
+
}
|
|
647
|
+
)
|
|
637
648
|
if len(adaptive_messages["content"]) > 0:
|
|
638
649
|
final_messages.insert(last_user_index, adaptive_messages)
|
|
639
650
|
|
|
@@ -162,12 +162,13 @@ def extract_clickable_elements(chrome_interface, uuid_mapping: Dict[str, str]) -
|
|
|
162
162
|
markdown_output.append(
|
|
163
163
|
"\n\n## Clickable Elements\nUse browser_click with UUID to click elements.\n"
|
|
164
164
|
)
|
|
165
|
-
markdown_output.append("| UUID | Text/Alt |\n")
|
|
166
|
-
markdown_output.append("
|
|
165
|
+
markdown_output.append("| UUID | Type | Text/Alt |\n")
|
|
166
|
+
markdown_output.append("|------|------|-----------|\n")
|
|
167
167
|
|
|
168
168
|
for element in elements_data:
|
|
169
169
|
xpath = element.get("xpath", "")
|
|
170
170
|
text = element.get("text", "").strip()
|
|
171
|
+
element_type = element.get("type", "").strip()
|
|
171
172
|
|
|
172
173
|
# Skip empty text entries
|
|
173
174
|
if not text:
|
|
@@ -180,7 +181,7 @@ def extract_clickable_elements(chrome_interface, uuid_mapping: Dict[str, str]) -
|
|
|
180
181
|
# Escape pipe characters in text for markdown table
|
|
181
182
|
text = text.replace("|", "\\|")
|
|
182
183
|
|
|
183
|
-
markdown_output.append(f"| `{element_uuid}` | {text} |\n")
|
|
184
|
+
markdown_output.append(f"| `{element_uuid}` | {element_type} | {text} |\n")
|
|
184
185
|
|
|
185
186
|
return "".join(markdown_output)
|
|
186
187
|
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Draw colored rectangle boxes with UUID labels over elements
|
|
3
|
+
*
|
|
4
|
+
* @param {Object} uuidXpathMap - Map of UUID to XPath selector
|
|
5
|
+
* @returns {Object} Result object with success status and message
|
|
6
|
+
*/
|
|
7
|
+
function drawElementBoxes(uuidXpathMap) {
|
|
8
|
+
try {
|
|
9
|
+
const existingContainer = document.getElementById(
|
|
10
|
+
"agentcrew-element-overlay-container",
|
|
11
|
+
);
|
|
12
|
+
if (existingContainer) {
|
|
13
|
+
existingContainer.remove();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const svgNS = "http://www.w3.org/2000/svg";
|
|
17
|
+
const container = document.createElementNS(svgNS, "svg");
|
|
18
|
+
container.setAttribute("id", "agentcrew-element-overlay-container");
|
|
19
|
+
container.style.position = "fixed";
|
|
20
|
+
container.style.top = "0";
|
|
21
|
+
container.style.left = "0";
|
|
22
|
+
container.style.width = "100%";
|
|
23
|
+
container.style.height = "100%";
|
|
24
|
+
container.style.pointerEvents = "none";
|
|
25
|
+
container.style.zIndex = "2147483647";
|
|
26
|
+
|
|
27
|
+
const colors = [
|
|
28
|
+
"#FF6B6B",
|
|
29
|
+
"#4ECDC4",
|
|
30
|
+
"#45B7D1",
|
|
31
|
+
"#FFA07A",
|
|
32
|
+
"#98D8C8",
|
|
33
|
+
"#F7DC6F",
|
|
34
|
+
"#BB8FCE",
|
|
35
|
+
"#85C1E2",
|
|
36
|
+
"#F8B739",
|
|
37
|
+
"#52B788",
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
const labelPadding = 8;
|
|
41
|
+
const fontSize = 14;
|
|
42
|
+
const labelHeight = 24;
|
|
43
|
+
const occupiedSpaces = [];
|
|
44
|
+
|
|
45
|
+
function checkOverlap(newLabel, existingLabels) {
|
|
46
|
+
for (const existing of existingLabels) {
|
|
47
|
+
if (
|
|
48
|
+
!(
|
|
49
|
+
newLabel.right < existing.left ||
|
|
50
|
+
newLabel.left > existing.right ||
|
|
51
|
+
newLabel.bottom < existing.top ||
|
|
52
|
+
newLabel.top > existing.bottom
|
|
53
|
+
)
|
|
54
|
+
) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function findBestLabelPosition(rect, labelWidth, existingLabels) {
|
|
62
|
+
const positions = [
|
|
63
|
+
{ x: rect.left, y: rect.top - labelHeight - 4, priority: 1 },
|
|
64
|
+
{ x: rect.left, y: rect.bottom + 4, priority: 2 },
|
|
65
|
+
{
|
|
66
|
+
x: rect.right - labelWidth,
|
|
67
|
+
y: rect.top - labelHeight - 4,
|
|
68
|
+
priority: 3,
|
|
69
|
+
},
|
|
70
|
+
{ x: rect.right - labelWidth, y: rect.bottom + 4, priority: 4 },
|
|
71
|
+
{
|
|
72
|
+
x: rect.left + rect.width / 2 - labelWidth / 2,
|
|
73
|
+
y: rect.top - labelHeight - 4,
|
|
74
|
+
priority: 5,
|
|
75
|
+
},
|
|
76
|
+
{ x: rect.left - labelWidth - 4, y: rect.top, priority: 6 },
|
|
77
|
+
{ x: rect.right + 4, y: rect.top, priority: 7 },
|
|
78
|
+
{
|
|
79
|
+
x: rect.left,
|
|
80
|
+
y: rect.top + rect.height / 2 - labelHeight / 2,
|
|
81
|
+
priority: 8,
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
positions.sort((a, b) => a.priority - b.priority);
|
|
86
|
+
|
|
87
|
+
for (const pos of positions) {
|
|
88
|
+
const labelBounds = {
|
|
89
|
+
left: pos.x,
|
|
90
|
+
right: pos.x + labelWidth,
|
|
91
|
+
top: pos.y,
|
|
92
|
+
bottom: pos.y + labelHeight,
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
if (labelBounds.top >= 0 && labelBounds.left >= 0) {
|
|
96
|
+
if (!checkOverlap(labelBounds, existingLabels)) {
|
|
97
|
+
return { x: pos.x, y: pos.y };
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return { x: rect.left, y: Math.max(0, rect.top - labelHeight - 4) };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let colorIndex = 0;
|
|
106
|
+
let drawnCount = 0;
|
|
107
|
+
|
|
108
|
+
for (const [uuid, xpath] of Object.entries(uuidXpathMap)) {
|
|
109
|
+
try {
|
|
110
|
+
const result = document.evaluate(
|
|
111
|
+
xpath,
|
|
112
|
+
document,
|
|
113
|
+
null,
|
|
114
|
+
XPathResult.FIRST_ORDERED_NODE_TYPE,
|
|
115
|
+
null,
|
|
116
|
+
);
|
|
117
|
+
const element = result.singleNodeValue;
|
|
118
|
+
|
|
119
|
+
if (!element) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const rect = element.getBoundingClientRect();
|
|
124
|
+
|
|
125
|
+
if (rect.width === 0 || rect.height === 0) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const color = colors[colorIndex % colors.length];
|
|
130
|
+
colorIndex++;
|
|
131
|
+
|
|
132
|
+
const group = document.createElementNS(svgNS, "g");
|
|
133
|
+
|
|
134
|
+
const box = document.createElementNS(svgNS, "rect");
|
|
135
|
+
box.setAttribute("x", rect.left);
|
|
136
|
+
box.setAttribute("y", rect.top);
|
|
137
|
+
box.setAttribute("width", rect.width);
|
|
138
|
+
box.setAttribute("height", rect.height);
|
|
139
|
+
box.setAttribute("fill", "none");
|
|
140
|
+
box.setAttribute("stroke", color);
|
|
141
|
+
box.setAttribute("stroke-width", "3");
|
|
142
|
+
box.setAttribute("stroke-dasharray", "5,5");
|
|
143
|
+
box.setAttribute("rx", "4");
|
|
144
|
+
|
|
145
|
+
const labelWidth = uuid.length * (fontSize * 0.6) + labelPadding * 2;
|
|
146
|
+
const labelPos = findBestLabelPosition(
|
|
147
|
+
rect,
|
|
148
|
+
labelWidth,
|
|
149
|
+
occupiedSpaces,
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
const labelBg = document.createElementNS(svgNS, "rect");
|
|
153
|
+
labelBg.setAttribute("x", labelPos.x);
|
|
154
|
+
labelBg.setAttribute("y", labelPos.y);
|
|
155
|
+
labelBg.setAttribute("width", labelWidth);
|
|
156
|
+
labelBg.setAttribute("height", labelHeight);
|
|
157
|
+
labelBg.setAttribute("fill", color);
|
|
158
|
+
labelBg.setAttribute("rx", "4");
|
|
159
|
+
|
|
160
|
+
const label = document.createElementNS(svgNS, "text");
|
|
161
|
+
label.setAttribute("x", labelPos.x + labelPadding);
|
|
162
|
+
label.setAttribute("y", labelPos.y + 17);
|
|
163
|
+
label.setAttribute("fill", "#FFFFFF");
|
|
164
|
+
label.setAttribute("font-family", "monospace");
|
|
165
|
+
label.setAttribute("font-size", fontSize);
|
|
166
|
+
label.setAttribute("font-weight", "bold");
|
|
167
|
+
label.textContent = uuid;
|
|
168
|
+
|
|
169
|
+
occupiedSpaces.push({
|
|
170
|
+
left: labelPos.x,
|
|
171
|
+
right: labelPos.x + labelWidth,
|
|
172
|
+
top: labelPos.y,
|
|
173
|
+
bottom: labelPos.y + labelHeight,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
group.appendChild(box);
|
|
177
|
+
group.appendChild(labelBg);
|
|
178
|
+
group.appendChild(label);
|
|
179
|
+
container.appendChild(group);
|
|
180
|
+
|
|
181
|
+
drawnCount++;
|
|
182
|
+
} catch (err) {
|
|
183
|
+
console.warn(`Failed to draw box for UUID ${uuid}:`, err);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
document.body.appendChild(container);
|
|
188
|
+
|
|
189
|
+
return {
|
|
190
|
+
success: true,
|
|
191
|
+
message: `Successfully drew ${drawnCount} element boxes`,
|
|
192
|
+
count: drawnCount,
|
|
193
|
+
};
|
|
194
|
+
} catch (error) {
|
|
195
|
+
return {
|
|
196
|
+
success: false,
|
|
197
|
+
error: error.message,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
}
|
|
@@ -10,6 +10,20 @@
|
|
|
10
10
|
const seenHrefs = new Set();
|
|
11
11
|
const seenElements = new Set();
|
|
12
12
|
|
|
13
|
+
function isInViewport(rect) {
|
|
14
|
+
const viewportWidth =
|
|
15
|
+
window.innerWidth || document.documentElement.clientWidth;
|
|
16
|
+
const viewportHeight =
|
|
17
|
+
window.innerHeight || document.documentElement.clientHeight;
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
rect.top < viewportHeight &&
|
|
21
|
+
rect.bottom > 0 &&
|
|
22
|
+
rect.left < viewportWidth &&
|
|
23
|
+
rect.right > 0
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
13
27
|
// Utility function to check if element is truly visible (including parent chain)
|
|
14
28
|
function isElementVisible(element) {
|
|
15
29
|
if (!element || !element.nodeType === 1) {
|
|
@@ -21,27 +35,24 @@
|
|
|
21
35
|
return false;
|
|
22
36
|
}
|
|
23
37
|
|
|
24
|
-
|
|
25
|
-
|
|
38
|
+
if (
|
|
39
|
+
element.tagName.toLowerCase() === "input" &&
|
|
40
|
+
!element.checkVisibility()
|
|
41
|
+
) {
|
|
42
|
+
//go up to parent if input is not visible
|
|
43
|
+
return element.parentElement.checkVisibility();
|
|
44
|
+
}
|
|
26
45
|
|
|
27
|
-
if (
|
|
46
|
+
if (!element.checkVisibility()) {
|
|
28
47
|
return false;
|
|
29
48
|
}
|
|
30
49
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
// Check if current element is hidden
|
|
39
|
-
if (style.display === "none" || style.visibility === "hidden") {
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Move to parent element
|
|
44
|
-
currentElement = currentElement.parentElement;
|
|
50
|
+
bounding_box = element.getBoundingClientRect();
|
|
51
|
+
if (!isInViewport(bounding_box)) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
if (bounding_box.width <= 1 && bounding_box.height <= 1) {
|
|
55
|
+
return false;
|
|
45
56
|
}
|
|
46
57
|
|
|
47
58
|
return true;
|
|
@@ -80,6 +91,8 @@
|
|
|
80
91
|
'input[type="button"]',
|
|
81
92
|
'input[type="submit"]',
|
|
82
93
|
'input[type="reset"]',
|
|
94
|
+
'input[type="checkbox"]',
|
|
95
|
+
'input[type="radio"]',
|
|
83
96
|
"[onclick]", // Elements with onclick handlers
|
|
84
97
|
'[role="button"]', // ARIA buttons
|
|
85
98
|
"[tabindex]", // Focusable elements
|
|
@@ -101,7 +114,14 @@
|
|
|
101
114
|
const href = element.href || element.getAttribute("href") || "";
|
|
102
115
|
|
|
103
116
|
// Generate XPath
|
|
104
|
-
|
|
117
|
+
let xpath = getXPath(element);
|
|
118
|
+
|
|
119
|
+
if (
|
|
120
|
+
element.tagName.toLowerCase() === "input" &&
|
|
121
|
+
!element.checkVisibility()
|
|
122
|
+
) {
|
|
123
|
+
xpath = getXPath(element.parentElement);
|
|
124
|
+
}
|
|
105
125
|
|
|
106
126
|
// Get display text
|
|
107
127
|
let displayText = element.getAttribute("aria-label");
|
|
@@ -119,7 +139,7 @@
|
|
|
119
139
|
altTexts.push(label);
|
|
120
140
|
}
|
|
121
141
|
});
|
|
122
|
-
if (altTexts.length > 0 &&
|
|
142
|
+
if (altTexts.length > 0 && displayText) {
|
|
123
143
|
displayText = altTexts.join(", ");
|
|
124
144
|
}
|
|
125
145
|
}
|
|
@@ -133,13 +153,26 @@
|
|
|
133
153
|
if (!displayText) {
|
|
134
154
|
displayText = element.title || "";
|
|
135
155
|
}
|
|
156
|
+
}
|
|
136
157
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
158
|
+
let elementType = element.tagName.toLowerCase();
|
|
159
|
+
if (elementType === "input") {
|
|
160
|
+
elementType = element.type;
|
|
161
|
+
if (element.type === "checkbox" || element.type === "radio") {
|
|
162
|
+
elementType =
|
|
163
|
+
element.type + "_" + element.name + "[" + element.value + "]";
|
|
164
|
+
let parent = element.parentElement;
|
|
165
|
+
while (!displayText) {
|
|
166
|
+
displayText = parent.textContent || "";
|
|
167
|
+
parent = parent.parentElement;
|
|
168
|
+
}
|
|
140
169
|
}
|
|
141
170
|
}
|
|
142
171
|
|
|
172
|
+
// Limit text length
|
|
173
|
+
if (displayText.length > 50) {
|
|
174
|
+
displayText = displayText.substring(0, 50) + "...";
|
|
175
|
+
}
|
|
143
176
|
// Only add if we have some meaningful content
|
|
144
177
|
if (displayText || xpath) {
|
|
145
178
|
// Deduplication logic
|
|
@@ -154,10 +187,11 @@
|
|
|
154
187
|
}
|
|
155
188
|
} else {
|
|
156
189
|
// For elements without href, deduplicate by tagName + text combination
|
|
157
|
-
const elementKey =
|
|
190
|
+
const elementKey = elementType.toLowerCase() + "|" + displayText;
|
|
158
191
|
if (!seenElements.has(elementKey)) {
|
|
159
192
|
seenElements.add(elementKey);
|
|
160
193
|
clickableElements.push({
|
|
194
|
+
type: elementType,
|
|
161
195
|
xpath: xpath,
|
|
162
196
|
text: displayText,
|
|
163
197
|
});
|
|
@@ -8,33 +8,36 @@
|
|
|
8
8
|
function extractElementsByText(text) {
|
|
9
9
|
const elementsFound = [];
|
|
10
10
|
|
|
11
|
+
function isInViewport(rect) {
|
|
12
|
+
const viewportWidth =
|
|
13
|
+
window.innerWidth || document.documentElement.clientWidth;
|
|
14
|
+
const viewportHeight =
|
|
15
|
+
window.innerHeight || document.documentElement.clientHeight;
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
rect.top < viewportHeight &&
|
|
19
|
+
rect.bottom > 0 &&
|
|
20
|
+
rect.left < viewportWidth &&
|
|
21
|
+
rect.right > 0
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
11
25
|
// Utility function to check if element is truly visible (including parent chain)
|
|
12
26
|
function isElementVisible(element) {
|
|
13
27
|
if (!element || !element.nodeType === 1) {
|
|
14
28
|
return false;
|
|
15
29
|
}
|
|
16
30
|
|
|
17
|
-
|
|
18
|
-
let currentElement = element;
|
|
19
|
-
|
|
20
|
-
if (currentElement.clientWidth <= 1 && currentElement.clientHeight <= 1) {
|
|
31
|
+
if (!element.checkVisibility()) {
|
|
21
32
|
return false;
|
|
22
33
|
}
|
|
23
34
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
// Check if current element is hidden
|
|
32
|
-
if (style.display === "none" || style.visibility === "hidden") {
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Move to parent element
|
|
37
|
-
currentElement = currentElement.parentElement;
|
|
35
|
+
bounding_box = element.getBoundingClientRect();
|
|
36
|
+
if (!isInViewport(bounding_box)) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
if (bounding_box.width <= 1 && bounding_box.height <= 1) {
|
|
40
|
+
return false;
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
return true;
|
|
@@ -120,4 +123,3 @@ function extractElementsByText(text) {
|
|
|
120
123
|
// const text = '{TEXT_PLACEHOLDER}';
|
|
121
124
|
// return extractElementsByText(text);
|
|
122
125
|
// })();
|
|
123
|
-
|
|
@@ -8,33 +8,36 @@
|
|
|
8
8
|
const inputElements = [];
|
|
9
9
|
const seenElements = new Set();
|
|
10
10
|
|
|
11
|
+
function isInViewport(rect) {
|
|
12
|
+
const viewportWidth =
|
|
13
|
+
window.innerWidth || document.documentElement.clientWidth;
|
|
14
|
+
const viewportHeight =
|
|
15
|
+
window.innerHeight || document.documentElement.clientHeight;
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
rect.top < viewportHeight &&
|
|
19
|
+
rect.bottom > 0 &&
|
|
20
|
+
rect.left < viewportWidth &&
|
|
21
|
+
rect.right > 0
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
11
25
|
// Utility function to check if element is truly visible (including parent chain)
|
|
12
26
|
function isElementVisible(element) {
|
|
13
27
|
if (!element || !element.nodeType === 1) {
|
|
14
28
|
return false;
|
|
15
29
|
}
|
|
16
30
|
|
|
17
|
-
|
|
18
|
-
let currentElement = element;
|
|
19
|
-
|
|
20
|
-
if (currentElement.clientWidth <= 1 && currentElement.clientHeight <= 1) {
|
|
31
|
+
if (!element.checkVisibility()) {
|
|
21
32
|
return false;
|
|
22
33
|
}
|
|
23
34
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
// Check if current element is hidden
|
|
32
|
-
if (style.display === "none" || style.visibility === "hidden") {
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Move to parent element
|
|
37
|
-
currentElement = currentElement.parentElement;
|
|
35
|
+
bounding_box = element.getBoundingClientRect();
|
|
36
|
+
if (!isInViewport(bounding_box)) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
if (bounding_box.width <= 1 && bounding_box.height <= 1) {
|
|
40
|
+
return false;
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
return true;
|
|
@@ -113,8 +116,6 @@
|
|
|
113
116
|
'input[type="email"]',
|
|
114
117
|
'input[type="password"]',
|
|
115
118
|
'input[type="number"]',
|
|
116
|
-
'input[type="checkbox"]',
|
|
117
|
-
'input[type="radio"]',
|
|
118
119
|
'input[type="tel"]',
|
|
119
120
|
'input[type="url"]',
|
|
120
121
|
'input[type="search"]',
|
|
@@ -198,9 +199,7 @@
|
|
|
198
199
|
|
|
199
200
|
// Get current value
|
|
200
201
|
let elementValue = "";
|
|
201
|
-
if (elementType === "
|
|
202
|
-
elementValue = element.checked ? "checked" : "unchecked";
|
|
203
|
-
} else if (elementType === "select") {
|
|
202
|
+
if (elementType === "select") {
|
|
204
203
|
elementValue = element.value || "";
|
|
205
204
|
// Also show selected text for better understanding
|
|
206
205
|
if (element.selectedOptions && element.selectedOptions.length > 0) {
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
function filterHiddenElements() {
|
|
2
|
+
try {
|
|
3
|
+
function isElementHidden(element) {
|
|
4
|
+
if (element.nodeType !== Node.ELEMENT_NODE) {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const tagName = element.tagName.toLowerCase();
|
|
9
|
+
if (
|
|
10
|
+
tagName === "script" ||
|
|
11
|
+
tagName === "style" ||
|
|
12
|
+
tagName === "noscript"
|
|
13
|
+
) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const computedStyle = window.getComputedStyle(element);
|
|
18
|
+
|
|
19
|
+
if (
|
|
20
|
+
computedStyle.display === "none" ||
|
|
21
|
+
computedStyle.visibility === "hidden" ||
|
|
22
|
+
computedStyle.opacity === "0"
|
|
23
|
+
) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const ariaHidden = element.getAttribute("aria-hidden");
|
|
28
|
+
if (ariaHidden === "true") {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function removeHiddenElementsFromNode(node) {
|
|
36
|
+
if (!node || node.nodeType !== Node.ELEMENT_NODE) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const children = Array.from(node.children);
|
|
41
|
+
|
|
42
|
+
for (const child of children) {
|
|
43
|
+
const originalElement = document.querySelector(
|
|
44
|
+
`[ag-data-temp-id="${child.getAttribute("ag-data-temp-id")}"]`,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
if (!originalElement) {
|
|
48
|
+
child.remove();
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (isElementHidden(originalElement)) {
|
|
53
|
+
child.remove();
|
|
54
|
+
} else {
|
|
55
|
+
removeHiddenElementsFromNode(child);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function addTempIds(node, prefix = "") {
|
|
61
|
+
if (!node || node.nodeType !== Node.ELEMENT_NODE) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const children = Array.from(node.children);
|
|
66
|
+
children.forEach((child, index) => {
|
|
67
|
+
const tempId = `${prefix}${index}`;
|
|
68
|
+
child.setAttribute("ag-data-temp-id", tempId);
|
|
69
|
+
addTempIds(child, `${tempId}-`);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function removeTempIds(node) {
|
|
74
|
+
if (!node || node.nodeType !== Node.ELEMENT_NODE) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
node.removeAttribute("ag-data-temp-id");
|
|
79
|
+
Array.from(node.children).forEach((child) => removeTempIds(child));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
addTempIds(document.documentElement);
|
|
83
|
+
const documentClone = document.documentElement.cloneNode(true);
|
|
84
|
+
|
|
85
|
+
removeHiddenElementsFromNode(documentClone);
|
|
86
|
+
|
|
87
|
+
removeTempIds(document.documentElement);
|
|
88
|
+
removeTempIds(documentClone);
|
|
89
|
+
|
|
90
|
+
const filteredHTML = documentClone.outerHTML;
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
success: true,
|
|
94
|
+
html: filteredHTML,
|
|
95
|
+
message: "Successfully filtered hidden elements using computed styles",
|
|
96
|
+
};
|
|
97
|
+
} catch (error) {
|
|
98
|
+
return {
|
|
99
|
+
success: false,
|
|
100
|
+
error: error.message,
|
|
101
|
+
stack: error.stack,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remove the overlay container with element boxes
|
|
3
|
+
*
|
|
4
|
+
* @returns {Object} Result object with success status and message
|
|
5
|
+
*/
|
|
6
|
+
function removeElementBoxes() {
|
|
7
|
+
try {
|
|
8
|
+
const container = document.getElementById('agentcrew-element-overlay-container');
|
|
9
|
+
|
|
10
|
+
if (!container) {
|
|
11
|
+
return {
|
|
12
|
+
success: true,
|
|
13
|
+
message: 'No overlay container found (already removed or never created)'
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
container.remove();
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
success: true,
|
|
21
|
+
message: 'Successfully removed element boxes overlay'
|
|
22
|
+
};
|
|
23
|
+
} catch (error) {
|
|
24
|
+
return {
|
|
25
|
+
success: false,
|
|
26
|
+
error: error.message
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|