Initial commit: Screen Leads app
Screen-capture lead tool: capture agent, Claude vision extractor with pluggable site recipes (LinkedIn), canonical funnel model, SQLite storage, FastAPI backend, dashboard, and setup/run scripts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
"""SiteRecipe interface. Each supported site implements one of these; adding a
|
||||
new site is a drop-in module registered in ai/recipes/__init__.py — the core
|
||||
capture loop never changes.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Any, Optional
|
||||
|
||||
from core.models import Lead, PageContext, PageMatch
|
||||
|
||||
|
||||
class SiteRecipe(ABC):
|
||||
site_id: str = ""
|
||||
display_name: str = ""
|
||||
enabled: bool = True
|
||||
# Which extracted page_type is a capturable target (e.g. a person's profile).
|
||||
target_page_type: str = "profile"
|
||||
|
||||
@abstractmethod
|
||||
def matches(self, ctx: PageContext) -> Optional[PageMatch]:
|
||||
"""Return a PageMatch if this recipe recognises the page, else None."""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def extraction_schema(self) -> dict[str, Any]:
|
||||
"""JSON schema (structured-output format) for the raw extraction."""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def extraction_prompt(self) -> str:
|
||||
"""Instruction given to the vision model alongside the screenshots."""
|
||||
|
||||
@abstractmethod
|
||||
def to_canonical(self, raw: dict[str, Any]) -> Lead:
|
||||
"""Map this site's raw extraction to the canonical Lead schema."""
|
||||
Reference in New Issue
Block a user