Tidy endpoints
All checks were successful
CI / Build and push Docker image (push) Successful in 1m30s

This commit is contained in:
Tom Foster 2025-06-16 17:02:56 +01:00
parent c1f7cfbe02
commit a49ae56d42
6 changed files with 82 additions and 63 deletions

View file

@ -2,6 +2,8 @@
from __future__ import annotations
from typing import TYPE_CHECKING
from fastapi import FastAPI
from . import __description__, __title__, __version__
@ -9,6 +11,23 @@ from .core.middleware import setup_middleware
from .core.registry import registry
from .models.base import HealthResponse
if TYPE_CHECKING:
from fastapi.routing import APIRoute
def generate_unique_id(route: APIRoute) -> str:
"""Generate a unique ID for a route.
Args:
route (APIRoute): The route to generate an ID for.
Returns:
str: The unique ID for the route.
"""
if route.tags:
return f"{route.tags[0]}_{route.name}"
return route.name
def create_app() -> FastAPI:
"""Create and configure the FastAPI application.
@ -22,6 +41,7 @@ def create_app() -> FastAPI:
description=__description__,
docs_url="/docs",
redoc_url="/redoc",
generate_unique_id_function=generate_unique_id,
)
# Setup middleware

View file

@ -33,7 +33,7 @@ class MemoryTool(BaseTool):
)
@staticmethod
def _create_entities(req: CreateEntitiesRequest) -> list[Entity]:
def create_entities(req: CreateEntitiesRequest) -> list[Entity]:
"""Create multiple entities in the graph.
Returns:
@ -47,7 +47,7 @@ class MemoryTool(BaseTool):
return new_entities
@staticmethod
def _create_relations(req: CreateRelationsRequest) -> list[Relation]:
def create_relations(req: CreateRelationsRequest) -> list[Relation]:
"""Create multiple relations between entities.
Returns:
@ -61,7 +61,7 @@ class MemoryTool(BaseTool):
return new
@staticmethod
def _add_observations(req: AddObservationsRequest) -> list[dict[str, str | list[str]]]:
def add_observations(req: AddObservationsRequest) -> list[dict[str, str | list[str]]]:
"""Add new observations to existing entities.
Returns:
@ -87,7 +87,7 @@ class MemoryTool(BaseTool):
return results
@staticmethod
def _delete_entities(req: DeleteEntitiesRequest) -> dict[str, str]:
def delete_entities(req: DeleteEntitiesRequest) -> dict[str, str]:
"""Delete entities and associated relations.
Returns:
@ -104,7 +104,7 @@ class MemoryTool(BaseTool):
return {"message": "Entities deleted successfully"}
@staticmethod
def _delete_observations(req: DeleteObservationsRequest) -> dict[str, str]:
def delete_observations(req: DeleteObservationsRequest) -> dict[str, str]:
"""Delete specific observations from entities.
Returns:
@ -123,7 +123,7 @@ class MemoryTool(BaseTool):
return {"message": "Observations deleted successfully"}
@staticmethod
def _delete_relations(req: DeleteRelationsRequest) -> dict[str, str]:
def delete_relations(req: DeleteRelationsRequest) -> dict[str, str]:
"""Delete relations from the graph.
Returns:
@ -138,7 +138,7 @@ class MemoryTool(BaseTool):
return {"message": "Relations deleted successfully"}
@staticmethod
def _read_graph() -> KnowledgeGraph:
def read_graph() -> KnowledgeGraph:
"""Read entire knowledge graph.
Returns:
@ -147,7 +147,7 @@ class MemoryTool(BaseTool):
return read_graph_file()
@staticmethod
def _search_nodes(req: SearchNodesRequest) -> KnowledgeGraph:
def search_nodes(req: SearchNodesRequest) -> KnowledgeGraph:
"""Search for nodes by keyword.
Returns:
@ -167,7 +167,7 @@ class MemoryTool(BaseTool):
return KnowledgeGraph(entities=entities, relations=relations)
@staticmethod
def _open_nodes(req: OpenNodesRequest) -> KnowledgeGraph:
def open_nodes(req: OpenNodesRequest) -> KnowledgeGraph:
"""Open specific nodes by name.
Returns:
@ -185,60 +185,60 @@ class MemoryTool(BaseTool):
router.add_api_route(
"/create_entities",
MemoryTool._create_entities,
MemoryTool.create_entities,
methods=["POST"],
summary="Create multiple entities in the graph",
summary="Store new entities (people, places, concepts) with their properties and observations",
)
router.add_api_route(
"/create_relations",
MemoryTool._create_relations,
MemoryTool.create_relations,
methods=["POST"],
summary="Create multiple relations between entities",
summary="Connect entities with relationships (works_at, lives_in, knows, etc.)",
)
router.add_api_route(
"/add_observations",
MemoryTool._add_observations,
MemoryTool.add_observations,
methods=["POST"],
summary="Add new observations to existing entities",
summary="Add new facts or observations to entities you've already stored",
)
router.add_api_route(
"/delete_entities",
MemoryTool._delete_entities,
MemoryTool.delete_entities,
methods=["POST"],
summary="Delete entities and associated relations",
summary="Remove entities and all their connections from memory",
)
router.add_api_route(
"/delete_observations",
MemoryTool._delete_observations,
MemoryTool.delete_observations,
methods=["POST"],
summary="Delete specific observations from entities",
summary="Remove specific facts or observations from entities",
)
router.add_api_route(
"/delete_relations",
MemoryTool._delete_relations,
MemoryTool.delete_relations,
methods=["POST"],
summary="Delete relations from the graph",
summary="Remove specific relationships between entities",
)
router.add_api_route(
"/read_graph",
MemoryTool._read_graph,
MemoryTool.read_graph,
methods=["GET"],
response_model=KnowledgeGraph,
summary="Read entire knowledge graph",
summary="Retrieve all stored entities and relationships from memory",
)
router.add_api_route(
"/search_nodes",
MemoryTool._search_nodes,
MemoryTool.search_nodes,
methods=["POST"],
response_model=KnowledgeGraph,
summary="Search for nodes by keyword",
summary="Find entities by searching names, types, or observations",
)
router.add_api_route(
"/open_nodes",
MemoryTool._open_nodes,
MemoryTool.open_nodes,
methods=["POST"],
response_model=KnowledgeGraph,
summary="Open specific nodes by name",
summary="Retrieve specific entities and their connections by exact name",
)
return router

