mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-07-08 22:22:17 +02:00
feat(capabilities): document verbs with descriptions and field docs
This commit is contained in:
parent
b1bd35c082
commit
23802a74bb
6 changed files with 64 additions and 16 deletions
|
|
@ -48,6 +48,7 @@ class Capability:
|
|||
"""One typed verb; the source of truth the doors (05) and agent (07) read."""
|
||||
|
||||
name: str
|
||||
description: str
|
||||
input_schema: type[BaseModel]
|
||||
output_schema: type[BaseModel]
|
||||
executor: Executor
|
||||
|
|
|
|||
|
|
@ -9,6 +9,12 @@ from app.capabilities.web.discover.schemas import DiscoverInput, DiscoverOutput
|
|||
|
||||
WEB_DISCOVER = Capability(
|
||||
name="web.discover",
|
||||
description=(
|
||||
"Search the web for a query and return ranked results. Use it to find "
|
||||
"pages when you don't already have exact URLs. Returns a list of hits "
|
||||
"(url, title, snippet, provider); pass the chosen url(s) to web.scrape "
|
||||
"to read their full content."
|
||||
),
|
||||
input_schema=DiscoverInput,
|
||||
output_schema=DiscoverOutput,
|
||||
executor=build_discover_executor(),
|
||||
|
|
|
|||
|
|
@ -2,20 +2,28 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from pydantic import BaseModel
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class DiscoverInput(BaseModel):
|
||||
query: str
|
||||
top_k: int = 10
|
||||
query: str = Field(
|
||||
description="What to search the web for, phrased in natural language."
|
||||
)
|
||||
top_k: int = Field(
|
||||
default=10, description="Maximum number of results to return (1-50)."
|
||||
)
|
||||
|
||||
|
||||
class DiscoverHit(BaseModel):
|
||||
url: str
|
||||
title: str
|
||||
snippet: str | None = None
|
||||
provider: str
|
||||
url: str = Field(
|
||||
description="The result's page URL; pass it to web.scrape to read it."
|
||||
)
|
||||
title: str = Field(description="The result's page title.")
|
||||
snippet: str | None = Field(
|
||||
default=None, description="A short extract summarizing the page."
|
||||
)
|
||||
provider: str = Field(description="Which search engine returned this hit.")
|
||||
|
||||
|
||||
class DiscoverOutput(BaseModel):
|
||||
hits: list[DiscoverHit]
|
||||
hits: list[DiscoverHit] = Field(description="Ranked search results, best first.")
|
||||
|
|
|
|||
|
|
@ -9,6 +9,12 @@ from app.capabilities.web.scrape.schemas import ScrapeInput, ScrapeOutput
|
|||
|
||||
WEB_SCRAPE = Capability(
|
||||
name="web.scrape",
|
||||
description=(
|
||||
"Fetch one or more web pages and return their clean, readable content. "
|
||||
"Give it the exact URLs to read (use web.discover first if you don't have "
|
||||
"them). Returns one row per URL with a status (success/empty/failed), the "
|
||||
"page content, and metadata such as title and description."
|
||||
),
|
||||
input_schema=ScrapeInput,
|
||||
output_schema=ScrapeOutput,
|
||||
executor=build_scrape_executor(),
|
||||
|
|
|
|||
|
|
@ -11,8 +11,21 @@ MAX_SCRAPE_URLS = 20
|
|||
|
||||
|
||||
class ScrapeInput(BaseModel):
|
||||
urls: list[str] = Field(min_length=1, max_length=MAX_SCRAPE_URLS)
|
||||
max_length: int = 50_000
|
||||
urls: list[str] = Field(
|
||||
min_length=1,
|
||||
max_length=MAX_SCRAPE_URLS,
|
||||
description=(
|
||||
"Full page URLs to fetch and read (1-20), each starting with "
|
||||
"http:// or https://. Pass the exact URLs you want the content of."
|
||||
),
|
||||
)
|
||||
max_length: int = Field(
|
||||
default=50_000,
|
||||
description=(
|
||||
"Maximum characters of cleaned content returned per page; "
|
||||
"content longer than this is truncated."
|
||||
),
|
||||
)
|
||||
|
||||
@property
|
||||
def estimated_units(self) -> int:
|
||||
|
|
@ -21,15 +34,28 @@ class ScrapeInput(BaseModel):
|
|||
|
||||
|
||||
class ScrapeRow(BaseModel):
|
||||
url: str
|
||||
status: Literal["success", "empty", "failed"]
|
||||
content: str | None = None
|
||||
metadata: dict[str, str] | None = None
|
||||
error: str | None = None
|
||||
url: str = Field(description="The requested URL this result is for.")
|
||||
status: Literal["success", "empty", "failed"] = Field(
|
||||
description=(
|
||||
"'success' = content returned; 'empty' = page reached but no "
|
||||
"readable content; 'failed' = could not be fetched (see error)."
|
||||
)
|
||||
)
|
||||
content: str | None = Field(
|
||||
default=None, description="Cleaned, readable page text (present on success)."
|
||||
)
|
||||
metadata: dict[str, str] | None = Field(
|
||||
default=None, description="Page metadata such as title and description."
|
||||
)
|
||||
error: str | None = Field(
|
||||
default=None, description="Why the fetch failed (present on 'failed')."
|
||||
)
|
||||
|
||||
|
||||
class ScrapeOutput(BaseModel):
|
||||
rows: list[ScrapeRow]
|
||||
rows: list[ScrapeRow] = Field(
|
||||
description="One result per requested URL, in the same order."
|
||||
)
|
||||
|
||||
@property
|
||||
def billable_units(self) -> int:
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ async def _echo_executor(payload: _EchoInput) -> _EchoOutput:
|
|||
|
||||
_ECHO = Capability(
|
||||
name="test.echo",
|
||||
description="Echo the input back for tests.",
|
||||
input_schema=_EchoInput,
|
||||
output_schema=_EchoOutput,
|
||||
executor=_echo_executor,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue