feat(capabilities): add web.discover schemas and provider seam

This commit is contained in:
CREDO23 2026-07-01 17:08:58 +02:00
parent a413539f6a
commit fa1055dd4c
6 changed files with 168 additions and 0 deletions

View file

@ -0,0 +1,3 @@
"""``web.discover`` verb: a query → candidate URLs the agent can feed to ``web.scrape``."""
from __future__ import annotations

View file

@ -0,0 +1,40 @@
"""``web.discover`` executor: route a query to the first configured search provider."""
from __future__ import annotations
from collections.abc import Sequence
from app.capabilities.types import Executor
from app.capabilities.web.discover.providers.base import DiscoverProvider
from app.capabilities.web.discover.schemas import DiscoverInput, DiscoverOutput
class NoDiscoverProviderError(RuntimeError):
"""Raised when no search provider is configured (no platform key/host set)."""
def build_discover_executor(
providers: Sequence[DiscoverProvider] | None = None,
) -> Executor:
"""Bind the executor to a provider set (defaults to the real env-keyed providers)."""
registry = list(providers) if providers is not None else _default_providers()
async def execute(payload: DiscoverInput) -> DiscoverOutput:
provider = next((p for p in registry if p.is_available()), None)
if provider is None:
raise NoDiscoverProviderError(
"web.discover has no configured search provider "
"(set a SearXNG host or a Linkup/Baidu key)."
)
hits = await provider.search(payload.query, payload.top_k)
return DiscoverOutput(hits=hits)
return execute
def _default_providers() -> list[DiscoverProvider]:
from app.capabilities.web.discover.providers.baidu import BaiduProvider
from app.capabilities.web.discover.providers.linkup import LinkupProvider
from app.capabilities.web.discover.providers.searxng import SearxngProvider
return [SearxngProvider(), LinkupProvider(), BaiduProvider()]

View file

@ -0,0 +1,3 @@
"""``web.discover`` search providers (env-keyed: SearXNG, Linkup, Baidu)."""
from __future__ import annotations

View file

@ -0,0 +1,22 @@
"""The seam every ``web.discover`` provider implements."""
from __future__ import annotations
from typing import Protocol, runtime_checkable
from app.capabilities.web.discover.schemas import DiscoverHit
@runtime_checkable
class DiscoverProvider(Protocol):
"""An env-keyed search backend that suggests candidate URLs for a query."""
name: str
def is_available(self) -> bool:
"""True when this provider's platform key/host is configured."""
...
async def search(self, query: str, top_k: int) -> list[DiscoverHit]:
"""Return up to ``top_k`` candidate hits for ``query``."""
...

View file

@ -0,0 +1,21 @@
"""``web.discover`` I/O contracts."""
from __future__ import annotations
from pydantic import BaseModel
class DiscoverInput(BaseModel):
query: str
top_k: int = 10
class DiscoverHit(BaseModel):
url: str
title: str
snippet: str | None = None
provider: str
class DiscoverOutput(BaseModel):
hits: list[DiscoverHit]