Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f23d46f
browser monitoring added
dimavrem22 Jan 24, 2026
17e26ee
agent sees data after recording
dimavrem22 Jan 25, 2026
895a02b
agent to initiate discovery
dimavrem22 Jan 25, 2026
679dc88
added auto launch chrome for /execute
dimavrem22 Jan 25, 2026
d491016
guide agent to make routines from scratch
dimavrem22 Jan 25, 2026
8a4e56d
refactored emitted messages
dimavrem22 Jan 25, 2026
a187947
new tab flow fixed
dimavrem22 Jan 25, 2026
fbc63e0
prompt change
dimavrem22 Jan 25, 2026
c4b314a
prompt change
dimavrem22 Jan 25, 2026
883743e
better prompts and sys messages
dimavrem22 Jan 25, 2026
1fde5b2
guide-agent-monitor-refactor
dimavrem22 Jan 25, 2026
eaf4031
allow modifying the dioscovery task sugested by the agent
dimavrem22 Jan 25, 2026
6e96b6b
better discovery result handling
dimavrem22 Jan 25, 2026
d7dd214
rm process user message
dimavrem22 Jan 26, 2026
2b79746
handle new chat role
dimavrem22 Jan 26, 2026
af8dd79
separate discovery approval and result
dimavrem22 Jan 26, 2026
f667389
separate nofitications
dimavrem22 Jan 26, 2026
9691e0b
small edit to notify_routine_discovery_response
dimavrem22 Jan 26, 2026
ec6a5e6
renaming
dimavrem22 Jan 26, 2026
fa25221
added logger statements
dimavrem22 Jan 26, 2026
a1f245c
added user actions
dimavrem22 Jan 26, 2026
9e0a6f9
rm routines
dimavrem22 Jan 26, 2026
0b38b35
system prompt deduplicaiton
dimavrem22 Jan 26, 2026
320b5ab
Update web_hacker/agents/guide_agent.py
dimavrem22 Jan 26, 2026
028c788
Update web_hacker/agents/guide_agent.py
dimavrem22 Jan 26, 2026
01db3a1
added RoutineChangeType enum
dimavrem22 Jan 26, 2026
a5fff35
rm logs, last_response_is cache
dimavrem22 Jan 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 15 additions & 125 deletions quickstart.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,16 @@
"""

import json
import os
import platform
import shutil
import subprocess
import sys
import time
from pathlib import Path
from typing import Optional

import requests
import websocket

from web_hacker.sdk import WebHacker, BrowserMonitor
from web_hacker.data_models.routine.routine import Routine
from web_hacker.cdp.connection import get_existing_tabs
from web_hacker.utils.chrome_utils import check_chrome_running, launch_chrome
from web_hacker.utils.terminal_utils import (
GREEN, YELLOW, BLUE, CYAN,
print_colored, print_header, ask_yes_no,
Expand All @@ -36,110 +31,6 @@
DISCOVERY_OUTPUT_DIR = Path("./routine_discovery_output")


def check_chrome_running(port: int) -> bool:
"""Check if Chrome is already running in debug mode."""
try:
response = requests.get(f"http://127.0.0.1:{port}/json/version", timeout=1)
return response.status_code == 200
except (requests.RequestException, requests.Timeout):
return False


def find_chrome_path() -> Optional[str]:
"""Find Chrome executable path based on OS."""
system = platform.system()

if system == "Darwin": # macOS
chrome_path = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
if os.path.isfile(chrome_path):
return chrome_path
elif system == "Linux":
for name in ["google-chrome", "chromium-browser", "chromium", "chrome"]:
chrome_path = shutil.which(name)
if chrome_path:
return chrome_path
elif system == "Windows":
possible_paths = [
os.path.expandvars(r"%ProgramFiles%\Google\Chrome\Application\chrome.exe"),
os.path.expandvars(r"%ProgramFiles(x86)%\Google\Chrome\Application\chrome.exe"),
os.path.expandvars(r"%LocalAppData%\Google\Chrome\Application\chrome.exe"),
]
for path in possible_paths:
if os.path.isfile(path):
return path
chrome_path = shutil.which("chrome") or shutil.which("google-chrome")
if chrome_path:
return chrome_path

return None


def launch_chrome(port: int) -> Optional[subprocess.Popen]:
"""Launch Chrome in debug mode."""
chrome_path = find_chrome_path()

if not chrome_path:
print_colored("⚠️ Chrome not found automatically.", YELLOW)
print(f" Please launch Chrome manually with --remote-debugging-port={port}")
input("Press Enter when Chrome is running in debug mode...")
return None

# Create user data directory
if platform.system() == "Windows":
chrome_user_dir = os.path.expandvars(r"%USERPROFILE%\tmp\chrome")
else:
chrome_user_dir = os.path.expanduser("~/tmp/chrome")

os.makedirs(chrome_user_dir, exist_ok=True)

chrome_args = [
chrome_path,
f"--remote-debugging-address=127.0.0.1",
f"--remote-debugging-port={port}",
f"--user-data-dir={chrome_user_dir}",
"--remote-allow-origins=*",
"--no-first-run",
"--no-default-browser-check",
"https://github.com/VectorlyApp/web-hacker/blob/main/docs/chrome-debug-mode-explanation.md",
]

print("🚀 Launching Chrome...")
try:
creation_flags = 0
if platform.system() == "Windows":
creation_flags = subprocess.CREATE_NEW_PROCESS_GROUP

process = subprocess.Popen(
chrome_args,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
creationflags=creation_flags,
)

print("⏳ Waiting for Chrome to start...")
for _ in range(10):
if check_chrome_running(port):
print_colored("✅ Chrome is ready!", GREEN)
time.sleep(0.5)
return process
time.sleep(1)

print_colored("⚠️ Chrome failed to start automatically.", YELLOW)
try:
process.terminate()
process.kill()
except Exception:
pass

input("Press Enter when Chrome is running in debug mode...")
return None

except Exception as e:
print_colored(f"⚠️ Error launching Chrome: {e}", YELLOW)
input("Press Enter when Chrome is running in debug mode...")
return None


def step_1_monitor_browser(cdp_captures_dir: Path) -> bool:
"""Step 1: Monitor browser activity (launches Chrome if needed)."""
print_header("Step 1: Monitor Browser Activity")
Expand All @@ -151,15 +42,6 @@ def step_1_monitor_browser(cdp_captures_dir: Path) -> bool:
print_colored(f"⏭️ Using existing captures from: {cdp_captures_dir}", GREEN)
return True

# Launch Chrome if not already running
if check_chrome_running(PORT):
print_colored(f"✅ Chrome is already running on port {PORT}", GREEN)
else:
launch_chrome(PORT)
if not check_chrome_running(PORT):
print_colored("❌ Chrome is not running. Cannot continue.", YELLOW)
return False

# Check for existing data
if cdp_captures_dir.exists() and any(cdp_captures_dir.iterdir()):
print_colored(f"⚠️ Directory {cdp_captures_dir} contains existing data.", YELLOW)
Expand All @@ -169,23 +51,31 @@ def step_1_monitor_browser(cdp_captures_dir: Path) -> bool:

print()
print_colored("📋 Instructions:", YELLOW)
print(" 1. A new Chrome tab will open")
print(" 1. Chrome will launch (if not already running)")
print(" 2. Navigate to your target website")
print(" 3. Perform the actions you want to automate")
print(" 4. Press Ctrl+C when done")
print()
input("Press Enter to start monitoring...")
print()

# Launch Chrome if not already running
if check_chrome_running(PORT):
print_colored(f"✅ Chrome is already running on port {PORT}", GREEN)
else:
launch_chrome(PORT)
if not check_chrome_running(PORT):
print_colored("❌ Chrome is not running. Cannot continue.", YELLOW)
return False

print("🔍 Starting browser monitor...")
print_colored(f" Output directory: {cdp_captures_dir}", BLUE)
print()

monitor = BrowserMonitor(
remote_debugging_address=REMOTE_DEBUGGING_ADDRESS,
output_dir=str(cdp_captures_dir),
url="about:blank",
incognito=True,
create_tab=False,
)

try:
Expand All @@ -194,8 +84,8 @@ def step_1_monitor_browser(cdp_captures_dir: Path) -> bool:
print_colored(" Press Ctrl+C when done...", YELLOW)
print()

# Wait for user to press Ctrl+C
while True:
# Wait for user to press Ctrl+C or tab to close
while monitor.is_alive:
time.sleep(1)

except KeyboardInterrupt:
Expand All @@ -218,7 +108,7 @@ def step_2_discover_routine(
hacker: WebHacker,
cdp_captures_dir: Path,
discovery_output_dir: Path,
) -> Optional[Routine]:
) -> Routine | None:
"""Step 2: Discover routine from captured data."""
print_header("Step 2: Discover Routine")

Expand Down
Loading