Skip to content

Commit 63a01b2

Browse files
author
Shriyansh Agnihotri
committed
Merge branch 'main' into experimental-1
2 parents 8149272 + 1f16781 commit 63a01b2

File tree

4 files changed

+48
-32
lines changed

4 files changed

+48
-32
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ After passing all the required parameters, the command to run Hercules should lo
110110
testzeus-hercules --input-file opt/input/test.feature --output-path opt/output --test-data-path opt/test_data --llm-model gpt-4o --llm-model-api-key sk-proj-k.......
111111
```
112112

113+
113114
#### Supported AI Models for TestZeus-Hercules
114115
- Anthropic Haiku: Compatible with Haiku 3.5 and above.
115116
- Groq: Supports any version with function calling and coding capabilities.
@@ -328,6 +329,9 @@ To configure Hercules in detail:
328329
- `TAKE_SCREENSHOTS=false`
329330
- `BROWSER_TYPE=chromium` (options: `firefox`, `chromium`)
330331
- `CAPTURE_NETWORK=false`
332+
333+
For example: If you would like to run with a "Headful" browser, you can set the environment variable with ```export HEADLESS=false``` before triggering Hercules.
334+
331335

332336
### Understanding `agents_llm_config-example.json`
333337

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "testzeus-hercules"
3-
version = "0.0.7"
3+
version = "0.0.8"
44
description = "Hercules: The World's First Open-Source AI Agent for End-to-End Testing"
55
authors = ["Shriyansh Agnihotri <shriyansh@testzeus.com>"]
66
readme = "README.md"

testzeus_hercules/core/memory/prompt_compressor.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
from autogen.agentchat.contrib.capabilities.transforms import TextMessageCompressor
55
from testzeus_hercules.utils.logger import logger
66

7-
TEXT_COMPRESSOR_LLM = LLMLingua()
8-
TEXT_COMPRESSOR = TextMessageCompressor(text_compressor=TEXT_COMPRESSOR_LLM)
7+
# TEXT_COMPRESSOR_LLM = LLMLingua()
8+
# TEXT_COMPRESSOR = TextMessageCompressor(text_compressor=TEXT_COMPRESSOR_LLM)
99

1010

1111
def add_text_compressor(agent: ConversableAgent) -> None:
@@ -14,6 +14,10 @@ def add_text_compressor(agent: ConversableAgent) -> None:
1414
Args:
1515
agent (ConversableAgent): The agent that needs text compression in prompts
1616
"""
17-
context_handling = transform_messages.TransformMessages(transforms=[TEXT_COMPRESSOR])
17+
return
18+
# removed the text compressor as its making the prompt lossy and causing lots of halucination.
19+
context_handling = transform_messages.TransformMessages(
20+
transforms=[TEXT_COMPRESSOR]
21+
)
1822
context_handling.add_to_agent(agent)
1923
logger.debug(f"Added text compressor to agent: {agent.name}")

testzeus_hercules/core/tools/enter_text_using_selector.py

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,9 @@ async def custom_fill_element(page: Page, selector: str, text_to_enter: str):
125125
)
126126
logger.debug(f"custom_fill_element result: {result}")
127127
except Exception as e:
128-
logger.error(f"Error in custom_fill_element, Selector: {selector}, Text: {text_to_enter}. Error: {str(e)}")
128+
logger.error(
129+
f"Error in custom_fill_element, Selector: {selector}, Text: {text_to_enter}. Error: {str(e)}"
130+
)
129131
raise
130132

131133

@@ -249,18 +251,24 @@ def detect_dom_changes(changes: str): # type: ignore
249251
)
250252

251253
result = await do_entertext(page, query_selector, text_to_enter)
252-
await asyncio.sleep(0.1) # sleep for 100ms to allow the mutation observer to detect changes
254+
await asyncio.sleep(
255+
0.1
256+
) # sleep for 100ms to allow the mutation observer to detect changes
253257
unsubscribe(detect_dom_changes)
254258

255259
await browser_manager.take_screenshots(f"{function_name}_end", page)
256260

257-
await browser_manager.notify_user(result["summary_message"], message_type=MessageType.ACTION)
261+
await browser_manager.notify_user(
262+
result["summary_message"], message_type=MessageType.ACTION
263+
)
258264
if dom_changes_detected:
259265
return f"{result['detailed_message']}.\n As a consequence of this action, new elements have appeared in view: {dom_changes_detected}. This means that the action of entering text {text_to_enter} is not yet executed and needs further interaction. Get all_fields DOM to complete the interaction."
260266
return result["detailed_message"]
261267

262268

263-
async def do_entertext(page: Page, selector: str, text_to_enter: str, use_keyboard_fill: bool = True):
269+
async def do_entertext(
270+
page: Page, selector: str, text_to_enter: str, use_keyboard_fill: bool = True
271+
):
264272
"""
265273
Performs the text entry operation on a DOM or Shadow DOM element.
266274
@@ -359,18 +367,20 @@ async def find_element_in_shadow_dom(page: Page, selector: str):
359367

360368
if use_keyboard_fill:
361369
await elem.focus()
362-
await asyncio.sleep(0.1)
370+
await asyncio.sleep(0.05)
363371
await press_key_combination("Control+A")
364-
await asyncio.sleep(0.1)
365-
await press_key_combination("Backspace")
366-
await asyncio.sleep(0.1)
372+
await asyncio.sleep(0.05)
373+
await press_key_combination("Delete")
374+
await asyncio.sleep(0.05)
367375
logger.debug(f"Focused element with selector {selector} to enter text")
368376
await page.keyboard.type(text_to_enter, delay=1)
369377
else:
370378
await custom_fill_element(page, selector, text_to_enter)
371379

372380
await elem.focus()
373-
logger.info(f'Success. Text "{text_to_enter}" set successfully in the element with selector {selector}')
381+
logger.info(
382+
f'Success. Text "{text_to_enter}" set successfully in the element with selector {selector}'
383+
)
374384
success_msg = f'Success. Text "{text_to_enter}" set successfully in the element with selector {selector}'
375385
return {
376386
"summary_message": success_msg,
@@ -385,46 +395,44 @@ async def find_element_in_shadow_dom(page: Page, selector: str):
385395

386396
async def bulk_enter_text(
387397
entries: Annotated[
388-
List[dict[str, str]],
389-
"List of objects, each containing 'query_selector' and 'text'.",
398+
List[EnterTextEntry],
399+
"List of EnterTextEntry objects. An object containing 'query_selector' (DOM selector query using mmid attribute e.g. [mmid='114']) and 'text' (text to enter on the element).",
390400
] # noqa: UP006
391401
) -> Annotated[
392-
List[dict[str, str]],
393-
"List of dictionaries, each containing 'query_selector' and the result of the operation.",
402+
List[str],
403+
"List of results from the entertext operation for each entry.",
394404
]: # noqa: UP006
395405
"""
396406
Enters text into multiple DOM elements using a bulk operation.
397407
398408
This function enters text into multiple DOM elements using a bulk operation.
399-
It takes a list of dictionaries, where each dictionary contains a 'query_selector' and 'text' pair.
409+
It takes a list of EnterTextEntry objects, where each contains 'query_selector' and 'text' attributes.
400410
The function internally calls the 'entertext' function to perform the text entry operation for each entry.
401411
402412
Args:
403-
entries: List of objects, each containing 'query_selector' and 'text'.
413+
entries: List of EnterTextEntry objects.
404414
405415
Returns:
406-
List of dictionaries, each containing 'query_selector' and the result of the operation.
416+
List of results from the entertext operation for each entry.
407417
408418
Example:
409419
entries = [
410-
{"query_selector": "#username", "text": "test_user"},
411-
{"query_selector": "#password", "text": "test_password"}
420+
EnterTextEntry(query_selector="#username", text="test_user"),
421+
EnterTextEntry(query_selector="#password", text="test_password")
412422
]
413423
results = await bulk_enter_text(entries)
414424
415425
Note:
416-
- Each entry in the 'entries' list should be a dictionary with 'query_selector' and 'text' keys.
417-
- The result is a list of dictionaries, where each dictionary contains the 'query_selector' and the result of the operation.
426+
- Each entry in the 'entries' list should be an instance of EnterTextEntry.
427+
- The result is a list of strings returned by the 'entertext' function for each entry.
418428
"""
419429
add_event(EventType.INTERACTION, EventData(detail="bulk_enter_text"))
420-
results: List[dict[str, str]] = [] # noqa: UP006
430+
results: List[str] = [] # noqa: UP006
421431
logger.info("Executing bulk Enter Text Command")
422432
for entry in entries:
423-
query_selector = entry["query_selector"]
424-
text_to_enter = entry["text"]
425-
logger.info(f"Entering text: {text_to_enter} in element with selector: {query_selector}")
426-
result = await entertext(EnterTextEntry(query_selector=query_selector, text=text_to_enter))
427-
428-
results.append({"query_selector": query_selector, "result": result})
429-
433+
logger.info(
434+
f"Entering text: {entry['text']} in element with selector: {entry['query_selector']}"
435+
)
436+
result = await entertext(entry)
437+
results.append(result)
430438
return results

0 commit comments

Comments
 (0)