mirror of
https://github.com/tcsenpai/agenticSeek.git
synced 2025-06-05 02:25:27 +00:00
Merge pull request #130 from Fosowl/dev
Planner agent improvement, Browser agent stuck prevention, frontend change, readme update + fix
This commit is contained in:
commit
55d5ff39ff
35
README.md
35
README.md
@ -5,44 +5,33 @@
|
||||
--------------------------------------------------------------------------------
|
||||
English | [中文](./README_CHS.md) | [繁體中文](./README_CHT.md) | [Français](./README_FR.md) | [日本語](./README_JP.md)
|
||||
|
||||
# AgenticSeek: Manus-like AI powered by Deepseek R1 Agents.
|
||||
# AgenticSeek: Private, Local Manus Alternative.
|
||||
|
||||
|
||||
**A fully local alternative to Manus AI**, a voice-enabled AI assistant that codes, explores your filesystem, browse the web and correct it's mistakes all without sending a byte of data to the cloud. Built with reasoning models like DeepSeek R1, this autonomous agent runs entirely on your hardware, keeping your data private.
|
||||
*A **100% local alternative to Manus AI**, this voice-enabled AI assistant autonomously browses the web, writes code, and plans tasks while keeping all data on your device. Powered by advanced reasoning models like DeepSeek R1, it runs entirely on your hardware, ensuring complete privacy and zero cloud dependency.*
|
||||
|
||||
[](https://fosowl.github.io/agenticSeek.html)  [](https://discord.gg/XSTKZ8nP) [](https://x.com/Martin993886460)
|
||||
|
||||
> 🛠️ **Work in Progress** – Looking for contributors!
|
||||
[](https://fosowl.github.io/agenticSeek.html)  [](https://discord.gg/m37d7XxZ) [](https://x.com/Martin993886460) [](https://github.com/Fosowl/agenticSeek/stargazers)
|
||||
|
||||
|
||||
> *Plan a 3 days solo trip to Budapest, find me a list of attractions and hostels, save everything in a CSV file*
|
||||
|
||||
https://github.com/user-attachments/assets/4bd5faf6-459f-4f94-bd1d-238c4b331469
|
||||
|
||||
> 🛠️ **Work in Progress** – Looking for contributors!
|
||||
|
||||
> *Do a deep search of AI startup in Osaka and Tokyo, find at least 5, then save in the research_japan.txt file*
|
||||
### *Capabilities*
|
||||
|
||||
> *Can you make a tetris game in C ?*
|
||||
- **100% Local**: *No cloud, runs on your hardware. Your data stays yours.*
|
||||
|
||||
> *I would like to setup a new project file index as mark2.*
|
||||
- **Autonomous Web Browsing**: *Autonomous web navigation.*
|
||||
|
||||
- **Autonomous Coding**: *Can write, debug, and run code in Python, C, Golang, Java...*
|
||||
|
||||
## Features:
|
||||
- **Agent routing**: *Automatically picks the right agent for the job.*
|
||||
|
||||
- **100% Local**: No cloud, runs on your hardware. Your data stays yours.
|
||||
- **Planning**: *For complex tasks, spins up multiple agents to plan and execute.*
|
||||
|
||||
- **Filesystem interaction**: Use bash to navigate and manipulate your files effortlessly.
|
||||
|
||||
- **Autonomous Coding**: Can write, debug, and run code in Python, C, Golang and more languages on the way.
|
||||
|
||||
- **Agent routing**: Automatically picks the right agent for the job.
|
||||
|
||||
- **Planning**: For complex tasks, spins up multiple agents to plan and execute.
|
||||
|
||||
- **Autonomous Web Browsing**: Autonomous web navigation.
|
||||
|
||||
- **Memory**: Efficient memory and sessions management.
|
||||
|
||||
---
|
||||
- **Memory**: *Efficient memory and sessions management.*
|
||||
|
||||
## Installation
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
**Manus AI 的本地替代品**,它是一个具有语音功能的大语言模型秘书,可以 Coding、访问你的电脑文件、浏览网页,并自动修正错误与反省,最重要的是不会向云端传送任何资料。采用 DeepSeek R1 等推理模型构建,完全在本地硬体上运行,进而保证资料的隐私。
|
||||
|
||||
[](https://fosowl.github.io/agenticSeek.html)  [](https://discord.gg/XSTKZ8nP) [](https://x.com/Martin993886460)
|
||||
[](https://fosowl.github.io/agenticSeek.html)  [](https://discord.gg/m37d7XxZ) [](https://x.com/Martin993886460)
|
||||
|
||||
> 🛠️ **目前还在开发阶段** – 欢迎任何贡献者加入我们!
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
**Manus AI 的本地替代品**,它是一個具有語音功能的大語言模型秘書,可以 Coding、訪問你的電腦文件、瀏覽網頁,並自動修正錯誤與反省,最重要的是不會向雲端傳送任何資料。採用 DeepSeek R1 等推理模型構建,完全在本地硬體上運行,進而保證資料的隱私。
|
||||
|
||||
[](https://fosowl.github.io/agenticSeek.html)  [](https://discord.gg/XSTKZ8nP) [](https://x.com/Martin993886460)
|
||||
[](https://fosowl.github.io/agenticSeek.html)  [](https://discord.gg/m37d7XxZ) [](https://x.com/Martin993886460)
|
||||
|
||||
> 🛠️ **目前還在開發階段** – 歡迎任何貢獻者加入我們!
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
Une alternative **entièrement locale** à Manus AI, un assistant IA qui code, explore votre système de fichiers, navigue sur le web et corrige ses erreurs, tout cela sans envoyer la moindre donnée dans le cloud. Cet agent autonome fonctionne entièrement sur votre hardware, garantissant la confidentialité de vos données.
|
||||
|
||||
[](https://fosowl.github.io/agenticSeek.html)  [](https://discord.gg/4Ub2D6Fj) [](https://x.com/Martin993886460)
|
||||
[](https://fosowl.github.io/agenticSeek.html)  [](https://discord.gg/m37d7XxZ) [](https://x.com/Martin993886460)
|
||||
|
||||
> 🛠️ **En cours de développement** – On cherche activement des contributeurs!
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
**Manus AIの完全なローカル代替品**、音声対応のAIアシスタントで、コードを書き、ファイルシステムを探索し、ウェブを閲覧し、ミスを修正し、データをクラウドに送信することなくすべてを行います。DeepSeek R1のような推論モデルを使用して構築されており、この自律エージェントは完全にハードウェア上で動作し、データのプライバシーを保護します。
|
||||
|
||||
[](https://fosowl.github.io/agenticSeek.html)  [](https://discord.gg/XSTKZ8nP) [](https://x.com/Martin993886460)
|
||||
[](https://fosowl.github.io/agenticSeek.html)  [](https://discord.gg/m37d7XxZ) [](https://x.com/Martin993886460)
|
||||
|
||||
> 🛠️ **進行中の作業** – 貢献者を探しています!
|
||||
|
||||
|
@ -73,7 +73,7 @@ body {
|
||||
|
||||
.app-sections {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 16px;
|
||||
height: calc(100vh - 80px);
|
||||
}
|
||||
|
@ -79,6 +79,7 @@ function App() {
|
||||
const res = await axios.get('http://0.0.0.0:8000/latest_answer');
|
||||
const data = res.data;
|
||||
|
||||
updateData(data);
|
||||
if (!data.answer || data.answer.trim() === '') {
|
||||
return;
|
||||
}
|
||||
@ -107,6 +108,17 @@ function App() {
|
||||
}
|
||||
};
|
||||
|
||||
const updateData = (data) => {
|
||||
setResponseData((prev) => ({
|
||||
...prev,
|
||||
blocks: data.blocks || prev.blocks || null,
|
||||
done: data.done,
|
||||
answer: data.answer,
|
||||
agent_name: data.agent_name,
|
||||
status: data.status,
|
||||
uid: data.uid,
|
||||
}));
|
||||
};
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
@ -129,8 +141,7 @@ function App() {
|
||||
setQuery('Enter your query...');
|
||||
console.log('Response:', res.data);
|
||||
const data = res.data;
|
||||
setResponseData(data);
|
||||
fetchLatestAnswer();
|
||||
updateData(data);
|
||||
} catch (err) {
|
||||
console.error('Error:', err);
|
||||
setError('Failed to process query.');
|
||||
@ -147,12 +158,8 @@ function App() {
|
||||
|
||||
const handleGetScreenshot = async () => {
|
||||
try {
|
||||
console.log('Fetching screenshot...');
|
||||
const res = await axios.get('http://0.0.0.0:8000/screenshots/updated_screen.png');
|
||||
setResponseData((prev) => ({ ...prev, screenshot: res.data.screenshot }));
|
||||
setCurrentView('screenshot');
|
||||
} catch (err) {
|
||||
console.error('Error fetching screenshot:', err);
|
||||
setError('Browser not in use');
|
||||
}
|
||||
};
|
||||
@ -164,12 +171,7 @@ function App() {
|
||||
</header>
|
||||
<main className="main">
|
||||
<div className="app-sections">
|
||||
<div className="task-section">
|
||||
<h2>Task</h2>
|
||||
<div className="task-details">
|
||||
<p className="placeholder">No active task. Start a conversation to create a task.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="chat-section">
|
||||
<h2>Chat Interface</h2>
|
||||
|
@ -77,4 +77,5 @@ Rules:
|
||||
- Only use web agent for finding necessary informations.
|
||||
- If a task might require user email (eg: api services), do not write plan instead ask for user email.
|
||||
- Do not search for tutorial.
|
||||
- Make sure json is within ```json tag
|
||||
- Make sure json is within ```json tag
|
||||
- One step, one agent.
|
@ -78,6 +78,10 @@ class Agent():
|
||||
def get_tools(self) -> dict:
|
||||
return self.tools
|
||||
|
||||
@property
|
||||
def get_success(self) -> bool:
|
||||
return self.success
|
||||
|
||||
def get_blocks_result(self) -> list:
|
||||
return self.blocks_result
|
||||
|
||||
|
@ -287,7 +287,19 @@ class BrowserAgent(Agent):
|
||||
for res in search_result:
|
||||
pretty_print(f"Title: {res['title']} - ", color="info", no_newline=True)
|
||||
pretty_print(f"Link: {res['link']}", color="status")
|
||||
|
||||
|
||||
def stuck_prompt(self, user_prompt: str, unvisited: List[str]) -> str:
|
||||
"""
|
||||
Prompt for when the agent repeat itself, can happen when fail to extract a link.
|
||||
"""
|
||||
prompt = self.make_newsearch_prompt(user_prompt, unvisited)
|
||||
prompt += f"""
|
||||
You previously said:
|
||||
{self.last_answer}
|
||||
You must consider other options. Choose other link.
|
||||
"""
|
||||
return prompt
|
||||
|
||||
async def process(self, user_prompt: str, speech_module: type) -> Tuple[str, str]:
|
||||
"""
|
||||
Process the user prompt to conduct an autonomous web search.
|
||||
@ -317,7 +329,11 @@ class BrowserAgent(Agent):
|
||||
while not complete and len(unvisited) > 0:
|
||||
|
||||
self.memory.clear()
|
||||
unvisited = self.select_unvisited(search_result)
|
||||
answer, reasoning = await self.llm_decide(prompt, show_reasoning = False)
|
||||
if self.last_answer == answer:
|
||||
prompt = self.stuck_prompt(user_prompt, unvisited)
|
||||
continue
|
||||
self.last_answer = answer
|
||||
pretty_print('▂'*32, color="status")
|
||||
|
||||
@ -339,6 +355,11 @@ class BrowserAgent(Agent):
|
||||
|
||||
links = self.parse_answer(answer)
|
||||
link = self.select_link(links)
|
||||
if link == self.current_page:
|
||||
pretty_print(f"Already visited {link}. Search callback.", color="status")
|
||||
prompt = self.make_newsearch_prompt(user_prompt, unvisited)
|
||||
self.search_history.append(link)
|
||||
continue
|
||||
|
||||
if Action.REQUEST_EXIT.value in answer:
|
||||
self.status_message = "Exiting web browser..."
|
||||
@ -349,7 +370,6 @@ class BrowserAgent(Agent):
|
||||
if (link == None and len(extracted_form) < 3) or Action.GO_BACK.value in answer or link in self.search_history:
|
||||
pretty_print(f"Going back to results. Still {len(unvisited)}", color="status")
|
||||
self.status_message = "Going back to search results..."
|
||||
unvisited = self.select_unvisited(search_result)
|
||||
prompt = self.make_newsearch_prompt(user_prompt, unvisited)
|
||||
self.search_history.append(link)
|
||||
self.current_page = link
|
||||
@ -357,8 +377,12 @@ class BrowserAgent(Agent):
|
||||
|
||||
animate_thinking(f"Navigating to {link}", color="status")
|
||||
if speech_module: speech_module.speak(f"Navigating to {link}")
|
||||
self.browser.go_to(link)
|
||||
nav_ok = self.browser.go_to(link)
|
||||
self.search_history.append(link)
|
||||
if not nav_ok:
|
||||
pretty_print(f"Failed to navigate to {link}.", color="failure")
|
||||
prompt = self.make_newsearch_prompt(user_prompt, unvisited)
|
||||
continue
|
||||
self.current_page = link
|
||||
page_text = self.browser.get_text()
|
||||
self.navigable_links = self.browser.get_navigable()
|
||||
|
@ -26,11 +26,18 @@ class PlannerAgent(Agent):
|
||||
}
|
||||
self.role = "planification"
|
||||
self.type = "planner_agent"
|
||||
|
||||
def parse_agent_tasks(self, text):
|
||||
tasks = []
|
||||
|
||||
def get_task_names(self, text: str) -> List[str]:
|
||||
"""
|
||||
Extracts task names from the given text.
|
||||
This method processes a multi-line string, where each line may represent a task name.
|
||||
containing '##' or starting with a digit. The valid task names are collected and returned.
|
||||
Args:
|
||||
text (str): A string containing potential task titles (eg: Task 1: I will...).
|
||||
Returns:
|
||||
List[str]: A list of extracted task names that meet the specified criteria.
|
||||
"""
|
||||
tasks_names = []
|
||||
|
||||
lines = text.strip().split('\n')
|
||||
for line in lines:
|
||||
if line is None:
|
||||
@ -41,9 +48,23 @@ class PlannerAgent(Agent):
|
||||
if '##' in line or line[0].isdigit():
|
||||
tasks_names.append(line)
|
||||
continue
|
||||
return tasks_names
|
||||
|
||||
def parse_agent_tasks(self, text: str) -> List[Tuple[str, str]]:
|
||||
"""
|
||||
Parses agent tasks from the given LLM text.
|
||||
This method extracts task information from a JSON. It identifies task names and their details.
|
||||
Args:
|
||||
text (str): The input text containing task information in a JSON-like format.
|
||||
Returns:
|
||||
List[Tuple[str, str]]: A list of tuples containing task names and their details.
|
||||
"""
|
||||
tasks = []
|
||||
tasks_names = self.get_task_names(text)
|
||||
|
||||
blocks, _ = self.tools["json"].load_exec_block(text)
|
||||
if blocks == None:
|
||||
return (None, None)
|
||||
return []
|
||||
for block in blocks:
|
||||
line_json = json.loads(block)
|
||||
if 'plan' in line_json:
|
||||
@ -58,10 +79,18 @@ class PlannerAgent(Agent):
|
||||
tasks.append(agent)
|
||||
if len(tasks_names) != len(tasks):
|
||||
names = [task['task'] for task in tasks]
|
||||
return zip(names, tasks)
|
||||
return zip(tasks_names, tasks)
|
||||
return list(map(list, zip(names, tasks)))
|
||||
return list(map(list, zip(tasks_names, tasks)))
|
||||
|
||||
def make_prompt(self, task: dict, agent_infos_dict: dict):
|
||||
def make_prompt(self, task: str, agent_infos_dict: dict) -> str:
|
||||
"""
|
||||
Generates a prompt for the agent based on the task and previous agents work information.
|
||||
Args:
|
||||
task (str): The task to be performed.
|
||||
agent_infos_dict (dict): A dictionary containing information from other agents.
|
||||
Returns:
|
||||
str: The formatted prompt for the agent.
|
||||
"""
|
||||
infos = ""
|
||||
if agent_infos_dict is None or len(agent_infos_dict) == 0:
|
||||
infos = "No needed informations."
|
||||
@ -76,8 +105,14 @@ class PlannerAgent(Agent):
|
||||
"""
|
||||
return prompt
|
||||
|
||||
def show_plan(self, agents_tasks: dict, answer: str) -> None:
|
||||
if agents_tasks == (None, None):
|
||||
def show_plan(self, agents_tasks: List[dict], answer: str) -> None:
|
||||
"""
|
||||
Displays the plan made by the agent.
|
||||
Args:
|
||||
agents_tasks (dict): The tasks assigned to each agent.
|
||||
answer (str): The answer from the LLM.
|
||||
"""
|
||||
if agents_tasks == []:
|
||||
pretty_print(answer, color="warning")
|
||||
pretty_print("Failed to make a plan. This can happen with (too) small LLM. Clarify your request and insist on it making a plan within ```json.", color="failure")
|
||||
return
|
||||
@ -85,45 +120,113 @@ class PlannerAgent(Agent):
|
||||
for task_name, task in agents_tasks:
|
||||
pretty_print(f"{task['agent']} -> {task['task']}", color="info")
|
||||
pretty_print("▔▗ E N D ▖▔", color="status")
|
||||
|
||||
|
||||
async def make_plan(self, prompt: str) -> str:
|
||||
"""
|
||||
Asks the LLM to make a plan.
|
||||
Args:
|
||||
prompt (str): The prompt to be sent to the LLM.
|
||||
Returns:
|
||||
str: The plan made by the LLM.
|
||||
"""
|
||||
ok = False
|
||||
answer = None
|
||||
while not ok:
|
||||
animate_thinking("Thinking...", color="status")
|
||||
self.memory.push('user', prompt)
|
||||
answer, _ = await self.llm_request()
|
||||
answer, reasoning = await self.llm_request()
|
||||
if "NO_UPDATE" in answer:
|
||||
return []
|
||||
agents_tasks = self.parse_agent_tasks(answer)
|
||||
if agents_tasks == (None, None):
|
||||
if agents_tasks == []:
|
||||
prompt = f"Failed to parse the tasks. Please make a plan within ```json.\n"
|
||||
pretty_print("Failed to make plan. Retrying...", color="warning")
|
||||
continue
|
||||
self.show_plan(agents_tasks, answer)
|
||||
ok = True
|
||||
return answer
|
||||
return self.parse_agent_tasks(answer)
|
||||
|
||||
async def update_plan(self, goal: str, agents_tasks: List[dict], agents_work_result: dict, id: str, success: bool) -> dict:
|
||||
"""
|
||||
Updates the plan with the results of the agents work.
|
||||
Args:
|
||||
goal (str): The goal to be achieved.
|
||||
agents_tasks (list): The tasks assigned to each agent.
|
||||
agents_work_result (dict): The results of the agents work.
|
||||
Returns:
|
||||
dict: The updated plan.
|
||||
"""
|
||||
self.status_message = "Updating plan..."
|
||||
last_agent_work = agents_work_result[id]
|
||||
tool_success_str = "success" if success else "failure"
|
||||
pretty_print(f"Agent {id} work {tool_success_str}.", color="success" if success else "failure")
|
||||
next_task = agents_tasks[int(id)][0]
|
||||
#if success:
|
||||
# return agents_tasks # we only update the plan if last task failed, for now
|
||||
update_prompt = f"""
|
||||
Your goal is : {goal}
|
||||
You previously made a plan, agents are currently working on it.
|
||||
The last agent working on task: {id}, did the following work:
|
||||
{last_agent_work}
|
||||
Agent {id} work was a {tool_success_str} according to system interpreter.
|
||||
The agent {id} about to work on task: {next_task}
|
||||
Is the work done for task {id} leading to sucess or failure ? Did an agent fail with a task?
|
||||
If agent work was good: answer "NO_UPDATE"
|
||||
If agent work is leading to failure: update the plan.
|
||||
plan should be within ```json like before.
|
||||
You need to rewrite the whole plan, but only change the tasks after task {id}.
|
||||
Keep the plan as short as the original one if possible. Do not change past tasks.
|
||||
"""
|
||||
pretty_print("Updating plan...", color="status")
|
||||
plan = await self.make_plan(update_prompt)
|
||||
if plan == []:
|
||||
pretty_print("No plan update required.", color="info")
|
||||
return agents_tasks
|
||||
return plan
|
||||
|
||||
async def start_agent_process(self, task: dict, required_infos: dict | None) -> str:
|
||||
"""
|
||||
Starts the agent process for a given task.
|
||||
Args:
|
||||
task (dict): The task to be performed.
|
||||
required_infos (dict | None): The required information for the task.
|
||||
Returns:
|
||||
str: The result of the agent process.
|
||||
"""
|
||||
self.status_message = f"Starting task {task['task']}..."
|
||||
agent_prompt = self.make_prompt(task['task'], required_infos)
|
||||
pretty_print(f"Agent {task['agent']} started working...", color="status")
|
||||
agent_answer, _ = await self.agents[task['agent'].lower()].process(agent_prompt, None)
|
||||
success = self.agents[task['agent'].lower()].get_success
|
||||
self.agents[task['agent'].lower()].show_answer()
|
||||
pretty_print(f"Agent {task['agent']} completed task.", color="status")
|
||||
return agent_answer
|
||||
return agent_answer, success
|
||||
|
||||
def get_work_result_agent(self, task_needs, agents_work_result):
|
||||
return {k: agents_work_result[k] for k in task_needs if k in agents_work_result}
|
||||
|
||||
async def process(self, prompt: str, speech_module: Speech) -> Tuple[str, str]:
|
||||
agents_tasks = (None, None)
|
||||
async def process(self, goal: str, speech_module: Speech) -> Tuple[str, str]:
|
||||
"""
|
||||
Process the goal by dividing it into tasks and assigning them to agents.
|
||||
Args:
|
||||
goal (str): The goal to be achieved (user prompt).
|
||||
speech_module (Speech): The speech module for text-to-speech.
|
||||
Returns:
|
||||
Tuple[str, str]: The result of the agent process and empty reasoning string.
|
||||
"""
|
||||
agents_tasks = []
|
||||
agents_work_result = dict()
|
||||
|
||||
answer = await self.make_plan(prompt)
|
||||
agents_tasks = self.parse_agent_tasks(answer)
|
||||
self.status_message = "Making a plan..."
|
||||
agents_tasks = await self.make_plan(goal)
|
||||
|
||||
if agents_tasks == (None, None):
|
||||
if agents_tasks == []:
|
||||
return "Failed to parse the tasks.", ""
|
||||
for task_name, task in agents_tasks:
|
||||
self.status_message = "Starting agent process..."
|
||||
i = 0
|
||||
steps = len(agents_tasks)
|
||||
while i < steps:
|
||||
task_name, task = agents_tasks[i][0], agents_tasks[i][1]
|
||||
self.status_message = "Starting agents..."
|
||||
pretty_print(f"I will {task_name}.", color="info")
|
||||
pretty_print(f"Assigned agent {task['agent']} to {task_name}", color="info")
|
||||
if speech_module: speech_module.speak(f"I will {task_name}. I assigned the {task['agent']} agent to the task.")
|
||||
@ -131,8 +234,14 @@ class PlannerAgent(Agent):
|
||||
if agents_work_result is not None:
|
||||
required_infos = self.get_work_result_agent(task['need'], agents_work_result)
|
||||
try:
|
||||
self.last_answer = await self.start_agent_process(task, required_infos)
|
||||
self.last_answer, success = await self.start_agent_process(task, required_infos)
|
||||
except Exception as e:
|
||||
raise e
|
||||
agents_work_result[task['id']] = self.last_answer
|
||||
if i == steps - 1:
|
||||
break
|
||||
agents_tasks = await self.update_plan(goal, agents_tasks, agents_work_result, task['id'], success)
|
||||
steps = len(agents_tasks)
|
||||
i += 1
|
||||
|
||||
return self.last_answer, ""
|
@ -166,13 +166,17 @@ class Browser:
|
||||
try:
|
||||
initial_handles = self.driver.window_handles
|
||||
self.driver.get(url)
|
||||
wait = WebDriverWait(self.driver, timeout=10)
|
||||
wait.until(
|
||||
lambda driver: (
|
||||
not any(keyword in driver.page_source.lower() for keyword in ["checking your browser", "captcha"])
|
||||
),
|
||||
message="stuck on 'checking browser' or verification screen"
|
||||
)
|
||||
try:
|
||||
wait = WebDriverWait(self.driver, timeout=10)
|
||||
wait.until(
|
||||
lambda driver: (
|
||||
not any(keyword in driver.page_source.lower() for keyword in ["checking your browser", "captcha"])
|
||||
),
|
||||
message="stuck on 'checking browser' or verification screen"
|
||||
)
|
||||
except TimeoutException:
|
||||
self.logger.warning("Timeout while waiting for page to bypass 'checking your browser'")
|
||||
return False
|
||||
self.apply_web_safety()
|
||||
self.logger.log(f"Navigated to: {url}")
|
||||
return True
|
||||
@ -601,10 +605,10 @@ if __name__ == "__main__":
|
||||
|
||||
input("press enter to continue")
|
||||
print("AntiCaptcha / Form Test")
|
||||
browser.go_to("https://www.browserscan.net/bot-detection")
|
||||
#browser.go_to("https://www.browserscan.net/bot-detection")
|
||||
#txt = browser.get_text()
|
||||
#browser.go_to("https://www.google.com/recaptcha/api2/demo")
|
||||
#browser.go_to("https://home.openweathermap.org/users/sign_up")
|
||||
browser.go_to("https://home.openweathermap.org/users/sign_up")
|
||||
inputs_visible = browser.get_form_inputs()
|
||||
print("inputs:", inputs_visible)
|
||||
#inputs_fill = ['[q](checked)', '[q](checked)', '[user[username]](mlg)', '[user[email]](mlg.fcu@gmail.com)', '[user[password]](placeholder_P@ssw0rd123)', '[user[password_confirmation]](placeholder_P@ssw0rd123)']
|
||||
|
Loading…
x
Reference in New Issue
Block a user