File size: 2,472 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
# file: app/schema.py
from datetime import datetime
from typing import List, Optional, Dict, Any
from pydantic import BaseModel, Field, EmailStr

class Company(BaseModel):
    id: Optional[str] = None  # Auto-generated if not provided
    name: str
    domain: str
    industry: str
    size: Optional[str] = None  # Changed to string to accept "500-1000 employees" format
    pains: List[str] = []
    notes: List[str] = []
    summary: Optional[str] = None

class Contact(BaseModel):
    id: str
    name: str
    email: EmailStr
    title: str
    prospect_id: str

class Fact(BaseModel):
    id: str
    source: str
    text: str
    collected_at: datetime
    ttl_hours: int
    confidence: float
    company_id: str

class Prospect(BaseModel):
    id: str
    company: Company
    contacts: List[Contact] = []
    facts: List[Fact] = []
    fit_score: float = 0.0
    status: str = "new"  # new, enriched, scored, drafted, compliant, sequenced, ready_for_handoff, dropped
    dropped_reason: Optional[str] = None
    summary: Optional[str] = None
    email_draft: Optional[Dict[str, str]] = None
    thread_id: Optional[str] = None

class Message(BaseModel):
    id: str
    thread_id: str
    prospect_id: str
    direction: str  # outbound, inbound
    subject: str
    body: str
    sent_at: datetime

class Thread(BaseModel):
    id: str
    prospect_id: str
    messages: List[Message] = []

class Suppression(BaseModel):
    id: str
    type: str  # email, domain, company
    value: str
    reason: str
    expires_at: Optional[datetime] = None

class HandoffPacket(BaseModel):
    prospect: Prospect
    thread: Optional[Thread]
    calendar_slots: List[Dict[str, str]] = []
    generated_at: datetime

class PipelineEvent(BaseModel):
    ts: datetime
    type: str  # agent_start, agent_log, agent_end, llm_token, llm_done, policy_block, policy_pass
    agent: str
    message: str
    payload: Dict[str, Any] = {}

class PipelineRequest(BaseModel):
    """
    Pipeline request supporting both dynamic and static modes

    NEW: company_names - List of company names to discover dynamically
    LEGACY: company_ids - List of company IDs from seed file (backwards compatible)
    """
    company_names: Optional[List[str]] = None  # NEW: Dynamic discovery mode
    company_ids: Optional[List[str]] = None     # LEGACY: Static mode
    use_seed_file: bool = False                 # Force legacy mode

class WriterStreamRequest(BaseModel):
    company_id: str