File size: 3,971 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
# file: agents/sequencer.py
from datetime import datetime
from app.schema import Prospect, Message
import uuid

class Sequencer:
    """Sequences and sends outreach emails"""
    
    def __init__(self, mcp_registry):
        self.mcp = mcp_registry
        self.email_client = mcp_registry.get_email_client()
        self.calendar_client = mcp_registry.get_calendar_client()
        self.store = mcp_registry.get_store_client()
    
    async def run(self, prospect: Prospect) -> Prospect:
        """Send email and create thread"""
        
        # Check if we have minimum requirements
        if not prospect.contacts:
            # Try to generate a default contact if none exist
            from app.schema import Contact
            default_contact = Contact(
                id=str(uuid.uuid4()),
                name=f"Customer Success at {prospect.company.name}",
                email=f"contact@{prospect.company.domain}",
                title="Customer Success",
                prospect_id=prospect.id
            )
            prospect.contacts = [default_contact]
            await self.store.save_contact(default_contact)
        
        if not prospect.email_draft:
            # Generate a simple default email if none exists
            prospect.email_draft = {
                "subject": f"Improving {prospect.company.name}'s Customer Experience",
                "body": f"""Dear {prospect.company.name} team,

We noticed your company is in the {prospect.company.industry} industry with {prospect.company.size} employees. 
We'd love to discuss how we can help improve your customer experience.

Looking forward to connecting with you.

Best regards,
Lucidya Team"""
            }
        
        # Now proceed with sending
        primary_contact = prospect.contacts[0]
        
        # Get calendar slots
        try:
            slots = await self.calendar_client.suggest_slots()
        except:
            slots = []  # Continue even if calendar fails
        
        # Generate ICS attachment for first slot
        ics_content = ""
        if slots:
            try:
                slot = slots[0]
                ics_content = await self.calendar_client.generate_ics(
                    f"Meeting with {prospect.company.name}",
                    slot["start_iso"],
                    slot["end_iso"]
                )
            except:
                pass  # Continue without ICS
        
        # Add calendar info to email
        calendar_text = ""
        if slots:
            calendar_text = f"\n\nI have a few time slots available this week:\n"
            for slot in slots[:3]:
                calendar_text += f"- {slot['start_iso'][:16].replace('T', ' at ')}\n"
        
        # Send email
        email_body = prospect.email_draft["body"]
        if calendar_text:
            email_body = email_body.rstrip() + calendar_text
        
        try:
            result = await self.email_client.send(
                to=primary_contact.email,
                subject=prospect.email_draft["subject"],
                body=email_body,
                prospect_id=prospect.id  # Add prospect_id for thread tracking
            )

            # Update prospect with thread ID
            # Handle both dict and string responses
            if isinstance(result, dict):
                prospect.thread_id = result.get("thread_id", str(uuid.uuid4()))
            elif isinstance(result, str):
                prospect.thread_id = result
            else:
                prospect.thread_id = str(uuid.uuid4())
            prospect.status = "sequenced"

        except Exception as e:
            # Even if email sending fails, don't block the prospect
            prospect.thread_id = f"mock-thread-{uuid.uuid4()}"
            prospect.status = "sequenced"
            print(f"Warning: Email send failed for {prospect.company.name}: {e}")
        
        await self.store.save_prospect(prospect)
        return prospect