refactor(instagram): simplify scrape and details capability schemas

This commit is contained in:
Anish Sarkar 2026-07-11 02:20:46 +05:30
parent 8afa4c6fc6
commit de1990f9f6
3 changed files with 21 additions and 28 deletions

View file

@ -1,13 +1,14 @@
"""``instagram.details`` I/O contracts. """``instagram.details`` I/O contracts.
A lean surface over ``InstagramScrapeInput`` (``resultsType="details"``). Each A lean surface over ``InstagramScrapeInput`` (``resultsType="details"``). Each
output item is a profile / hashtag / place, discriminated by the synthesized output item is a profile (``detailKind="profile"``, a SurfSense addition; every
``detailKind`` field (a SurfSense addition; every other field mirrors the actor). other field mirrors the actor). Hashtag/place details are login-walled and
therefore unsupported.
""" """
from __future__ import annotations from __future__ import annotations
from typing import Annotated, Literal from typing import Literal
from pydantic import BaseModel, Field, model_validator from pydantic import BaseModel, Field, model_validator
@ -15,16 +16,9 @@ from app.capabilities.instagram.scrape.schemas import (
MAX_INSTAGRAM_ITEMS, MAX_INSTAGRAM_ITEMS,
MAX_INSTAGRAM_SOURCES, MAX_INSTAGRAM_SOURCES,
) )
from app.proprietary.platforms.instagram import ( from app.proprietary.platforms.instagram import InstagramProfile
InstagramHashtag,
InstagramPlace,
InstagramProfile,
)
InstagramDetailItem = Annotated[ InstagramDetailItem = InstagramProfile
InstagramProfile | InstagramHashtag | InstagramPlace,
Field(discriminator="detailKind"),
]
class DetailsInput(BaseModel): class DetailsInput(BaseModel):
@ -32,18 +26,17 @@ class DetailsInput(BaseModel):
default_factory=list, default_factory=list,
max_length=MAX_INSTAGRAM_SOURCES, max_length=MAX_INSTAGRAM_SOURCES,
description=( description=(
"Profile / hashtag / place URLs (or bare profile IDs). The URL type " "Profile URLs or bare profile IDs. Provide these OR search_queries."
"determines the detail kind. Provide these OR search_queries."
), ),
) )
search_queries: list[str] = Field( search_queries: list[str] = Field(
default_factory=list, default_factory=list,
max_length=MAX_INSTAGRAM_SOURCES, max_length=MAX_INSTAGRAM_SOURCES,
description="Discovery keywords. Provide these OR urls (never both).", description="Discovery keywords resolved to profiles. Provide these OR urls.",
) )
search_type: Literal["hashtag", "profile", "place"] = Field( search_type: Literal["profile", "user"] = Field(
default="hashtag", default="profile",
description="What to discover from search_queries (no 'user' — use instagram.scrape).", description="Discovery kind (profile-only; hashtag/place are login-walled).",
) )
search_limit: int = Field( search_limit: int = Field(
default=10, default=10,
@ -78,7 +71,7 @@ class DetailsInput(BaseModel):
class DetailsOutput(BaseModel): class DetailsOutput(BaseModel):
items: list[InstagramDetailItem] = Field( items: list[InstagramDetailItem] = Field(
default_factory=list, default_factory=list,
description="One item per profile/hashtag/place, keyed by detailKind.", description="One profile detail item per resolved profile.",
) )
@property @property

View file

@ -10,8 +10,8 @@ from app.capabilities.instagram.scrape.schemas import ScrapeInput, ScrapeOutput
INSTAGRAM_SCRAPE = Capability( INSTAGRAM_SCRAPE = Capability(
name="instagram.scrape", name="instagram.scrape",
description=( description=(
"Scrape public Instagram posts, reels, or mentions from " "Scrape public Instagram posts, reels, or mentions from profile/post/"
"profile/post/hashtag/place URLs, or discover content via search queries." "reel URLs, or discover public profiles via search queries."
), ),
input_schema=ScrapeInput, input_schema=ScrapeInput,
output_schema=ScrapeOutput, output_schema=ScrapeOutput,

View file

@ -26,8 +26,8 @@ class ScrapeInput(BaseModel):
default_factory=list, default_factory=list,
max_length=MAX_INSTAGRAM_SOURCES, max_length=MAX_INSTAGRAM_SOURCES,
description=( description=(
"Instagram URLs or bare profile IDs: profile, post (/p/), reel " "Instagram URLs or bare profile IDs: profile, post (/p/), or reel "
"(/reel/), hashtag (/explore/tags/), or place (/explore/locations/). " "(/reel/). Hashtag/place URLs are unsupported (login-walled). "
"Provide these OR search_queries (never both)." "Provide these OR search_queries (never both)."
), ),
) )
@ -35,13 +35,13 @@ class ScrapeInput(BaseModel):
default_factory=list, default_factory=list,
max_length=MAX_INSTAGRAM_SOURCES, max_length=MAX_INSTAGRAM_SOURCES,
description=( description=(
"Discovery keywords (hashtags as plaintext, no '#'). Provide these " "Discovery keywords resolved to profiles via Google (IG's keyword "
"OR urls (never both)." "search is login-walled). Provide these OR urls (never both)."
), ),
) )
search_type: Literal["hashtag", "profile", "place", "user"] = Field( search_type: Literal["profile", "user"] = Field(
default="hashtag", default="profile",
description="What to discover from search_queries. Only used with search_queries.", description="Discovery kind (profile-only; hashtag/place are login-walled).",
) )
result_type: Literal["posts", "reels", "mentions"] = Field( result_type: Literal["posts", "reels", "mentions"] = Field(
default="posts", default="posts",