View file

@ -78,7 +78,7 @@ class SearxngTool(BaseTool):
)
@router.get("/categories", response_model=CategoriesResponse)
def get_categories() -> CategoriesResponse:
def categories() -> CategoriesResponse:
"""Get available search categories from SearXNG.
Returns:
@ -110,7 +110,7 @@ class SearxngTool(BaseTool):
)
@router.get("/engines", response_model=EnginesResponse)
def get_engines() -> EnginesResponse:
def engines() -> EnginesResponse:
"""Get available search engines from SearXNG.
Returns:

View file

@ -143,54 +143,53 @@ class TimeTool(BaseTool):
"""Return the FastAPI router for time tool endpoints."""
router = APIRouter()
router.add_api_route(
"/get_current_utc_time",
self.get_current_utc,
methods=["GET"],
response_model=TimeResponse,
summary="Current UTC time",
@router.get(
"/get_current_utc_time", response_model=TimeResponse, summary="Current UTC time"
)
router.add_api_route(
def get_current_utc() -> TimeResponse:
return TimeTool.get_current_utc()
@router.get(
"/get_current_local_time",
self.get_current_local,
methods=["GET"],
response_model=LocalTimeResponse,
summary="Current Local Time",
)
router.add_api_route(
"/format_time",
self.format_current_time,
methods=["POST"],
response_model=FormattedTimeResponse,
summary="Format current time",
def get_current_local() -> LocalTimeResponse:
return TimeTool.get_current_local()
@router.post(
"/format_time", response_model=FormattedTimeResponse, summary="Format current time"
)
router.add_api_route(
def format_current_time(data: FormatTimeInput) -> FormattedTimeResponse:
return TimeTool.format_current_time(data)
@router.post(
"/convert_time",
self.convert_time,
methods=["POST"],
response_model=ConvertedTimeResponse,
summary="Convert between timezones",
)
router.add_api_route(
def convert_time(data: ConvertTimeInput) -> ConvertedTimeResponse:
return TimeTool.convert_time(data)
@router.post(
"/elapsed_time",
self.elapsed_time,
methods=["POST"],
response_model=ElapsedTimeResponse,
summary="Time elapsed between timestamps",
)
router.add_api_route(
def elapsed_time(data: ElapsedTimeInput) -> ElapsedTimeResponse:
return TimeTool.elapsed_time(data)
@router.post(
"/parse_timestamp",
self.parse_timestamp,
methods=["POST"],
response_model=ParsedTimestampResponse,
summary="Parse and normalize timestamps",
)
router.add_api_route(
"/list_time_zones",
self.list_time_zones,
methods=["GET"],
summary="All valid time zones",
)
def parse_timestamp(data: ParseTimestampInput) -> ParsedTimestampResponse:
return TimeTool.parse_timestamp(data)
@router.get("/list_time_zones", summary="All valid time zones")
def list_time_zones() -> list[str]:
return TimeTool.list_time_zones()
return router

View file

@ -35,7 +35,7 @@ class WeatherTool(BaseTool):
response_model=WeatherForecastOutput,
summary="Get current weather and forecast",
)
def get_weather_forecast(
def forecast(
latitude: Annotated[
float | None, Query(description="Latitude for the location (e.g. 52.52)")
] = None,

View file

@ -29,7 +29,7 @@ class WebTool(BaseTool):
router = APIRouter()
@router.get("/web_read", response_model=WebResponse)
def web_read_get(
def read_get(
url: Annotated[HttpUrl | None, Query(description="URL to parse")] = None,
with_metadata: Annotated[bool, Query(description="Include metadata")] = True,
include_formatting: Annotated[bool, Query(description="Keep formatting")] = True,
@ -58,7 +58,7 @@ class WebTool(BaseTool):
)
@router.post("/web_read", response_model=WebResponse)
def web_read_post(request: WebRequest) -> WebResponse:
def read_post(request: WebRequest) -> WebResponse:
"""Read web page content via POST request.
Returns:
@ -74,7 +74,7 @@ class WebTool(BaseTool):
)
@router.get("/web_raw", response_model=WebRawResponse)
def web_raw(
def raw(
url: Annotated[
HttpUrl | None, Query(description="URL to fetch raw content and headers from")
] = None,