Skip to content

Commit 6fbc296

Browse files
authored
New swagger UI integration, improve frontend, remove repo_url from api error response, add api endpoints for ingestion and api config json, better docstring for endpoints, fix include/exclude frontend behavior, new download endpoint (#366)
1 parent 8445050 commit 6fbc296

File tree

12 files changed

+586
-413
lines changed

12 files changed

+586
-413
lines changed

src/server/main.py

Lines changed: 82 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,21 @@
66
from pathlib import Path
77

88
from dotenv import load_dotenv
9-
from fastapi import FastAPI
10-
from fastapi.responses import FileResponse, HTMLResponse
9+
from fastapi import FastAPI, Request
10+
from fastapi.responses import FileResponse, HTMLResponse, JSONResponse
1111
from fastapi.staticfiles import StaticFiles
1212
from slowapi.errors import RateLimitExceeded
1313
from starlette.middleware.trustedhost import TrustedHostMiddleware
1414

1515
from server.routers import dynamic, index, ingest
16+
from server.server_config import templates
1617
from server.server_utils import lifespan, limiter, rate_limit_exception_handler
1718

1819
# Load environment variables from .env file
1920
load_dotenv()
2021

2122
# Initialize the FastAPI application with lifespan
22-
app = FastAPI(lifespan=lifespan)
23+
app = FastAPI(lifespan=lifespan, docs_url=None, redoc_url=None)
2324
app.state.limiter = limiter
2425

2526
# Register the custom exception handler for rate limits
@@ -48,10 +49,9 @@
4849
async def health_check() -> dict[str, str]:
4950
"""Health check endpoint to verify that the server is running.
5051
51-
Returns
52-
-------
53-
dict[str, str]
54-
A JSON object with a "status" key indicating the server's health status.
52+
**Returns**
53+
54+
- **dict[str, str]**: A JSON object with a "status" key indicating the server's health status.
5555
5656
"""
5757
return {"status": "healthy"}
@@ -61,43 +61,103 @@ async def health_check() -> dict[str, str]:
6161
async def head_root() -> HTMLResponse:
6262
"""Respond to HTTP HEAD requests for the root URL.
6363
64-
Mirrors the headers and status code of the index page.
64+
**This endpoint mirrors the headers and status code of the index page**
65+
for HTTP HEAD requests, providing a lightweight way to check if the server
66+
is responding without downloading the full page content.
67+
68+
**Returns**
6569
66-
Returns
67-
-------
68-
HTMLResponse
69-
An empty HTML response with appropriate headers.
70+
- **HTMLResponse**: An empty HTML response with appropriate headers
7071
7172
"""
7273
return HTMLResponse(content=None, headers={"content-type": "text/html; charset=utf-8"})
7374

7475

7576
@app.get("/robots.txt", include_in_schema=False)
7677
async def robots() -> FileResponse:
77-
"""Serve the ``robots.txt`` file to guide search engine crawlers.
78+
"""Serve the robots.txt file to guide search engine crawlers.
79+
80+
**This endpoint serves the ``robots.txt`` file located in the static directory**
81+
to provide instructions to search engine crawlers about which parts of the site
82+
they should or should not index.
83+
84+
**Returns**
7885
79-
Returns
80-
-------
81-
FileResponse
82-
The ``robots.txt`` file located in the static directory.
86+
- **FileResponse**: The ``robots.txt`` file located in the static directory
8387
8488
"""
8589
return FileResponse("static/robots.txt")
8690

8791

8892
@app.get("/llms.txt")
8993
async def llm_txt() -> FileResponse:
90-
"""Serve the ``llms.txt`` file to provide information about the site to LLMs.
94+
"""Serve the llm.txt file to provide information about the site to LLMs.
9195
92-
Returns
93-
-------
94-
FileResponse
95-
The ``llms.txt`` file located in the static directory.
96+
**This endpoint serves the ``llms.txt`` file located in the static directory**
97+
to provide information about the site to Large Language Models (LLMs)
98+
and other AI systems that may be crawling the site.
99+
100+
**Returns**
101+
102+
- **FileResponse**: The ``llms.txt`` file located in the static directory
96103
97104
"""
98105
return FileResponse("static/llms.txt")
99106

100107

108+
@app.get("/docs", response_class=HTMLResponse, include_in_schema=False)
109+
async def custom_swagger_ui(request: Request) -> HTMLResponse:
110+
"""Serve custom Swagger UI documentation.
111+
112+
**This endpoint serves a custom Swagger UI interface**
113+
for the API documentation, providing an interactive way to explore
114+
and test the available endpoints.
115+
116+
**Parameters**
117+
118+
- **request** (`Request`): The incoming HTTP request
119+
120+
**Returns**
121+
122+
- **HTMLResponse**: Custom Swagger UI documentation page
123+
124+
"""
125+
return templates.TemplateResponse("swagger_ui.jinja", {"request": request})
126+
127+
128+
@app.get("/api", include_in_schema=True)
129+
def openapi_json_get() -> JSONResponse:
130+
"""Return the OpenAPI schema.
131+
132+
**This endpoint returns the OpenAPI schema (openapi.json)**
133+
that describes the API structure, endpoints, and data models
134+
for documentation and client generation purposes.
135+
136+
**Returns**
137+
138+
- **JSONResponse**: The OpenAPI schema as JSON
139+
140+
"""
141+
return JSONResponse(app.openapi())
142+
143+
144+
@app.api_route("/api", methods=["POST", "PUT", "DELETE", "OPTIONS", "HEAD"], include_in_schema=False)
145+
@app.api_route("/api/", methods=["GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD"], include_in_schema=False)
146+
def openapi_json() -> JSONResponse:
147+
"""Return the OpenAPI schema for various HTTP methods.
148+
149+
**This endpoint returns the OpenAPI schema (openapi.json)**
150+
for multiple HTTP methods, providing API documentation
151+
for clients that may use different request methods.
152+
153+
**Returns**
154+
155+
- **JSONResponse**: The OpenAPI schema as JSON
156+
157+
"""
158+
return JSONResponse(app.openapi())
159+
160+
101161
# Include routers for modular endpoints
102162
app.include_router(index)
103163
app.include_router(ingest)

src/server/models.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ class IngestSuccessResponse(BaseModel):
6969
Short form of repository URL (user/repo).
7070
summary : str
7171
Summary of the ingestion process including token estimates.
72+
ingest_id : str
73+
Ingestion id used to download full context.
7274
tree : str
7375
File tree structure of the repository.
7476
content : str
@@ -85,6 +87,7 @@ class IngestSuccessResponse(BaseModel):
8587
repo_url: str = Field(..., description="Original repository URL")
8688
short_repo_url: str = Field(..., description="Short repository URL (user/repo)")
8789
summary: str = Field(..., description="Ingestion summary with token estimates")
90+
ingest_id: str = Field(..., description="Ingestion id used to download full context")
8891
tree: str = Field(..., description="File tree structure")
8992
content: str = Field(..., description="Processed file content")
9093
default_max_file_size: int = Field(..., description="File size slider position used")
@@ -99,13 +102,10 @@ class IngestErrorResponse(BaseModel):
99102
----------
100103
error : str
101104
Error message describing what went wrong.
102-
repo_url : str
103-
The repository URL that failed to process.
104105
105106
"""
106107

107108
error: str = Field(..., description="Error message")
108-
repo_url: str = Field(..., description="Repository URL that failed")
109109

110110

111111
# Union type for API responses

src/server/query_processor.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ async def process_query(
9999
print(f"{Colors.BROWN}WARN{Colors.END}: {Colors.RED}<- {Colors.END}", end="")
100100
print(f"{Colors.RED}{exc}{Colors.END}")
101101

102-
return IngestErrorResponse(error=str(exc), repo_url=short_repo_url)
102+
return IngestErrorResponse(error=str(exc))
103103

104104
if len(content) > MAX_DISPLAY_SIZE:
105105
content = (
@@ -122,6 +122,7 @@ async def process_query(
122122
repo_url=input_text,
123123
short_repo_url=short_repo_url,
124124
summary=summary,
125+
ingest_id=query.id,
125126
tree=tree,
126127
content=content,
127128
default_max_file_size=slider_position,

src/server/routers/download.py

Lines changed: 0 additions & 49 deletions
This file was deleted.

0 commit comments

Comments
 (0)