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.
Files changed (33) hide show
  1. AgentCrew/__init__.py +1 -1
  2. AgentCrew/modules/agents/local_agent.py +11 -0
  3. AgentCrew/modules/browser_automation/element_extractor.py +4 -3
  4. AgentCrew/modules/browser_automation/js/draw_element_boxes.js +200 -0
  5. AgentCrew/modules/browser_automation/js/extract_clickable_elements.js +57 -23
  6. AgentCrew/modules/browser_automation/js/extract_elements_by_text.js +21 -19
  7. AgentCrew/modules/browser_automation/js/extract_input_elements.js +22 -23
  8. AgentCrew/modules/browser_automation/js/filter_hidden_elements.js +104 -0
  9. AgentCrew/modules/browser_automation/js/remove_element_boxes.js +29 -0
  10. AgentCrew/modules/browser_automation/js_loader.py +385 -92
  11. AgentCrew/modules/browser_automation/service.py +118 -347
  12. AgentCrew/modules/browser_automation/tool.py +28 -29
  13. AgentCrew/modules/chat/message/conversation.py +9 -8
  14. AgentCrew/modules/console/input_handler.py +2 -0
  15. AgentCrew/modules/console/ui_effects.py +3 -4
  16. AgentCrew/modules/custom_llm/service.py +25 -3
  17. AgentCrew/modules/file_editing/tool.py +9 -11
  18. AgentCrew/modules/google/native_service.py +13 -0
  19. AgentCrew/modules/llm/constants.py +38 -1
  20. AgentCrew/modules/llm/model_registry.py +9 -0
  21. AgentCrew/modules/llm/types.py +12 -1
  22. AgentCrew/modules/memory/base_service.py +2 -2
  23. AgentCrew/modules/memory/chroma_service.py +80 -138
  24. AgentCrew/modules/memory/tool.py +15 -15
  25. AgentCrew/modules/openai/response_service.py +19 -11
  26. AgentCrew/modules/openai/service.py +15 -0
  27. AgentCrew/modules/prompts/constants.py +27 -14
  28. {agentcrew_ai-0.8.2.dist-info → agentcrew_ai-0.8.3.dist-info}/METADATA +2 -2
  29. {agentcrew_ai-0.8.2.dist-info → agentcrew_ai-0.8.3.dist-info}/RECORD +33 -30
  30. {agentcrew_ai-0.8.2.dist-info → agentcrew_ai-0.8.3.dist-info}/WHEEL +0 -0
  31. {agentcrew_ai-0.8.2.dist-info → agentcrew_ai-0.8.3.dist-info}/entry_points.txt +0 -0
  32. {agentcrew_ai-0.8.2.dist-info → agentcrew_ai-0.8.3.dist-info}/licenses/LICENSE +0 -0
  33. {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.2"
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("|------|----------|\n")
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
- // Walk up the parent chain checking visibility
25
- let currentElement = element;
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 (currentElement.clientWidth <= 1 && currentElement.clientHeight <= 1) {
46
+ if (!element.checkVisibility()) {
28
47
  return false;
29
48
  }
30
49
 
31
- while (
32
- currentElement &&
33
- currentElement !== document.body &&
34
- currentElement !== document.documentElement
35
- ) {
36
- const style = window.getComputedStyle(currentElement);
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
- const xpath = getXPath(element);
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 && !displayText) {
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
- // Limit text length
138
- if (displayText.length > 50) {
139
- displayText = displayText.substring(0, 50) + "...";
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 = element.tagName.toLowerCase() + "|" + displayText;
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
- // Walk up the parent chain checking visibility
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
- while (
25
- currentElement &&
26
- currentElement !== document.body &&
27
- currentElement !== document.documentElement
28
- ) {
29
- const style = window.getComputedStyle(currentElement);
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
- // Walk up the parent chain checking visibility
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
- while (
25
- currentElement &&
26
- currentElement !== document.body &&
27
- currentElement !== document.documentElement
28
- ) {
29
- const style = window.getComputedStyle(currentElement);
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 === "checkbox" || elementType === "radio") {
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
+ }