first commit

This commit is contained in:
nasir@endelospay.com
2025-08-12 02:54:17 +05:00
commit d97cad1736
225 changed files with 137626 additions and 0 deletions

View File

@@ -0,0 +1,365 @@
#!/usr/bin/env python3
"""
Browser Action Debugging Utility
This utility helps debug browser automation issues by:
1. Testing MCP server connectivity
2. Validating browser state
3. Testing selector discovery and execution
4. Providing detailed logging for troubleshooting
"""
import asyncio
import logging
import json
import sys
from typing import Dict, Any, List
from mcp_chrome_client import MCPChromeClient
# Configure logging
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler(sys.stdout),
logging.FileHandler('browser_debug.log')
]
)
logger = logging.getLogger(__name__)
class BrowserActionDebugger:
"""Debug utility for browser automation issues"""
def __init__(self, config: Dict[str, Any]):
self.config = config
self.client = MCPChromeClient(config)
self.logger = logging.getLogger(__name__)
async def run_full_diagnostic(self) -> Dict[str, Any]:
"""Run a comprehensive diagnostic of browser automation"""
results = {
"connectivity": None,
"browser_state": None,
"page_content": None,
"interactive_elements": None,
"selector_tests": [],
"action_tests": []
}
try:
# Test 1: MCP Server Connectivity
self.logger.info("🔍 TEST 1: Testing MCP server connectivity...")
results["connectivity"] = await self._test_connectivity()
# Test 2: Browser State
self.logger.info("🔍 TEST 2: Checking browser state...")
results["browser_state"] = await self._test_browser_state()
# Test 3: Page Content
self.logger.info("🔍 TEST 3: Getting page content...")
results["page_content"] = await self._test_page_content()
# Test 4: Interactive Elements
self.logger.info("🔍 TEST 4: Finding interactive elements...")
results["interactive_elements"] = await self._test_interactive_elements()
# Test 5: Selector Generation
self.logger.info("🔍 TEST 5: Testing selector generation...")
results["selector_tests"] = await self._test_selector_generation()
# Test 6: Action Execution
self.logger.info("🔍 TEST 6: Testing action execution...")
results["action_tests"] = await self._test_action_execution()
except Exception as e:
self.logger.error(f"💥 Diagnostic failed: {e}")
results["error"] = str(e)
return results
async def _test_connectivity(self) -> Dict[str, Any]:
"""Test MCP server connectivity"""
try:
await self.client.connect()
return {
"status": "success",
"server_type": self.client.server_type,
"server_url": self.client.server_url,
"connected": self.client.session is not None
}
except Exception as e:
return {
"status": "failed",
"error": str(e)
}
async def _test_browser_state(self) -> Dict[str, Any]:
"""Test browser state and availability"""
try:
# Try to get current URL
result = await self.client._call_mcp_tool("chrome_get_web_content", {
"format": "text",
"selector": "title"
})
return {
"status": "success",
"browser_available": True,
"page_title": result.get("content", [{}])[0].get("text", "Unknown") if result.get("content") else "Unknown"
}
except Exception as e:
return {
"status": "failed",
"browser_available": False,
"error": str(e)
}
async def _test_page_content(self) -> Dict[str, Any]:
"""Test page content retrieval"""
try:
result = await self.client._call_mcp_tool("chrome_get_web_content", {
"format": "text"
})
content = result.get("content", [])
if content and len(content) > 0:
text_content = content[0].get("text", "")
return {
"status": "success",
"content_length": len(text_content),
"has_content": len(text_content) > 0,
"preview": text_content[:200] + "..." if len(text_content) > 200 else text_content
}
else:
return {
"status": "success",
"content_length": 0,
"has_content": False,
"preview": ""
}
except Exception as e:
return {
"status": "failed",
"error": str(e)
}
async def _test_interactive_elements(self) -> Dict[str, Any]:
"""Test interactive element discovery"""
try:
result = await self.client._call_mcp_tool("chrome_get_interactive_elements", {
"types": ["button", "a", "input", "select", "textarea"]
})
elements = result.get("elements", [])
# Analyze elements
element_summary = {}
for element in elements:
tag = element.get("tagName", "unknown").lower()
element_summary[tag] = element_summary.get(tag, 0) + 1
return {
"status": "success",
"total_elements": len(elements),
"element_types": element_summary,
"sample_elements": elements[:5] if elements else []
}
except Exception as e:
return {
"status": "failed",
"error": str(e)
}
async def _test_selector_generation(self) -> List[Dict[str, Any]]:
"""Test selector generation for various elements"""
tests = []
try:
# Get interactive elements first
result = await self.client._call_mcp_tool("chrome_get_interactive_elements", {
"types": ["button", "a", "input"]
})
elements = result.get("elements", [])[:5] # Test first 5 elements
for i, element in enumerate(elements):
test_result = {
"element_index": i,
"element_tag": element.get("tagName", "unknown"),
"element_text": element.get("textContent", "")[:50],
"element_attributes": element.get("attributes", {}),
"generated_selector": None,
"selector_valid": False
}
try:
# Generate selector
selector = self.client._extract_best_selector(element)
test_result["generated_selector"] = selector
# Test if selector is valid by trying to use it
validation_result = await self.client._call_mcp_tool("chrome_get_web_content", {
"selector": selector,
"textOnly": False
})
test_result["selector_valid"] = validation_result.get("content") is not None
except Exception as e:
test_result["error"] = str(e)
tests.append(test_result)
except Exception as e:
tests.append({
"error": f"Failed to get elements for selector testing: {e}"
})
return tests
async def _test_action_execution(self) -> List[Dict[str, Any]]:
"""Test action execution with safe, non-destructive actions"""
tests = []
# Test 1: Try to get page title (safe action)
test_result = {
"action": "get_page_title",
"description": "Safe action to get page title",
"status": None,
"error": None
}
try:
result = await self.client._call_mcp_tool("chrome_get_web_content", {
"selector": "title",
"textOnly": True
})
test_result["status"] = "success"
test_result["result"] = result
except Exception as e:
test_result["status"] = "failed"
test_result["error"] = str(e)
tests.append(test_result)
# Test 2: Try keyboard action (safe - just Escape key)
test_result = {
"action": "keyboard_escape",
"description": "Safe keyboard action (Escape key)",
"status": None,
"error": None
}
try:
result = await self.client._call_mcp_tool("chrome_keyboard", {
"keys": "Escape"
})
test_result["status"] = "success"
test_result["result"] = result
except Exception as e:
test_result["status"] = "failed"
test_result["error"] = str(e)
tests.append(test_result)
return tests
async def test_specific_selector(self, selector: str) -> Dict[str, Any]:
"""Test a specific selector"""
self.logger.info(f"🔍 Testing specific selector: {selector}")
result = {
"selector": selector,
"validation": None,
"click_test": None
}
try:
# Test 1: Validate selector exists
validation = await self.client._call_mcp_tool("chrome_get_web_content", {
"selector": selector,
"textOnly": False
})
result["validation"] = {
"status": "success" if validation.get("content") else "not_found",
"content": validation.get("content")
}
# Test 2: Try clicking (only if element was found)
if validation.get("content"):
try:
click_result = await self.client._call_mcp_tool("chrome_click_element", {
"selector": selector
})
result["click_test"] = {
"status": "success",
"result": click_result
}
except Exception as click_error:
result["click_test"] = {
"status": "failed",
"error": str(click_error)
}
else:
result["click_test"] = {
"status": "skipped",
"reason": "Element not found"
}
except Exception as e:
result["validation"] = {
"status": "failed",
"error": str(e)
}
return result
async def cleanup(self):
"""Cleanup resources"""
try:
await self.client.disconnect()
except Exception as e:
self.logger.warning(f"Cleanup warning: {e}")
async def main():
"""Main function for running diagnostics"""
# Default configuration - adjust as needed
config = {
'mcp_server_type': 'http',
'mcp_server_url': 'http://localhost:3000/mcp',
'mcp_server_command': '',
'mcp_server_args': []
}
debugger = BrowserActionDebugger(config)
try:
print("🚀 Starting Browser Action Diagnostics...")
results = await debugger.run_full_diagnostic()
print("\n" + "="*60)
print("📊 DIAGNOSTIC RESULTS")
print("="*60)
for test_name, test_result in results.items():
print(f"\n{test_name.upper()}:")
print(json.dumps(test_result, indent=2, default=str))
# Save results to file
with open('browser_diagnostic_results.json', 'w') as f:
json.dump(results, f, indent=2, default=str)
print(f"\n✅ Diagnostics complete! Results saved to browser_diagnostic_results.json")
except Exception as e:
print(f"💥 Diagnostic failed: {e}")
finally:
await debugger.cleanup()
if __name__ == "__main__":
asyncio.run(main())