@@ -52,16 +52,40 @@ async def lifespan(app: FastAPI):
5252
5353 yield
5454
55- app = FastAPI (lifespan = lifespan )
55+ app = FastAPI (
56+ lifespan = lifespan ,
57+ title = "PicoCode API" ,
58+ description = "Local Codebase Assistant with RAG (Retrieval-Augmented Generation). "
59+ "Index codebases, perform semantic search, and query with AI assistance." ,
60+ version = "0.2.0" ,
61+ docs_url = "/docs" ,
62+ redoc_url = "/redoc" ,
63+ openapi_tags = [
64+ {"name" : "projects" , "description" : "Project management operations" },
65+ {"name" : "indexing" , "description" : "Code indexing operations" },
66+ {"name" : "query" , "description" : "Semantic search and code queries" },
67+ {"name" : "health" , "description" : "Health and status checks" },
68+ ]
69+ )
5670templates = Jinja2Templates (directory = "templates" )
5771if os .path .isdir ("static" ):
5872 app .mount ("/static" , StaticFiles (directory = "static" ), name = "static" )
5973
6074
6175# Project Management API (PyCharm-compatible)
62- @app .post ("/api/projects" )
76+ @app .post ("/api/projects" , tags = [ "projects" ], summary = "Create or get a project" )
6377def api_create_project (request : CreateProjectRequest ):
64- """Create or get a project with per-project database."""
78+ """
79+ Create or get a project with per-project database.
80+
81+ - **path**: Absolute path to project directory (required)
82+ - **name**: Optional project name (defaults to directory name)
83+
84+ Returns project metadata including:
85+ - **id**: Unique project identifier
86+ - **database_path**: Path to project's SQLite database
87+ - **status**: Current project status
88+ """
6589
6690 try :
6791 # Validate input
@@ -83,9 +107,18 @@ def api_create_project(request: CreateProjectRequest):
83107 return JSONResponse ({"error" : "Internal server error" }, status_code = 500 )
84108
85109
86- @app .get ("/api/projects" )
110+ @app .get ("/api/projects" , tags = [ "projects" ], summary = "List all projects" )
87111def api_list_projects ():
88- """List all projects."""
112+ """
113+ List all registered projects.
114+
115+ Returns array of project objects with metadata:
116+ - **id**: Unique project identifier
117+ - **name**: Project name
118+ - **path**: Project directory path
119+ - **status**: Current status (created, indexing, ready, error)
120+ - **last_indexed_at**: Last indexing timestamp
121+ """
89122 try :
90123 projects = list_projects ()
91124 return JSONResponse (projects )
@@ -94,9 +127,15 @@ def api_list_projects():
94127 return JSONResponse ({"error" : "Failed to list projects" }, status_code = 500 )
95128
96129
97- @app .get ("/api/projects/{project_id}" )
130+ @app .get ("/api/projects/{project_id}" , tags = [ "projects" ], summary = "Get project by ID" )
98131def api_get_project (project_id : str ):
99- """Get project details by ID."""
132+ """
133+ Get project details by ID.
134+
135+ - **project_id**: Unique project identifier
136+
137+ Returns project metadata or 404 if not found.
138+ """
100139 try :
101140 project = get_project_by_id (project_id )
102141 if not project :
@@ -107,9 +146,16 @@ def api_get_project(project_id: str):
107146 return JSONResponse ({"error" : "Failed to retrieve project" }, status_code = 500 )
108147
109148
110- @app .delete ("/api/projects/{project_id}" )
149+ @app .delete ("/api/projects/{project_id}" , tags = [ "projects" ], summary = "Delete a project" )
111150def api_delete_project (project_id : str ):
112- """Delete a project and its database."""
151+ """
152+ Delete a project and its database.
153+
154+ - **project_id**: Unique project identifier
155+
156+ Permanently removes the project and all indexed data.
157+ Returns 404 if project not found.
158+ """
113159 try :
114160 delete_project (project_id )
115161 return JSONResponse ({"success" : True })
@@ -121,9 +167,23 @@ def api_delete_project(project_id: str):
121167 return JSONResponse ({"error" : "Failed to delete project" }, status_code = 500 )
122168
123169
124- @app .post ("/api/projects/index" )
170+ @app .post ("/api/projects/index" , tags = [ "indexing" ], summary = "Index a project" )
125171def api_index_project (http_request : Request , request : IndexProjectRequest , background_tasks : BackgroundTasks ):
126- """Index/re-index a project in the background."""
172+ """
173+ Index or re-index a project in the background.
174+
175+ - **project_id**: Unique project identifier
176+
177+ Starts background indexing process:
178+ - Scans project directory for code files
179+ - Generates embeddings for semantic search
180+ - Uses incremental indexing (skips unchanged files)
181+
182+ Rate limit: 10 requests per minute per IP.
183+
184+ Returns immediately with status "indexing".
185+ Poll project status to check completion.
186+ """
127187 # Rate limiting for indexing operations (more strict)
128188 client_ip = _get_client_ip (http_request )
129189 allowed , retry_after = indexing_limiter .is_allowed (client_ip )
@@ -167,9 +227,27 @@ def index_callback():
167227 return JSONResponse ({"error" : "Failed to start indexing" }, status_code = 500 )
168228
169229
170- @app .post ("/api/query" )
230+ @app .post ("/api/query" , tags = [ "query" ], summary = "Semantic search query" )
171231def api_query (http_request : Request , request : QueryRequest ):
172- """Query a project using semantic search (PyCharm-compatible)."""
232+ """
233+ Query a project using semantic search.
234+
235+ - **project_id**: Unique project identifier
236+ - **query**: Search query text
237+ - **top_k**: Number of results to return (default: 5, max: 20)
238+
239+ Performs semantic search using vector embeddings:
240+ - Generates embedding for query
241+ - Finds most similar code chunks
242+ - Returns ranked results with scores
243+
244+ Rate limit: 100 requests per minute per IP.
245+
246+ Returns:
247+ - **results**: Array of matching code chunks
248+ - **project_id**: Project identifier
249+ - **query**: Original query text
250+ """
173251 # Rate limiting
174252 client_ip = _get_client_ip (http_request )
175253 allowed , retry_after = query_limiter .is_allowed (client_ip )
@@ -206,13 +284,25 @@ def api_query(http_request: Request, request: QueryRequest):
206284
207285
208286
209- @app .get ("/api/health" )
287+ @app .get ("/api/health" , tags = [ "health" ], summary = "Health check" )
210288def api_health ():
211- """Health check endpoint."""
289+ """
290+ Health check endpoint for monitoring and status verification.
291+
292+ Returns:
293+ - **status**: "ok" if service is running
294+ - **version**: API version
295+ - **features**: List of enabled features
296+
297+ Use this endpoint for:
298+ - Load balancer health checks
299+ - Monitoring systems
300+ - Service availability verification
301+ """
212302 return JSONResponse ({
213303 "status" : "ok" ,
214304 "version" : "0.2.0" ,
215- "features" : ["rag" , "per-project-db" , "pycharm-api" ]
305+ "features" : ["rag" , "per-project-db" , "pycharm-api" , "incremental-indexing" , "rate-limiting" , "caching" ]
216306 })
217307
218308
0 commit comments