|
|
|
|
|
""" |
|
|
Hunter Agent - Discovers companies dynamically |
|
|
Now uses web search to find company information instead of static files |
|
|
""" |
|
|
import json |
|
|
from typing import List, Optional |
|
|
from app.schema import Company, Prospect |
|
|
from app.config import COMPANIES_FILE, SKIP_WEB_SEARCH |
|
|
from services.company_discovery import get_company_discovery_service |
|
|
import logging |
|
|
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
|
|
|
class Hunter: |
|
|
""" |
|
|
Discovers companies and creates prospects dynamically |
|
|
|
|
|
NEW: Can now discover companies from user input (company names) |
|
|
LEGACY: Still supports loading from seed file for backwards compatibility |
|
|
""" |
|
|
|
|
|
def __init__(self, mcp_registry): |
|
|
self.mcp = mcp_registry |
|
|
self.store = mcp_registry.get_store_client() |
|
|
self.discovery = get_company_discovery_service() |
|
|
|
|
|
async def run( |
|
|
self, |
|
|
company_names: Optional[List[str]] = None, |
|
|
company_ids: Optional[List[str]] = None, |
|
|
use_seed_file: bool = False |
|
|
) -> List[Prospect]: |
|
|
""" |
|
|
Discover companies and create prospects |
|
|
|
|
|
Args: |
|
|
company_names: List of company names to discover (NEW - dynamic mode) |
|
|
company_ids: List of company IDs from seed file (LEGACY - static mode) |
|
|
use_seed_file: If True, load from seed file instead of discovery |
|
|
|
|
|
Returns: |
|
|
List of Prospect objects |
|
|
""" |
|
|
prospects = [] |
|
|
|
|
|
|
|
|
if company_names and not use_seed_file: |
|
|
logger.info(f"Hunter: Dynamic discovery mode - discovering {len(company_names)} companies") |
|
|
|
|
|
for company_name in company_names: |
|
|
try: |
|
|
logger.info(f"Hunter: Discovering '{company_name}'...") |
|
|
|
|
|
|
|
|
company = await self.discovery.discover_company(company_name, skip_search=SKIP_WEB_SEARCH) |
|
|
|
|
|
if not company: |
|
|
logger.warning(f"Hunter: Could not discover company '{company_name}'") |
|
|
|
|
|
company = self._create_fallback_company(company_name) |
|
|
|
|
|
|
|
|
prospect = Prospect( |
|
|
id=company.id, |
|
|
company=company, |
|
|
status="new" |
|
|
) |
|
|
|
|
|
|
|
|
await self.store.save_prospect(prospect) |
|
|
prospects.append(prospect) |
|
|
|
|
|
logger.info(f"Hunter: Successfully created prospect for '{company_name}'") |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"Hunter: Error discovering '{company_name}': {str(e)}") |
|
|
|
|
|
company = self._create_fallback_company(company_name) |
|
|
prospect = Prospect( |
|
|
id=company.id, |
|
|
company=company, |
|
|
status="new" |
|
|
) |
|
|
await self.store.save_prospect(prospect) |
|
|
prospects.append(prospect) |
|
|
|
|
|
|
|
|
else: |
|
|
logger.info("Hunter: Legacy mode - loading from seed file") |
|
|
|
|
|
try: |
|
|
|
|
|
with open(COMPANIES_FILE) as f: |
|
|
companies_data = json.load(f) |
|
|
|
|
|
for company_data in companies_data: |
|
|
|
|
|
if company_ids and company_data["id"] not in company_ids: |
|
|
continue |
|
|
|
|
|
company = Company(**company_data) |
|
|
|
|
|
|
|
|
prospect = Prospect( |
|
|
id=company.id, |
|
|
company=company, |
|
|
status="new" |
|
|
) |
|
|
|
|
|
|
|
|
await self.store.save_prospect(prospect) |
|
|
prospects.append(prospect) |
|
|
|
|
|
logger.info(f"Hunter: Loaded {len(prospects)} companies from seed file") |
|
|
|
|
|
except FileNotFoundError: |
|
|
logger.error(f"Hunter: Seed file not found: {COMPANIES_FILE}") |
|
|
|
|
|
if not company_names: |
|
|
return [] |
|
|
except Exception as e: |
|
|
logger.error(f"Hunter: Error loading seed file: {str(e)}") |
|
|
return [] |
|
|
|
|
|
return prospects |
|
|
|
|
|
def _create_fallback_company(self, company_name: str) -> Company: |
|
|
"""Create a minimal fallback company when discovery fails""" |
|
|
import re |
|
|
import uuid |
|
|
|
|
|
|
|
|
slug = re.sub(r'[^a-zA-Z0-9]', '', company_name.lower())[:20] |
|
|
company_id = f"{slug}_{str(uuid.uuid4())[:8]}" |
|
|
|
|
|
|
|
|
company = Company( |
|
|
id=company_id, |
|
|
name=company_name, |
|
|
domain=f"{slug}.com", |
|
|
industry="Technology", |
|
|
size=100, |
|
|
pains=[ |
|
|
"Customer experience improvement needed", |
|
|
"Operational efficiency challenges" |
|
|
], |
|
|
notes=[ |
|
|
"Company information discovery in progress", |
|
|
"Limited data available" |
|
|
] |
|
|
) |
|
|
|
|
|
logger.info(f"Hunter: Created fallback company for '{company_name}'") |
|
|
return company |