Self-hosted knowledge management for SMEs: a split-screen Markdown editor whose sections an LLM refines while you write, and RAG question answering over the documents that result. FastAPI + Postgres/pgvector on the back, SvelteKit on the front, everything OpenAI-compatible and self-hostable. Squashed into a single commit; the development history stays local. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CA43ZJda8Rbp2hKXNy8f6b
46 lines
1.5 KiB
Python
46 lines
1.5 KiB
Python
"""Reading templates. Any authenticated user: the picker needs them."""
|
|
|
|
import uuid
|
|
from typing import Annotated
|
|
|
|
from fastapi import Depends
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.api.templates.routing import reader_router
|
|
from app.api.templates.schemas import TemplateDetail, TemplateSummary
|
|
from app.api.templates.view import detail, summary
|
|
from app.auth.deps import get_current_user
|
|
from app.config import get_settings
|
|
from app.db import get_db
|
|
from app.errors import ApiError
|
|
from app.models import Template, User
|
|
|
|
router = reader_router()
|
|
|
|
|
|
@router.get("")
|
|
async def list_templates(
|
|
user: Annotated[User, Depends(get_current_user)],
|
|
db: Annotated[AsyncSession, Depends(get_db)],
|
|
) -> list[TemplateSummary]:
|
|
"""Templates the picker offers. Templates in the reader's language come
|
|
first — they are customer content, so a mismatched one is still listed
|
|
rather than hidden."""
|
|
rows = (await db.execute(select(Template).order_by(Template.name))).scalars().all()
|
|
wanted = user.locale or get_settings().default_locale
|
|
ordered = sorted(rows, key=lambda row: row.config.get("locale") != wanted)
|
|
return [summary(row) for row in ordered]
|
|
|
|
|
|
@router.get("/{template_id}")
|
|
async def get_template(
|
|
template_id: uuid.UUID,
|
|
user: Annotated[User, Depends(get_current_user)],
|
|
db: Annotated[AsyncSession, Depends(get_db)],
|
|
) -> TemplateDetail:
|
|
row = await db.get(Template, template_id)
|
|
if row is None:
|
|
raise ApiError(404, "Template not found.", "not_found")
|
|
return detail(row)
|