diff --git a/sources/agents/browser_agent.py b/sources/agents/browser_agent.py
index b0a9e87..1c3cf94 100644
--- a/sources/agents/browser_agent.py
+++ b/sources/agents/browser_agent.py
@@ -54,7 +54,7 @@ class BrowserAgent(Agent):
links_clean = []
for link in links:
link = link.strip()
- if link[-1] == '.':
+ if not (link[-1].isalpha() or link[-1].isdigit()):
links_clean.append(link[:-1])
else:
links_clean.append(link)
@@ -71,7 +71,7 @@ class BrowserAgent(Agent):
Your goal is to find accurate and complete information to satisfy the user’s request.
User request: {user_prompt}
To proceed, choose a relevant link from the search results. Announce your choice by saying: "I want to navigate to "
- Do not explain your choice.
+ Do not eplain your choice.
"""
def make_navigation_prompt(self, user_prompt: str, page_text: str) -> str:
@@ -120,22 +120,27 @@ class BrowserAgent(Agent):
Example 1 (useful page, no need go futher):
Note: According to karpathy site () LeCun net is ......"
- No link seem useful to provide futher information. GO_BACK
+ No link seem useful to provide futher information.
+ Action: GO_BACK
Example 2 (not useful, see useful link on page):
Error: reddit.com/welcome does not discuss anything related to the user’s query.
- There is a link that could lead to the information, I want to navigate to http://reddit.com/r/locallama
+ There is a link that could lead to the information.
+ Action: navigate to http://reddit.com/r/locallama
Example 3 (not useful, no related links):
Error: x.com does not discuss anything related to the user’s query and no navigation link are usefull.
- GO_BACK
+ Action: GO_BACK
Example 3 (query answer found, enought notes taken):
Note: I found on that ......
- Given this answer the user query I should exit the web browser. REQUEST_EXIT
+ Given this answer the user query I should exit the web browser.
+ Action: REQUEST_EXIT
Example 4 (loging form visible):
+
Note: I am on the login page, I will type the given username and password.
+ Action:
[username_field](David)
[password_field](edgerunners77)
@@ -143,7 +148,7 @@ class BrowserAgent(Agent):
{user_prompt}
You previously took these notes:
{notes}
- Do not Step-by-Step explanation. Instead write simple explanation sentence following by your notes and actions.
+ Do not Step-by-Step explanation. Write Notes or Error as a long paragraph followed by your action.
"""
def llm_decide(self, prompt: str, show_reasoning: bool = False) -> Tuple[str, str]:
@@ -190,7 +195,7 @@ class BrowserAgent(Agent):
buffer = []
links = []
for line in lines:
- if "exit" in line:
+ if line == '' or 'action:' in line.lower():
saving = False
if "note" in line.lower():
saving = True
@@ -198,7 +203,7 @@ class BrowserAgent(Agent):
buffer.append(line)
else:
links.extend(self.extract_links(line))
- self.notes.append('. '.join(buffer))
+ self.notes.append('. '.join(buffer).strip())
return links
def select_link(self, links: List[str]) -> str | None:
@@ -293,6 +298,7 @@ class BrowserAgent(Agent):
extracted_form = self.extract_form(answer)
if len(extracted_form) > 0:
+ pretty_print(f"Filling inputs form...", color="status")
self.browser.fill_form_inputs(extracted_form)
self.browser.find_and_click_submission()
page_text = self.browser.get_text()
@@ -303,22 +309,25 @@ class BrowserAgent(Agent):
link = self.select_link(links)
if "REQUEST_EXIT" in answer:
+ pretty_print(f"Agent requested exit.", color="status")
complete = True
break
if len(unvisited) == 0:
+ pretty_print(f"Visited all links.", color="status")
break
if "FORM_FILLED" in answer:
+ pretty_print(f"Filled form. Handling page update.", color="status")
page_text = self.browser.get_text()
self.navigable_links = self.browser.get_navigable()
prompt = self.make_navigation_prompt(user_prompt, page_text)
continue
if link == None or "GO_BACK" in answer:
+ pretty_print(f"Going back to results. Still {len(unvisited)}", color="status")
unvisited = self.select_unvisited(search_result)
prompt = self.make_newsearch_prompt(user_prompt, unvisited)
- pretty_print(f"Going back to results. Still {len(unvisited)}", color="warning")
continue
animate_thinking(f"Navigating to {link}", color="status")
@@ -329,8 +338,8 @@ class BrowserAgent(Agent):
page_text = self.browser.get_text()
self.navigable_links = self.browser.get_navigable()
prompt = self.make_navigation_prompt(user_prompt, page_text)
- pretty_print(f"Current page: {self.current_page}", color="warning")
+ pretty_print("Exited navigation, starting to summarize finding...", color="status")
prompt = self.conclude_prompt(user_prompt)
mem_last_idx = self.memory.push('user', prompt)
answer, reasoning = self.llm_request()
diff --git a/sources/tools/searxSearch.py b/sources/tools/searxSearch.py
index e0df8e0..83a6203 100644
--- a/sources/tools/searxSearch.py
+++ b/sources/tools/searxSearch.py
@@ -54,7 +54,7 @@ class searxSearch(Tools):
status = self.link_valid(link)
statuses.append(status)
return statuses
-
+
def execute(self, blocks: list, safety: bool = False) -> str:
"""Executes a search query against a SearxNG instance using POST and extracts URLs and titles."""
if not blocks:
diff --git a/sources/tools/tools.py b/sources/tools/tools.py
index 339992c..397fb8b 100644
--- a/sources/tools/tools.py
+++ b/sources/tools/tools.py
@@ -2,11 +2,13 @@
"""
define a generic tool class, any tool can be used by the agent.
-A tool can be used by deepseek like so:
+A tool can be used by a llm like so:
```
```
+we call these "blocks".
+
For example:
```python
print("Hello world")
@@ -40,9 +42,7 @@ class Tools():
return self.current_dir
def check_config_dir_validity(self):
- """
- Check if the config directory is valid.
- """
+ """Check if the config directory is valid."""
path = self.config['MAIN']['work_dir']
if path == "":
print("WARNING: Work directory not set in config.ini")
@@ -56,15 +56,11 @@ class Tools():
return True
def config_exists(self):
- """
- Check if the config file exists.
- """
+ """Check if the config file exists."""
return os.path.exists('./config.ini')
def create_work_dir(self):
- """
- Create the work directory if it does not exist.
- """
+ """Create the work directory if it does not exist."""
default_path = os.path.dirname(os.getcwd())
if self.config_exists():
self.config.read('./config.ini')
diff --git a/tests/test_browser_agent_parsing.py b/tests/test_browser_agent_parsing.py
new file mode 100644
index 0000000..6ec763c
--- /dev/null
+++ b/tests/test_browser_agent_parsing.py
@@ -0,0 +1,69 @@
+import unittest
+import os
+import sys
+sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) # Add project root to Python path
+from sources.agents.browser_agent import BrowserAgent
+
+class TestBrowserAgentParsing(unittest.TestCase):
+ def setUp(self):
+ # Initialize a basic BrowserAgent instance for testing
+ self.agent = BrowserAgent(
+ name="TestAgent",
+ prompt_path="../prompts/base/browser_agent.txt",
+ provider=None
+ )
+
+ def test_extract_links(self):
+ # Test various link formats
+ test_text = """
+ Check this out: https://example.com, and www.google.com!
+ Also try https://test.org/about?page=1.
+ """
+ expected = [
+ "https://example.com",
+ "www.google.com",
+ "https://test.org/about?page=1"
+ ]
+ result = self.agent.extract_links(test_text)
+ self.assertEqual(result, expected)
+
+ def test_extract_form(self):
+ # Test form extraction
+ test_text = """
+ Fill this: [username](john) and [password](secret123)
+ Not a form: [random]text
+ """
+ expected = ["[username](john)", "[password](secret123)"]
+ result = self.agent.extract_form(test_text)
+ self.assertEqual(result, expected)
+
+ def test_clean_links(self):
+ # Test link cleaning
+ test_links = [
+ "https://example.com.",
+ "www.test.com,",
+ "https://clean.org!",
+ "https://good.com"
+ ]
+ expected = [
+ "https://example.com",
+ "www.test.com",
+ "https://clean.org",
+ "https://good.com"
+ ]
+ result = self.agent.clean_links(test_links)
+ self.assertEqual(result, expected)
+
+ def test_parse_answer(self):
+ # Test parsing answer with notes and links
+ test_text = """
+ Here's some info
+ Note: This is important. We are doing test it's very cool.
+ action:
+ i wanna navigate to https://test.com
+ """
+ self.agent.parse_answer(test_text)
+ self.assertEqual(self.agent.notes[0], "Note: This is important. We are doing test it's very cool.")
+
+if __name__ == "__main__":
+ unittest.main()
\ No newline at end of file