mirror of
https://github.com/tcsenpai/agenticSeek.git
synced 2025-06-03 01:30:11 +00:00
feat : small frontend improvement & planner auto fix
This commit is contained in:
parent
14f42b638d
commit
a32cf60958
6
app.py
Normal file → Executable file
6
app.py
Normal file → Executable file
@ -22,12 +22,15 @@ config.read('config.ini')
|
||||
app = FastAPI(title="AgenticSeek API", version="0.1.0")
|
||||
logger = Logger("backend.log")
|
||||
|
||||
if not os.path.exists(".screenshots"):
|
||||
os.makedirs(".screenshots")
|
||||
|
||||
app.mount("/screenshots", StaticFiles(directory=".screenshots"), name="screenshots")
|
||||
|
||||
# Add CORS middleware to allow frontend requests
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["http://localhost:3000"],
|
||||
allow_origins=["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
@ -139,7 +142,6 @@ async def process_query(request: QueryRequest):
|
||||
)
|
||||
try:
|
||||
interaction.tts_enabled = request.tts_enabled
|
||||
interaction.stt_enabled = request.stt_enabled
|
||||
interaction.last_query = request.query
|
||||
logger.info("Agents request is being processed")
|
||||
is_generating = True
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: '3.8'
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
redis:
|
||||
@ -30,10 +30,12 @@ services:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- ./searxng:/etc/searxng:rw
|
||||
- ./searxng/entrypoint.sh:/usr/local/bin/searxng-entrypoint.sh:ro
|
||||
entrypoint: /usr/local/bin/searxng-entrypoint.sh
|
||||
environment:
|
||||
- SEARXNG_BASE_URL=http://localhost:8080/
|
||||
- UWSGI_WORKERS=1
|
||||
- UWSGI_THREADS=1
|
||||
- UWSGI_WORKERS=4
|
||||
- UWSGI_THREADS=4
|
||||
cap_add:
|
||||
- CHOWN
|
||||
- SETGID
|
||||
|
@ -45,7 +45,7 @@
|
||||
gap: 40px;
|
||||
height: calc(100vh - 200px);
|
||||
}
|
||||
|
||||
|
||||
.left-panel,
|
||||
.right-panel {
|
||||
background-color: #1a1a1a;
|
||||
@ -54,6 +54,7 @@
|
||||
box-shadow: 0 0 10px rgba(0, 255, 204, 0.2);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.left-panel {
|
||||
@ -66,6 +67,7 @@
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: 100%;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
@ -81,6 +83,11 @@
|
||||
border-radius: 8px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.messages::-webkit-scrollbar,
|
||||
.content::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.user-message {
|
||||
background-color: #00ffcc;
|
||||
@ -189,7 +196,7 @@
|
||||
.content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 10px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.blocks {
|
||||
@ -200,7 +207,7 @@
|
||||
|
||||
.block {
|
||||
background-color: #222;
|
||||
padding: 15px;
|
||||
padding: 10px;
|
||||
border: 1px solid #00ffcc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
@ -214,7 +221,7 @@
|
||||
|
||||
.block pre {
|
||||
background-color: #111;
|
||||
padding: 10px;
|
||||
padding: 5px;
|
||||
border-radius: 4px;
|
||||
font-size: 0.85rem;
|
||||
white-space: pre-wrap;
|
||||
@ -222,7 +229,7 @@
|
||||
}
|
||||
|
||||
.screenshot {
|
||||
margin-top: 20px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.screenshot img {
|
||||
|
@ -9,45 +9,111 @@ function App() {
|
||||
const [error, setError] = useState(null);
|
||||
const [currentView, setCurrentView] = useState('blocks');
|
||||
const [responseData, setResponseData] = useState(null);
|
||||
const [isOnline, setIsOnline] = useState(false); // Added state
|
||||
const messagesEndRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
scrollToBottom();
|
||||
}, [messages]);
|
||||
|
||||
// Added: checks /health
|
||||
const checkHealth = async () => {
|
||||
try {
|
||||
await axios.get('http://0.0.0.0:8000/health');
|
||||
setIsOnline(true);
|
||||
console.log('System is online');
|
||||
} catch {
|
||||
setIsOnline(false);
|
||||
console.log('System is offline');
|
||||
}
|
||||
};
|
||||
|
||||
const scrollToBottom = () => {
|
||||
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (currentView === 'screenshot') {
|
||||
let isMounted = true;
|
||||
|
||||
const fetchScreenshot = async () => {
|
||||
try {
|
||||
const res = await axios.get('http://0.0.0.0:8000/screenshots/updated_screen.png', {
|
||||
responseType: 'blob',
|
||||
params: { t: new Date().getTime() }
|
||||
});
|
||||
if (isMounted) {
|
||||
console.log('Screenshot fetched successfully');
|
||||
const imageUrl = URL.createObjectURL(res.data);
|
||||
setResponseData((prev) => {
|
||||
if (prev?.screenshot && prev.screenshot !== 'placeholder.png') {
|
||||
URL.revokeObjectURL(prev.screenshot);
|
||||
}
|
||||
return {
|
||||
...prev,
|
||||
screenshot: imageUrl,
|
||||
screenshotTimestamp: new Date().getTime()
|
||||
};
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error fetching screenshot:', err);
|
||||
if (isMounted) {
|
||||
setResponseData((prev) => ({
|
||||
...prev,
|
||||
screenshot: 'placeholder.png',
|
||||
screenshotTimestamp: new Date().getTime()
|
||||
}));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fetchScreenshot();
|
||||
const interval = setInterval(fetchScreenshot, 1000);
|
||||
|
||||
return () => {
|
||||
isMounted = false;
|
||||
clearInterval(interval);
|
||||
if (responseData?.screenshot && responseData.screenshot !== 'placeholder.png') {
|
||||
URL.revokeObjectURL(responseData.screenshot);
|
||||
}
|
||||
};
|
||||
}
|
||||
}, [currentView]);
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
if (!query.trim()) return;
|
||||
checkHealth();
|
||||
if (!query.trim()) {
|
||||
console.log('Empty query');
|
||||
return;
|
||||
}
|
||||
setMessages((prev) => [...prev, { type: 'user', content: query }]);
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
//const res = await axios.post('http://backend:8000/query', { ... });
|
||||
const res = await axios.post('${process.env.BACKEND_URL}/query', {
|
||||
console.log('Sending query:', query);
|
||||
const res = await axios.post('http://0.0.0.0:8000/query', {
|
||||
query,
|
||||
lang: 'en',
|
||||
tts_enabled: false,
|
||||
stt_enabled: false,
|
||||
tts_enabled: false
|
||||
});
|
||||
console.log('Response:', res.data);
|
||||
const data = res.data;
|
||||
setResponseData(data);
|
||||
setMessages((prev) => [
|
||||
...prev,
|
||||
{ type: 'agent', content: data.answer, agentName: data.agent_name },
|
||||
]);
|
||||
setCurrentView('blocks');
|
||||
} catch (err) {
|
||||
console.error('Error:', err);
|
||||
setError('Failed to process query.');
|
||||
setMessages((prev) => [
|
||||
...prev,
|
||||
{ type: 'error', content: 'Error: Unable to get a response.' },
|
||||
]);
|
||||
} finally {
|
||||
console.log('Query completed');
|
||||
setIsLoading(false);
|
||||
setQuery('');
|
||||
}
|
||||
@ -55,11 +121,12 @@ function App() {
|
||||
|
||||
const handleGetScreenshot = async () => {
|
||||
try {
|
||||
//const res = await axios.get('http://backend:8000/screenshots/updated_screen.png');
|
||||
const res = await axios.get('${process.env.BACKEND_URL}/screenshots/updated_screen.png');
|
||||
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');
|
||||
}
|
||||
};
|
||||
@ -73,7 +140,7 @@ function App() {
|
||||
<div className="chat-container">
|
||||
<div className="left-panel">
|
||||
<h2>C H A T</h2>
|
||||
<br></br>
|
||||
<br />
|
||||
<div className="messages">
|
||||
{messages.length === 0 ? (
|
||||
<p className="placeholder">No messages yet. Type below to start!</p>
|
||||
@ -98,7 +165,8 @@ function App() {
|
||||
)}
|
||||
<div ref={messagesEndRef} />
|
||||
</div>
|
||||
{isLoading && <div className="loading-animation">Loading...</div>}
|
||||
{isOnline && isLoading && <div className="loading-animation">Thinking...</div>}
|
||||
{!isLoading && !isOnline && <p className="loading-animation">System offline. Deploy backend first.</p>}
|
||||
<form onSubmit={handleSubmit} className="input-form">
|
||||
<input
|
||||
type="text"
|
||||
@ -114,7 +182,7 @@ function App() {
|
||||
</div>
|
||||
<div className="right-panel">
|
||||
<h2>I N T E R F A C E</h2>
|
||||
<br></br>
|
||||
<br />
|
||||
<div className="view-selector">
|
||||
<button
|
||||
className={currentView === 'blocks' ? 'active' : ''}
|
||||
@ -153,7 +221,15 @@ function App() {
|
||||
</div>
|
||||
) : (
|
||||
<div className="screenshot">
|
||||
<img src="${process.env.BACKEND_URL}/screenshots/updated_screen.png" alt="Screenshot" />
|
||||
<img
|
||||
src={responseData?.screenshot || 'placeholder.png'}
|
||||
alt="Screenshot"
|
||||
onError={(e) => {
|
||||
e.target.src = 'placeholder.png';
|
||||
console.error('Failed to load screenshot');
|
||||
}}
|
||||
key={responseData?.screenshotTimestamp || 'default'} // Force re-render
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
@ -45,6 +45,7 @@ rules:
|
||||
- Do not ever use editor such as vim or nano.
|
||||
- Make sure to always cd your work folder before executing commands, like cd <work dir> && <your command>
|
||||
- only use file name with file_finder, not path
|
||||
- If query is unrelated to file operations, do nothing, and say that there was mistake in agent allocation.
|
||||
|
||||
Example Interaction
|
||||
User: "I need to find the file config.txt and read its contents."
|
||||
|
@ -55,6 +55,7 @@ rules:
|
||||
- Make sure to always cd your work folder before executing commands, like cd <work dir> && <your command>
|
||||
- Do not ever use editor such as vim or nano.
|
||||
- only use file name with file_finder, not path
|
||||
- If query is unrelated to file operations, do nothing, and say that there was mistake in agent allocation.
|
||||
|
||||
Example Interaction
|
||||
User: "I need to find the file config.txt and read its contents."
|
||||
|
9
searxng/entrypoint.sh
Executable file
9
searxng/entrypoint.sh
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
# entrypoint for docker searxng service
|
||||
|
||||
SECRET_KEY=$(openssl rand -hex 32)
|
||||
|
||||
sed -i "s/ultrasecretkey/$SECRET_KEY/g" /etc/searxng/settings.yml
|
||||
|
||||
exec /usr/local/searxng/dockerfiles/docker-entrypoint.sh "$@"
|
@ -5,11 +5,11 @@ gid = searxng
|
||||
|
||||
# Number of workers (usually CPU count)
|
||||
# default value: %k (= number of CPU core, see Dockerfile)
|
||||
workers = 1
|
||||
workers = 4
|
||||
|
||||
# Number of threads per worker
|
||||
# default value: 4 (see Dockerfile)
|
||||
threads = 1
|
||||
threads = 4
|
||||
|
||||
# The right granted on the created socket
|
||||
chmod-socket = 666
|
||||
@ -19,7 +19,7 @@ single-interpreter = true
|
||||
master = true
|
||||
plugin = python3
|
||||
lazy-apps = true
|
||||
enable-threads = 1
|
||||
enable-threads = 4
|
||||
|
||||
# Module to import
|
||||
module = searx.webapp
|
||||
@ -49,4 +49,4 @@ die-on-term
|
||||
# uwsgi serves the static files
|
||||
static-map = /static=/usr/local/searxng/searx/static
|
||||
static-gzip-all = True
|
||||
offload-threads = 1
|
||||
offload-threads = 4
|
2731
searxng/settings.yml.new
Normal file
2731
searxng/settings.yml.new
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,72 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script to automate SearXNG setup and deployment with Docker Compose
|
||||
|
||||
command_exists() {
|
||||
command -v "$1" &> /dev/null
|
||||
}
|
||||
|
||||
# Check if Docker is installed
|
||||
if ! command_exists docker; then
|
||||
echo "Error: Docker is not installed. Please install Docker first."
|
||||
echo "On Ubuntu: sudo apt install docker.io"
|
||||
echo "On macOS/Windows: Install Docker Desktop from https://www.docker.com/get-started/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if Docker daemon is running
|
||||
echo "Checking if Docker daemon is running..."
|
||||
if ! docker info &> /dev/null; then
|
||||
echo "Error: Docker daemon is not running or inaccessible."
|
||||
if [ "$(uname)" = "Linux" ]; then
|
||||
echo "Trying to start Docker service (may require sudo)..."
|
||||
if sudo systemctl start docker &> /dev/null; then
|
||||
echo "Docker started successfully."
|
||||
else
|
||||
echo "Failed to start Docker. Possible issues:"
|
||||
echo "1. Run this script with sudo: sudo bash setup_searxng.sh"
|
||||
echo "2. Check Docker installation: sudo systemctl status docker"
|
||||
echo "3. Add your user to the docker group: sudo usermod -aG docker $USER (then log out and back in)"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Please start Docker manually:"
|
||||
echo "- On macOS/Windows: Open Docker Desktop."
|
||||
echo "- On Linux: Run 'sudo systemctl start docker' or check your distro's docs."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Docker daemon is running."
|
||||
fi
|
||||
|
||||
# Check if Docker Compose is installed
|
||||
if ! command_exists docker-compose; then
|
||||
echo "Error: Docker Compose is not installed. Please install it first."
|
||||
echo "On Ubuntu: sudo apt install docker-compose"
|
||||
echo "Or via pip: pip install docker-compose"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create a directory for SearXNG config if it doesn’t exist
|
||||
mkdir -p searxng
|
||||
cd . || exit
|
||||
|
||||
# Check if docker-compose.yml exists
|
||||
if [ ! -f "docker-compose.yml" ]; then
|
||||
echo "Error: docker-compose.yml not found in the current directory."
|
||||
echo "Please create it before running this script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Start containers to generate initial config files
|
||||
echo "Starting containers for initial setup..."
|
||||
if ! docker-compose up -d; then
|
||||
echo "Error: Failed to start containers. Check Docker logs with 'docker compose logs'."
|
||||
echo "Possible fixes: Run with sudo or ensure port 8080 is free."
|
||||
exit 1
|
||||
fi
|
||||
sleep 10
|
||||
|
||||
# Generate a secret key and update settings
|
||||
SECRET_KEY=$(openssl rand -hex 32)
|
||||
if [ -f "searxng/settings.yml" ]; then
|
||||
@ -16,4 +83,9 @@ else
|
||||
echo "Error: settings.yml not found. Initial setup may have failed."
|
||||
docker-compose logs searxng
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Display status and access instructions
|
||||
echo "SearXNG setup complete!"
|
||||
docker ps -a --filter "name=searxng" --filter "name=redis"
|
||||
echo "Access SearXNG at: http://localhost:8080"
|
@ -9,7 +9,7 @@ workers = 1
|
||||
|
||||
# Number of threads per worker
|
||||
# default value: 4 (see Dockerfile)
|
||||
enable-threads = false
|
||||
enable-threads = true
|
||||
threads = 1
|
||||
|
||||
# The right granted on the created socket
|
||||
@ -20,7 +20,7 @@ single-interpreter = true
|
||||
master = true
|
||||
plugin = python3
|
||||
lazy-apps = true
|
||||
enable-threads = 1
|
||||
enable-threads = 4
|
||||
|
||||
# Module to import
|
||||
module = searx.webapp
|
||||
@ -50,4 +50,4 @@ die-on-term
|
||||
# uwsgi serves the static files
|
||||
static-map = /static=/usr/local/searxng/searx/static
|
||||
static-gzip-all = True
|
||||
offload-threads = 2
|
||||
offload-threads = 4
|
||||
|
@ -76,8 +76,7 @@ class PlannerAgent(Agent):
|
||||
"""
|
||||
return prompt
|
||||
|
||||
def show_plan(self, answer: dict) -> None:
|
||||
agents_tasks = self.parse_agent_tasks(answer)
|
||||
def show_plan(self, agents_tasks: dict, answer: str) -> None:
|
||||
if agents_tasks == (None, None):
|
||||
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")
|
||||
@ -94,12 +93,13 @@ class PlannerAgent(Agent):
|
||||
animate_thinking("Thinking...", color="status")
|
||||
self.memory.push('user', prompt)
|
||||
answer, _ = self.llm_request()
|
||||
self.show_plan(answer)
|
||||
ok_str = input("Is the plan ok? (y/n): ")
|
||||
if ok_str == 'y':
|
||||
ok = True
|
||||
else:
|
||||
prompt = input("Please reformulate: ")
|
||||
agents_tasks = self.parse_agent_tasks(answer)
|
||||
if agents_tasks == (None, None):
|
||||
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
|
||||
|
||||
def start_agent_process(self, task: str, required_infos: dict | None) -> str:
|
||||
|
@ -123,16 +123,25 @@ class Browser:
|
||||
self.js_scripts_folder = "./sources/web_scripts/" if not __name__ == "__main__" else "./web_scripts/"
|
||||
self.anticaptcha = "https://chrome.google.com/webstore/detail/nopecha-captcha-solver/dknlfmjaanfblgfdfebhijalfmhmjjjo/related"
|
||||
self.logger = Logger("browser.log")
|
||||
self.screenshot_folder = os.path.join(os.getcwd(), ".screenshots")
|
||||
self.tabs = []
|
||||
try:
|
||||
self.driver = driver
|
||||
self.wait = WebDriverWait(self.driver, 10)
|
||||
except Exception as e:
|
||||
raise Exception(f"Failed to initialize browser: {str(e)}")
|
||||
self.screenshot_folder = os.path.join(os.getcwd(), ".screenshots")
|
||||
self.screenshot()
|
||||
self.driver.get("https://www.google.com")
|
||||
self.setup_tabs()
|
||||
if anticaptcha_manual_install:
|
||||
self.load_anticatpcha_manually()
|
||||
|
||||
def setup_tabs(self):
|
||||
self.tabs = self.driver.window_handles
|
||||
self.driver.get("https://www.google.com")
|
||||
self.screenshot()
|
||||
|
||||
def switch_control_tab(self):
|
||||
self.logger.log("Switching to control tab.")
|
||||
self.driver.switch_to.window(self.tabs[0])
|
||||
|
||||
def load_anticatpcha_manually(self):
|
||||
pretty_print("You might want to install the AntiCaptcha extension for captchas.", color="warning")
|
||||
@ -154,6 +163,7 @@ class Browser:
|
||||
)
|
||||
self.apply_web_safety()
|
||||
self.logger.log(f"Navigated to: {url}")
|
||||
self.logger.info(f"Navigated to: {self.get_page_title()}")
|
||||
self.screenshot()
|
||||
return True
|
||||
except TimeoutException as e:
|
||||
@ -201,6 +211,8 @@ class Browser:
|
||||
lines.append(cleaned)
|
||||
result = "[Start of page]\n\n" + "\n\n".join(lines) + "\n\n[End of page]"
|
||||
result = re.sub(r'!\[(.*?)\]\(.*?\)', r'[IMAGE: \1]', result)
|
||||
self.logger.info(f"Extracted text: {result[:100]}...")
|
||||
self.logger.info(f"Extracted text length: {len(result)}")
|
||||
return result[:8192]
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error getting text: {str(e)}")
|
||||
@ -226,9 +238,11 @@ class Browser:
|
||||
def is_link_valid(self, url:str) -> bool:
|
||||
"""Check if a URL is a valid link (page, not related to icon or metadata)."""
|
||||
if len(url) > 64:
|
||||
self.logger.warning(f"URL too long: {url}")
|
||||
return False
|
||||
parsed_url = urlparse(url)
|
||||
if not parsed_url.scheme or not parsed_url.netloc:
|
||||
self.logger.warning(f"Invalid URL: {url}")
|
||||
return False
|
||||
if re.search(r'/\d+$', parsed_url.path):
|
||||
return False
|
||||
@ -360,6 +374,7 @@ class Browser:
|
||||
Wait for a submission outcome (e.g., URL change or new element).
|
||||
"""
|
||||
try:
|
||||
self.logger.info("Waiting for submission outcome...")
|
||||
wait = WebDriverWait(self.driver, timeout)
|
||||
wait.until(
|
||||
lambda driver: driver.current_url != self.driver.current_url or
|
||||
@ -387,8 +402,10 @@ class Browser:
|
||||
message=f"Button with XPath '{xpath}' not clickable within {timeout} seconds"
|
||||
)
|
||||
if self.click_element(xpath):
|
||||
self.logger.info(f"Clicked button '{button_text}' at XPath: {xpath}")
|
||||
return True
|
||||
else:
|
||||
self.logger.warning(f"Button '{button_text}' at XPath: {xpath} not clickable")
|
||||
return False
|
||||
except TimeoutException:
|
||||
self.logger.warning(f"Timeout waiting for '{button_text}' button at XPath: {xpath}")
|
||||
@ -424,9 +441,9 @@ class Browser:
|
||||
self.logger.info(f"Ticked checkbox {index}")
|
||||
except ElementClickInterceptedException:
|
||||
self.driver.execute_script("arguments[0].click();", checkbox)
|
||||
self.logger.info(f"Ticked checkbox {index} using JavaScript")
|
||||
self.logger.warning(f"Click checkbox {index} intercepted")
|
||||
else:
|
||||
self.logger.debug(f"Checkbox {index} already ticked")
|
||||
self.logger.info(f"Checkbox {index} already ticked")
|
||||
except TimeoutException:
|
||||
self.logger.warning(f"Timeout waiting for checkbox {index} to be clickable")
|
||||
continue
|
||||
@ -534,6 +551,7 @@ class Browser:
|
||||
def scroll_bottom(self) -> bool:
|
||||
"""Scroll to the bottom of the page."""
|
||||
try:
|
||||
self.logger.info("Scrolling to the bottom of the page...")
|
||||
self.driver.execute_script(
|
||||
"window.scrollTo(0, document.body.scrollHeight);"
|
||||
)
|
||||
@ -549,6 +567,7 @@ class Browser:
|
||||
|
||||
def screenshot(self, filename:str = 'updated_screen.png') -> bool:
|
||||
"""Take a screenshot of the current page."""
|
||||
self.logger.info("Taking screenshot...")
|
||||
try:
|
||||
path = os.path.join(self.screenshot_folder, filename)
|
||||
if not os.path.exists(self.screenshot_folder):
|
||||
@ -564,11 +583,12 @@ class Browser:
|
||||
"""
|
||||
Apply security measures to block any website malicious/annoying execution, privacy violation etc..
|
||||
"""
|
||||
self.logger.info("Applying web safety measures...")
|
||||
script = self.load_js("inject_safety_script.js")
|
||||
input_elements = self.driver.execute_script(script)
|
||||
|
||||
if __name__ == "__main__":
|
||||
driver = create_driver(headless=True, stealth_mode=True)
|
||||
driver = create_driver(headless=False, stealth_mode=True)
|
||||
browser = Browser(driver, anticaptcha_manual_install=True)
|
||||
|
||||
#browser.go_to("https://github.com/Fosowl/agenticSeek")
|
||||
|
@ -1,12 +1,11 @@
|
||||
|
||||
from typing import Tuple, Callable
|
||||
from pydantic import BaseModel
|
||||
from sources.utility import pretty_print
|
||||
|
||||
class QueryRequest(BaseModel):
|
||||
query: str
|
||||
lang: str = "en"
|
||||
tts_enabled: bool = True
|
||||
stt_enabled: bool = False
|
||||
|
||||
def __str__(self):
|
||||
return f"Query: {self.query}, Language: {self.lang}, TTS: {self.tts_enabled}, STT: {self.stt_enabled}"
|
||||
@ -14,9 +13,7 @@ class QueryRequest(BaseModel):
|
||||
def jsonify(self):
|
||||
return {
|
||||
"query": self.query,
|
||||
"lang": self.lang,
|
||||
"tts_enabled": self.tts_enabled,
|
||||
"stt_enabled": self.stt_enabled
|
||||
}
|
||||
|
||||
class QueryResponse(BaseModel):
|
||||
|
@ -54,12 +54,9 @@ if [ ! -f "docker-compose.yml" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# start searxng service for internet search service
|
||||
cd searxng && ./setup_searxng.sh && cd ..
|
||||
|
||||
# start docker compose for searxng, redis, frontend services
|
||||
echo "SearXNG setup complete!"
|
||||
|
||||
# start docker compose for searxng, redis, frontend services
|
||||
echo "Warning: stopping all docker containers (t-4 seconds)..."
|
||||
sleep 4
|
||||
docker stop $(docker ps -a -q)
|
||||
|
Loading…
x
Reference in New Issue
Block a user