Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/perspicacite/mcp/usage_guide.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,30 @@
"when_to_use": "Ingest specific DOIs into a KB.",
"key_knobs": [],
},
{
"name": "ensure_kb",
"purpose": (
"Idempotently create and ingest a per-paper KB for a DOI, using the ASB "
"binder slug convention. Returns immediately if the KB already has chunks."
),
"when_to_use": (
"Before grounding questions against a single paper, to guarantee its KB "
"exists without re-ingesting it on every call."
),
"key_knobs": ["doi (required)", "mode — reserved, currently unused"],
},
{
"name": "ground_paper",
"purpose": (
"Answer a research question against one paper's dedicated KB, ensuring "
"that KB exists first (via ensure_kb)."
),
"when_to_use": (
"Ask a question of a specific paper by DOI in one call. Set tier='si' to "
"prefer evidence from the paper's supplementary information."
),
"key_knobs": ["doi (required)", "question (required)", "tier (paper|si) — default: paper"],
},
{
"name": "ingest_local_documents",
"purpose": "Ingest local files (PDF/text) into a KB.",
Expand Down
19 changes: 17 additions & 2 deletions tests/unit/test_web_app_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,27 @@ def _load_app():
return app


def _flatten_routes(routes):
"""Yield leaf routes, descending into routers wrapped by include_router.

FastAPI >= 0.139 no longer copies an included router's routes onto the app.
It appends one wrapper per include_router() call, exposing the router as
``original_router``. Older versions flatten, leaving nothing to descend into.
"""
for route in routes:
included_router = getattr(route, "original_router", None)
if included_router is None:
yield route
else:
yield from _flatten_routes(included_router.routes)


def _route_methods_by_path(app):
"""Return {path: {methods}} for every APIRoute on the app."""
"""Return {path: {methods}} for every APIRoute reachable from the app."""
from fastapi.routing import APIRoute

out: dict[str, set[str]] = {}
for r in app.routes:
for r in _flatten_routes(app.routes):
if isinstance(r, APIRoute):
out.setdefault(r.path, set()).update(r.methods or set())
else:
Expand Down
Loading