agentcrew-ai 0.8.2__py3-none-any.whl → 0.8.4__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 (47) hide show
  1. AgentCrew/__init__.py +1 -1
  2. AgentCrew/main.py +3 -1
  3. AgentCrew/modules/a2a/agent_cards.py +8 -2
  4. AgentCrew/modules/a2a/errors.py +72 -0
  5. AgentCrew/modules/a2a/server.py +21 -2
  6. AgentCrew/modules/a2a/task_manager.py +180 -39
  7. AgentCrew/modules/agents/local_agent.py +11 -0
  8. AgentCrew/modules/browser_automation/element_extractor.py +4 -3
  9. AgentCrew/modules/browser_automation/js/draw_element_boxes.js +200 -0
  10. AgentCrew/modules/browser_automation/js/extract_clickable_elements.js +58 -26
  11. AgentCrew/modules/browser_automation/js/extract_elements_by_text.js +21 -19
  12. AgentCrew/modules/browser_automation/js/extract_input_elements.js +22 -23
  13. AgentCrew/modules/browser_automation/js/filter_hidden_elements.js +104 -0
  14. AgentCrew/modules/browser_automation/js/remove_element_boxes.js +29 -0
  15. AgentCrew/modules/browser_automation/js_loader.py +385 -92
  16. AgentCrew/modules/browser_automation/service.py +118 -347
  17. AgentCrew/modules/browser_automation/tool.py +28 -29
  18. AgentCrew/modules/chat/message/command_processor.py +7 -1
  19. AgentCrew/modules/chat/message/conversation.py +9 -8
  20. AgentCrew/modules/code_analysis/service.py +39 -0
  21. AgentCrew/modules/code_analysis/tool.py +10 -1
  22. AgentCrew/modules/console/command_handlers.py +186 -1
  23. AgentCrew/modules/console/completers.py +67 -0
  24. AgentCrew/modules/console/console_ui.py +59 -5
  25. AgentCrew/modules/console/display_handlers.py +12 -0
  26. AgentCrew/modules/console/input_handler.py +2 -0
  27. AgentCrew/modules/console/ui_effects.py +3 -4
  28. AgentCrew/modules/custom_llm/service.py +25 -3
  29. AgentCrew/modules/file_editing/tool.py +9 -11
  30. AgentCrew/modules/google/native_service.py +13 -0
  31. AgentCrew/modules/gui/widgets/message_bubble.py +1 -6
  32. AgentCrew/modules/llm/constants.py +38 -1
  33. AgentCrew/modules/llm/model_registry.py +9 -0
  34. AgentCrew/modules/llm/types.py +12 -1
  35. AgentCrew/modules/memory/base_service.py +2 -2
  36. AgentCrew/modules/memory/chroma_service.py +79 -138
  37. AgentCrew/modules/memory/context_persistent.py +10 -4
  38. AgentCrew/modules/memory/tool.py +17 -18
  39. AgentCrew/modules/openai/response_service.py +19 -11
  40. AgentCrew/modules/openai/service.py +15 -0
  41. AgentCrew/modules/prompts/constants.py +27 -14
  42. {agentcrew_ai-0.8.2.dist-info → agentcrew_ai-0.8.4.dist-info}/METADATA +3 -3
  43. {agentcrew_ai-0.8.2.dist-info → agentcrew_ai-0.8.4.dist-info}/RECORD +47 -43
  44. {agentcrew_ai-0.8.2.dist-info → agentcrew_ai-0.8.4.dist-info}/WHEEL +0 -0
  45. {agentcrew_ai-0.8.2.dist-info → agentcrew_ai-0.8.4.dist-info}/entry_points.txt +0 -0
  46. {agentcrew_ai-0.8.2.dist-info → agentcrew_ai-0.8.4.dist-info}/licenses/LICENSE +0 -0
  47. {agentcrew_ai-0.8.2.dist-info → agentcrew_ai-0.8.4.dist-info}/top_level.txt +0 -0
@@ -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
@@ -153,11 +186,10 @@
153
186
  });
154
187
  }
155
188
  } else {
156
- // For elements without href, deduplicate by tagName + text combination
157
- const elementKey = element.tagName.toLowerCase() + "|" + displayText;
158
- if (!seenElements.has(elementKey)) {
159
- seenElements.add(elementKey);
189
+ if (!seenElements.has(xpath)) {
190
+ seenElements.add(xpath);
160
191
  clickableElements.push({
192
+ type: elementType,
161
193
  xpath: xpath,
162
194
  text: displayText,
163
195
  });
@@ -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
+ }