|
| 1 | +# API Models Documentation |
| 2 | + |
| 3 | +This document describes the Pydantic models used for the `/api/ingest` endpoint in the Gitingest API. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +The `/api/ingest` endpoint uses structured Pydantic models for both input validation and response formatting. This ensures type safety, automatic validation, and consistent API responses. |
| 8 | + |
| 9 | +## Models |
| 10 | + |
| 11 | +### PatternType Enum |
| 12 | + |
| 13 | +```python |
| 14 | +class PatternType(str, Enum): |
| 15 | + INCLUDE = "include" |
| 16 | + EXCLUDE = "exclude" |
| 17 | +``` |
| 18 | + |
| 19 | +Defines the two types of file filtering patterns: |
| 20 | +- `INCLUDE`: Only include files matching the pattern |
| 21 | +- `EXCLUDE`: Exclude files matching the pattern |
| 22 | + |
| 23 | +### IngestRequest |
| 24 | + |
| 25 | +Input model for the `/api/ingest` endpoint. |
| 26 | + |
| 27 | +```python |
| 28 | +class IngestRequest(BaseModel): |
| 29 | + input_text: str = Field(..., description="Git repository URL or slug to ingest") |
| 30 | + max_file_size: int = Field(..., ge=0, le=500, description="File size slider position (0-500)") |
| 31 | + pattern_type: PatternType = Field(default=PatternType.EXCLUDE, description="Pattern type for file filtering") |
| 32 | + pattern: str = Field(default="", description="Glob/regex pattern for file filtering") |
| 33 | + token: str | None = Field(default=None, description="GitHub PAT for private repositories") |
| 34 | +``` |
| 35 | + |
| 36 | +**Validation Rules:** |
| 37 | +- `input_text`: Must not be empty (stripped of whitespace) |
| 38 | +- `max_file_size`: Must be between 0 and 500 (inclusive) |
| 39 | +- `pattern_type`: Defaults to "exclude" |
| 40 | +- `pattern`: Stripped of whitespace, defaults to empty string |
| 41 | +- `token`: Optional GitHub personal access token |
| 42 | + |
| 43 | +**Example:** |
| 44 | +```json |
| 45 | +{ |
| 46 | + "input_text": "https://github.com/cyclotruc/gitingest", |
| 47 | + "max_file_size": 243, |
| 48 | + "pattern_type": "exclude", |
| 49 | + "pattern": "*.md", |
| 50 | + "token": null |
| 51 | +} |
| 52 | +``` |
| 53 | + |
| 54 | +### IngestSuccessResponse |
| 55 | + |
| 56 | +Response model for successful ingestion operations. |
| 57 | + |
| 58 | +```python |
| 59 | +class IngestSuccessResponse(BaseModel): |
| 60 | + result: Literal[True] = True |
| 61 | + repo_url: str = Field(..., description="Original repository URL") |
| 62 | + short_repo_url: str = Field(..., description="Short repository URL (user/repo)") |
| 63 | + summary: str = Field(..., description="Ingestion summary with token estimates") |
| 64 | + tree: str = Field(..., description="File tree structure") |
| 65 | + content: str = Field(..., description="Processed file content") |
| 66 | + ingest_id: str = Field(..., description="Unique ingestion identifier") |
| 67 | + default_file_size: int = Field(..., description="File size slider position used") |
| 68 | + pattern_type: str = Field(..., description="Pattern type used") |
| 69 | + pattern: str = Field(..., description="Pattern used") |
| 70 | + token: str | None = Field(None, description="Token used (if any)") |
| 71 | +``` |
| 72 | + |
| 73 | +**Example:** |
| 74 | +```json |
| 75 | +{ |
| 76 | + "result": true, |
| 77 | + "repo_url": "https://github.com/cyclotruc/gitingest", |
| 78 | + "short_repo_url": "cyclotruc/gitingest", |
| 79 | + "summary": "Processed 50 files, estimated tokens: 15,000", |
| 80 | + "tree": "gitingest/\n├── src/\n│ ├── server/\n│ └── gitingest/\n└── README.md", |
| 81 | + "content": "Repository content here...", |
| 82 | + "ingest_id": "abc123", |
| 83 | + "default_file_size": 243, |
| 84 | + "pattern_type": "exclude", |
| 85 | + "pattern": "*.md", |
| 86 | + "token": null |
| 87 | +} |
| 88 | +``` |
| 89 | + |
| 90 | +### IngestErrorResponse |
| 91 | + |
| 92 | +Response model for failed ingestion operations. |
| 93 | + |
| 94 | +```python |
| 95 | +class IngestErrorResponse(BaseModel): |
| 96 | + error: str = Field(..., description="Error message") |
| 97 | + repo_url: str = Field(..., description="Repository URL that failed") |
| 98 | + default_file_size: int = Field(..., description="File size slider position used") |
| 99 | + pattern_type: str = Field(..., description="Pattern type used") |
| 100 | + pattern: str = Field(..., description="Pattern used") |
| 101 | + token: str | None = Field(None, description="Token used (if any)") |
| 102 | +``` |
| 103 | + |
| 104 | +**Example:** |
| 105 | +```json |
| 106 | +{ |
| 107 | + "error": "Repository not found or is private", |
| 108 | + "repo_url": "https://github.com/private/repo", |
| 109 | + "default_file_size": 243, |
| 110 | + "pattern_type": "exclude", |
| 111 | + "pattern": "", |
| 112 | + "token": null |
| 113 | +} |
| 114 | +``` |
| 115 | + |
| 116 | +### IngestResponse |
| 117 | + |
| 118 | +Union type for API responses. |
| 119 | + |
| 120 | +```python |
| 121 | +IngestResponse = Union[IngestSuccessResponse, IngestErrorResponse] |
| 122 | +``` |
| 123 | + |
| 124 | +This allows the endpoint to return either a success or error response with proper typing. |
| 125 | + |
| 126 | +## Usage in FastAPI |
| 127 | + |
| 128 | +The models are used in the `/api/ingest` endpoint as follows: |
| 129 | + |
| 130 | +```python |
| 131 | +@router.post("/api/ingest", |
| 132 | + response_model=IngestResponse, |
| 133 | + responses={ |
| 134 | + 200: {"model": IngestSuccessResponse, "description": "Successful ingestion"}, |
| 135 | + 400: {"model": IngestErrorResponse, "description": "Bad request or processing error"}, |
| 136 | + 500: {"model": IngestErrorResponse, "description": "Internal server error"} |
| 137 | + }) |
| 138 | +async def api_ingest( |
| 139 | + request: Request, |
| 140 | + input_text: str = Form(...), |
| 141 | + max_file_size: int = Form(...), |
| 142 | + pattern_type: str = Form("exclude"), |
| 143 | + pattern: str = Form(""), |
| 144 | + token: Optional[str] = Form(None), |
| 145 | +) -> IngestResponse: |
| 146 | + # Implementation... |
| 147 | +``` |
| 148 | + |
| 149 | +## Benefits |
| 150 | + |
| 151 | +1. **Type Safety**: All inputs and outputs are properly typed |
| 152 | +2. **Automatic Validation**: Pydantic validates all inputs according to defined rules |
| 153 | +3. **API Documentation**: FastAPI automatically generates OpenAPI documentation |
| 154 | +4. **Consistent Responses**: Structured error and success responses |
| 155 | +5. **IDE Support**: Better autocomplete and error detection in IDEs |
| 156 | + |
| 157 | +## Error Handling |
| 158 | + |
| 159 | +The models provide structured error handling: |
| 160 | + |
| 161 | +- **Validation Errors**: Invalid input parameters are caught and returned as `IngestErrorResponse` |
| 162 | +- **Processing Errors**: Repository processing failures return detailed error information |
| 163 | +- **Unexpected Errors**: Internal server errors are caught and formatted consistently |
| 164 | + |
| 165 | +## Migration from Previous Implementation |
| 166 | + |
| 167 | +The previous implementation used raw dictionaries and manual JSON responses. The new models provide: |
| 168 | + |
| 169 | +- Better type safety |
| 170 | +- Automatic validation |
| 171 | +- Consistent error handling |
| 172 | +- Improved API documentation |
| 173 | +- Better developer experience |
0 commit comments