---
paths:
  - "django/**"
---
# AIService (Django-Ninja Backend)

## Important

NEVER start, restart, or manage the dev server (uvicorn, nohup, background processes). The developer will run services manually.

## Commands

```bash
uv sync                    # Install dependencies
uv run uvicorn aiservice.asgi:application --reload  # Dev server
uv run pytest              # Run all tests
uv run pytest tests/path/test_file.py::test_name -v  # Single test
uv run mypy .              # Type check
uv run ty check            # Type check (ty)
uv run ruff check .        # Lint
uv run ruff format .       # Format
```

## Architecture

- All endpoints are `async def` — runs under ASGI via uvicorn
- Django-Ninja with Pydantic schemas. APIs defined in `aiservice/urls.py`
- Use Pydantic `BaseModel` or `ninja.Schema` for all request/response types
- Use `aiservice/llm.py` for LLM calls — never call provider APIs directly
- Prompts stored as `.md` files alongside their modules
- Always use `libcst` for code transformation, never `ast` (preserves formatting)
- Use `asyncio.TaskGroup` for concurrent operations

## Multi-Language Handlers

`core/languages/` has per-language modules registering via `core/registry`. Routers in `core/shared/` dispatch by `language` field. To add a language: create `core/languages/<lang>/`, register in `__init__.py`, implement protocol methods.

## Gotchas

- No automatic exception handling — use `get_object_or_404` explicitly
- Auth: `HttpBearer` before `django_auth` to avoid CSRF errors
- Lazy imports in routers to avoid circular dependencies

## Testing

- Tests in `tests/` by feature: `optimizer/`, `testgen/`, `integration/`, `validators/`
- `@pytest.mark.asyncio` for async tests
- Factories: `create_optimizer_context()`, `create_refiner_context()`

## Style

- 120 char line length, Python 3.12+
- Minimal comments — explain "why" not "what"
- No docstrings unless requested
