"""Company-enrichment provider interface. Answers "what does a paid, first-party data vendor already know about this company?" - a richer, metered complement to the free SearchProvider/LLM discovery pipeline (app/services/discovery_service.py), never a replacement for it. Every method here maps to one NinjaPear (nubela.co) API endpoint; orchestration (call order, the leadership-lookup cap, partial-failure handling) lives in app/services/enrichment_service.py, not here - this Protocol is a dumb I/O layer, matching app/search/base.py's shape. """ from __future__ import annotations from typing import Protocol from pydantic import BaseModel, Field class LeadershipMember(BaseModel): name: str title: str | None = None work_email: str | None = None profile_url: str | None = None bio: str | None = None class CompanyDetails(BaseModel): description: str | None = None industry: str | None = None founded_year: int | None = None specialties: list[str] = Field(default_factory=list) leadership_team: list[LeadershipMember] = Field(default_factory=list) employee_count_range: str | None = None class FundingRound(BaseModel): round_name: str | None = None amount: str | None = None date: str | None = None investors: list[str] = Field(default_factory=list) class CompanyFunding(BaseModel): total_raised: str | None = None rounds: list[FundingRound] = Field(default_factory=list) class CompetitorWithReason(BaseModel): name: str reason: str | None = None class Product(BaseModel): name: str description: str | None = None category: str | None = None class RecentUpdate(BaseModel): type: str text: str url: str | None = None date: str | None = None class Customer(BaseModel): name: str relationship: str | None = None class EnrichmentProvider(Protocol): provider_name: str async def get_company_details(self, name: str, website: str | None) -> CompanyDetails: ... async def get_funding(self, name: str, website: str | None) -> CompanyFunding: ... async def get_updates(self, name: str, website: str | None) -> list[RecentUpdate]: ... async def get_competitors( self, name: str, website: str | None ) -> list[CompetitorWithReason]: ... async def get_products(self, name: str, website: str | None) -> list[Product]: ... async def get_customers(self, name: str, website: str | None) -> list[Customer]: ... async def get_work_email(self, person_name: str, company_website: str) -> str | None: ... async def get_person_profile( self, person_name: str, company_website: str ) -> tuple[str | None, str | None]: """Returns (profile_url, bio).""" ...