From bbd81bcc99564693103f9813a3a72c7805c7d0ae Mon Sep 17 00:00:00 2001 From: CREDO23 Date: Wed, 1 Jul 2026 16:42:47 +0200 Subject: [PATCH] feat(capabilities): add web.scrape schemas --- .../app/capabilities/web/__init__.py | 5 ++++ .../app/capabilities/web/scrape/__init__.py | 3 ++ .../app/capabilities/web/scrape/schemas.py | 29 +++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 surfsense_backend/app/capabilities/web/__init__.py create mode 100644 surfsense_backend/app/capabilities/web/scrape/__init__.py create mode 100644 surfsense_backend/app/capabilities/web/scrape/schemas.py diff --git a/surfsense_backend/app/capabilities/web/__init__.py b/surfsense_backend/app/capabilities/web/__init__.py new file mode 100644 index 000000000..d6df4107d --- /dev/null +++ b/surfsense_backend/app/capabilities/web/__init__.py @@ -0,0 +1,5 @@ +"""``web.*`` namespace: the generic web scraping verbs.""" + +from __future__ import annotations + +from app.capabilities.web.scrape import definition # noqa: F401 — registers web.scrape diff --git a/surfsense_backend/app/capabilities/web/scrape/__init__.py b/surfsense_backend/app/capabilities/web/scrape/__init__.py new file mode 100644 index 000000000..0a21b156e --- /dev/null +++ b/surfsense_backend/app/capabilities/web/scrape/__init__.py @@ -0,0 +1,3 @@ +"""``web.scrape`` verb: a URL array → one cleaned row per URL.""" + +from __future__ import annotations diff --git a/surfsense_backend/app/capabilities/web/scrape/schemas.py b/surfsense_backend/app/capabilities/web/scrape/schemas.py new file mode 100644 index 000000000..3e77dd56b --- /dev/null +++ b/surfsense_backend/app/capabilities/web/scrape/schemas.py @@ -0,0 +1,29 @@ +"""``web.scrape`` I/O contracts.""" + +from __future__ import annotations + +from typing import Literal + +from pydantic import BaseModel + + +class ScrapeInput(BaseModel): + urls: list[str] + max_length: int = 50_000 + + +class ScrapeRow(BaseModel): + url: str + status: Literal["success", "empty", "failed"] + content: str | None = None + metadata: dict[str, str] | None = None + error: str | None = None + + +class ScrapeOutput(BaseModel): + rows: list[ScrapeRow] + + @property + def billable_units(self) -> int: + """One billable unit per successful scrape.""" + return sum(1 for row in self.rows if row.status == "success")