File size: 5,664 Bytes
8bab08d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# file: agents/hunter.py
"""
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 = []
# Mode 1: Dynamic discovery from company names (NEW)
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}'...")
# Discover company information from web (or use fallback if configured)
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}'")
# Create a minimal fallback company
company = self._create_fallback_company(company_name)
# Create prospect
prospect = Prospect(
id=company.id,
company=company,
status="new"
)
# Save to store
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)}")
# Create fallback and continue
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)
# Mode 2: Legacy mode - load from seed file (BACKWARDS COMPATIBLE)
else:
logger.info("Hunter: Legacy mode - loading from seed file")
try:
# Load from seed file
with open(COMPANIES_FILE) as f:
companies_data = json.load(f)
for company_data in companies_data:
# Filter by IDs if specified
if company_ids and company_data["id"] not in company_ids:
continue
company = Company(**company_data)
# Create prospect
prospect = Prospect(
id=company.id,
company=company,
status="new"
)
# Save to store
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 no seed file and no company names provided, return empty
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
# Generate ID
slug = re.sub(r'[^a-zA-Z0-9]', '', company_name.lower())[:20]
company_id = f"{slug}_{str(uuid.uuid4())[:8]}"
# Create minimal company
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 |