mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-07-10 22:32:16 +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."""
|
"""One typed verb; the source of truth the doors (05) and agent (07) read."""
|
||||||
|
|
||||||
name: str
|
name: str
|
||||||
|
description: str
|
||||||
input_schema: type[BaseModel]
|
input_schema: type[BaseModel]
|
||||||
output_schema: type[BaseModel]
|
output_schema: type[BaseModel]
|
||||||
executor: Executor
|
executor: Executor
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,12 @@ from app.capabilities.web.discover.schemas import DiscoverInput, DiscoverOutput
|
||||||
|
|
||||||
WEB_DISCOVER = Capability(
|
WEB_DISCOVER = Capability(
|
||||||
name="web.discover",
|
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,
|
input_schema=DiscoverInput,
|
||||||
output_schema=DiscoverOutput,
|
output_schema=DiscoverOutput,
|
||||||
executor=build_discover_executor(),
|
executor=build_discover_executor(),
|
||||||
|
|
|
||||||
|
|
@ -2,20 +2,28 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
|
||||||
class DiscoverInput(BaseModel):
|
class DiscoverInput(BaseModel):
|
||||||
query: str
|
query: str = Field(
|
||||||
top_k: int = 10
|
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):
|
class DiscoverHit(BaseModel):
|
||||||
url: str
|
url: str = Field(
|
||||||
title: str
|
description="The result's page URL; pass it to web.scrape to read it."
|
||||||
snippet: str | None = None
|
)
|
||||||
provider: str
|
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):
|
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(
|
WEB_SCRAPE = Capability(
|
||||||
name="web.scrape",
|
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,
|
input_schema=ScrapeInput,
|
||||||
output_schema=ScrapeOutput,
|
output_schema=ScrapeOutput,
|
||||||
executor=build_scrape_executor(),
|
executor=build_scrape_executor(),
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,21 @@ MAX_SCRAPE_URLS = 20
|
||||||
|
|
||||||
|
|
||||||
class ScrapeInput(BaseModel):
|
class ScrapeInput(BaseModel):
|
||||||
urls: list[str] = Field(min_length=1, max_length=MAX_SCRAPE_URLS)
|
urls: list[str] = Field(
|
||||||
max_length: int = 50_000
|
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
|
@property
|
||||||
def estimated_units(self) -> int:
|
def estimated_units(self) -> int:
|
||||||
|
|
@ -21,15 +34,28 @@ class ScrapeInput(BaseModel):
|
||||||
|
|
||||||
|
|
||||||
class ScrapeRow(BaseModel):
|
class ScrapeRow(BaseModel):
|
||||||
url: str
|
url: str = Field(description="The requested URL this result is for.")
|
||||||
status: Literal["success", "empty", "failed"]
|
status: Literal["success", "empty", "failed"] = Field(
|
||||||
content: str | None = None
|
description=(
|
||||||
metadata: dict[str, str] | None = None
|
"'success' = content returned; 'empty' = page reached but no "
|
||||||
error: str | None = None
|
"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):
|
class ScrapeOutput(BaseModel):
|
||||||
rows: list[ScrapeRow]
|
rows: list[ScrapeRow] = Field(
|
||||||
|
description="One result per requested URL, in the same order."
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def billable_units(self) -> int:
|
def billable_units(self) -> int:
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ async def _echo_executor(payload: _EchoInput) -> _EchoOutput:
|
||||||
|
|
||||||
_ECHO = Capability(
|
_ECHO = Capability(
|
||||||
name="test.echo",
|
name="test.echo",
|
||||||
|
description="Echo the input back for tests.",
|
||||||
input_schema=_EchoInput,
|
input_schema=_EchoInput,
|
||||||
output_schema=_EchoOutput,
|
output_schema=_EchoOutput,
|
||||||
executor=_echo_executor,
|
executor=_echo_executor,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue